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)
7 DS390 adaptation by Kevin Vigor <kevin@vigor.nu>
9 This program is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 In other words, you are welcome to use, share and improve this program.
24 You are forbidden to forbid anyone else to use, share and improve
25 what you give them. Help stamp out software-hoarding!
26 -------------------------------------------------------------------------*/
36 #include "SDCCglobl.h"
39 #ifdef HAVE_SYS_ISA_DEFS_H
40 #include <sys/isa_defs.h>
42 #ifdef HAVE_MACHINE_ENDIAN_H
43 #include <machine/endian.h>
48 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
49 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
50 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
56 #define BETTER_LITERAL_SHIFT
58 char *aopLiteral (value * val, int offset);
60 /* this is the down and dirty file with all kinds of
61 kludgy & hacky stuff. This is what it is all about
62 CODE GENERATION for a specific MCU . some of the
63 routines may be reusable, will have to see */
65 static char *zero = "#0x00";
66 static char *one = "#0x01";
71 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
72 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
74 unsigned fReturnSizeDS390 = 5; /* shared with ralloc.c */
75 static char *fReturn24[] =
76 {"dpl", "dph", "dpx", "b", "a"};
77 static char *fReturn16[] =
78 {"dpl", "dph", "b", "a"};
79 static char **fReturn = fReturn24;
80 static char *accUse[] =
83 static short rbank = -1;
97 static void saveRBank (int, iCode *, bool);
99 #define RESULTONSTACK(x) \
100 (IC_RESULT(x) && IC_RESULT(x)->aop && \
101 IC_RESULT(x)->aop->type == AOP_STK )
103 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
104 #define MOVA(x) { char *_mova_tmp = strdup(x); \
105 if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
107 emitcode("mov","a,%s",_mova_tmp); \
111 #define CLRC emitcode("clr","c")
112 #define SETC emitcode("setb","c")
114 // A scratch register which will be used to hold
115 // result bytes from operands in far space via DPTR2.
116 #define DP2_RESULT_REG "ap"
118 static lineNode *lineHead = NULL;
119 static lineNode *lineCurr = NULL;
121 static unsigned char SLMask[] =
122 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
123 0xE0, 0xC0, 0x80, 0x00};
124 static unsigned char SRMask[] =
125 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
126 0x07, 0x03, 0x01, 0x00};
133 /*-----------------------------------------------------------------*/
134 /* emitcode - writes the code into a file : for now it is simple */
135 /*-----------------------------------------------------------------*/
137 emitcode (char *inst, char *fmt,...)
140 char lb[INITIAL_INLINEASM];
148 sprintf (lb, "%s\t", inst);
150 sprintf (lb, "%s", inst);
151 vsprintf (lb + (strlen (lb)), fmt, ap);
154 vsprintf (lb, fmt, ap);
156 while (isspace (*lbp))
160 lineCurr = (lineCurr ?
161 connectLine (lineCurr, newLineNode (lb)) :
162 (lineHead = newLineNode (lb)));
163 lineCurr->isInline = _G.inLine;
164 lineCurr->isDebug = _G.debugLine;
168 /*-----------------------------------------------------------------*/
169 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
170 /*-----------------------------------------------------------------*/
172 getFreePtr (iCode * ic, asmop ** aopp, bool result)
174 bool r0iu = FALSE, r1iu = FALSE;
175 bool r0ou = FALSE, r1ou = FALSE;
177 /* the logic: if r0 & r1 used in the instruction
178 then we are in trouble otherwise */
180 /* first check if r0 & r1 are used by this
181 instruction, in which case we are in trouble */
182 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
183 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
188 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
189 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
191 /* if no usage of r0 then return it */
194 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
195 (*aopp)->type = AOP_R0;
197 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
200 /* if no usage of r1 then return it */
203 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
204 (*aopp)->type = AOP_R1;
206 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
209 /* now we know they both have usage */
210 /* if r0 not used in this instruction */
213 /* push it if not already pushed */
216 emitcode ("push", "%s",
217 ds390_regWithIdx (R0_IDX)->dname);
221 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
222 (*aopp)->type = AOP_R0;
224 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
227 /* if r1 not used then */
231 /* push it if not already pushed */
234 emitcode ("push", "%s",
235 ds390_regWithIdx (R1_IDX)->dname);
239 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
240 (*aopp)->type = AOP_R1;
241 return ds390_regWithIdx (R1_IDX);
245 /* I said end of world but not quite end of world yet */
246 /* if this is a result then we can push it on the stack */
249 (*aopp)->type = AOP_STK;
253 /* other wise this is true end of the world */
254 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
255 "getFreePtr should never reach here");
259 /*-----------------------------------------------------------------*/
260 /* newAsmop - creates a new asmOp */
261 /*-----------------------------------------------------------------*/
263 newAsmop (short type)
267 aop = Safe_calloc (1, sizeof (asmop));
272 static int _currentDPS; /* Current processor DPS. */
273 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
274 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
276 /*-----------------------------------------------------------------*/
277 /* genSetDPTR: generate code to select which DPTR is in use (zero */
278 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
279 /* alternate DPTR (DPL1/DPH1/DPX1). */
280 /*-----------------------------------------------------------------*/
285 /* If we are doing lazy evaluation, simply note the desired
286 * change, but don't emit any code yet.
296 emitcode ("mov", "dps, #0x00");
301 emitcode ("mov", "dps, #0x01");
305 /*-----------------------------------------------------------------*/
306 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
308 /* Any code that operates on DPTR (NB: not on the individual */
309 /* components, like DPH) *must* call _flushLazyDPS() before using */
310 /* DPTR within a lazy DPS evaluation block. */
312 /* Note that aopPut and aopGet already contain the proper calls to */
313 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
314 /* DPS evaluation block. */
316 /* Also, _flushLazyDPS must be called before any flow control */
317 /* operations that could potentially branch out of the block. */
319 /* Lazy DPS evaluation is simply an optimization (though an */
320 /* important one), so if in doubt, leave it out. */
321 /*-----------------------------------------------------------------*/
323 _startLazyDPSEvaluation (void)
327 #ifdef BETTER_LITERAL_SHIFT
334 /*-----------------------------------------------------------------*/
335 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
336 /* desired one. Call before using DPTR within a lazy DPS evaluation */
338 /*-----------------------------------------------------------------*/
348 if (_desiredDPS != _currentDPS)
352 emitcode ("inc", "dps");
356 emitcode ("dec", "dps");
358 _currentDPS = _desiredDPS;
362 /*-----------------------------------------------------------------*/
363 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
365 /* Forces us back to the safe state (standard DPTR selected). */
366 /*-----------------------------------------------------------------*/
368 _endLazyDPSEvaluation (void)
370 #ifdef BETTER_LITERAL_SHIFT
389 /*-----------------------------------------------------------------*/
390 /* pointerCode - returns the code for a pointer type */
391 /*-----------------------------------------------------------------*/
393 pointerCode (sym_link * etype)
396 return PTR_TYPE (SPEC_OCLS (etype));
400 /*-----------------------------------------------------------------*/
401 /* aopForSym - for a true symbol */
402 /*-----------------------------------------------------------------*/
404 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
407 memmap *space = SPEC_OCLS (sym->etype);
409 /* if already has one */
413 /* assign depending on the storage class */
414 /* if it is on the stack or indirectly addressable */
415 /* space we need to assign either r0 or r1 to it */
416 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
418 sym->aop = aop = newAsmop (0);
419 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
420 aop->size = getSize (sym->type);
422 /* now assign the address of the variable to
423 the pointer register */
424 if (aop->type != AOP_STK)
430 emitcode ("push", "acc");
432 emitcode ("mov", "a,_bp");
433 emitcode ("add", "a,#0x%02x",
435 ((char) (sym->stack - _G.nRegsSaved)) :
436 ((char) sym->stack)) & 0xff);
437 emitcode ("mov", "%s,a",
438 aop->aopu.aop_ptr->name);
441 emitcode ("pop", "acc");
444 emitcode ("mov", "%s,#%s",
445 aop->aopu.aop_ptr->name,
447 aop->paged = space->paged;
450 aop->aopu.aop_stk = sym->stack;
454 if (sym->onStack && options.stack10bit)
456 /* It's on the 10 bit stack, which is located in
461 emitcode ("push", "acc");
463 emitcode ("mov", "a,_bp");
464 emitcode ("add", "a,#0x%02x",
466 ((char) (sym->stack - _G.nRegsSaved)) :
467 ((char) sym->stack)) & 0xff);
471 if (options.model == MODEL_FLAT24)
472 emitcode ("mov", "dpx1,#0x40");
474 emitcode ("mov", "dph1,#0x00");
475 emitcode ("mov", "dpl1, a");
479 if (options.model == MODEL_FLAT24)
480 emitcode ("mov", "dpx,#0x40");
481 emitcode ("mov", "dph,#0x00");
482 emitcode ("mov", "dpl, a");
486 emitcode ("pop", "acc");
488 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
489 aop->size = getSize (sym->type);
493 /* if in bit space */
494 if (IN_BITSPACE (space))
496 sym->aop = aop = newAsmop (AOP_CRY);
497 aop->aopu.aop_dir = sym->rname;
498 aop->size = getSize (sym->type);
501 /* if it is in direct space */
502 if (IN_DIRSPACE (space))
504 sym->aop = aop = newAsmop (AOP_DIR);
505 aop->aopu.aop_dir = sym->rname;
506 aop->size = getSize (sym->type);
510 /* special case for a function */
511 if (IS_FUNC (sym->type))
513 sym->aop = aop = newAsmop (AOP_IMMD);
514 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
515 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
516 aop->size = FPTRSIZE;
520 /* only remaining is far space */
521 /* in which case DPTR gets the address */
522 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
527 emitcode ("mov", "dptr,#%s", sym->rname);
532 emitcode ("mov", "dptr,#%s", sym->rname);
534 aop->size = getSize (sym->type);
536 /* if it is in code space */
537 if (IN_CODESPACE (space))
543 /*-----------------------------------------------------------------*/
544 /* aopForRemat - rematerialzes an object */
545 /*-----------------------------------------------------------------*/
547 aopForRemat (symbol * sym)
549 iCode *ic = sym->rematiCode;
550 asmop *aop = newAsmop (AOP_IMMD);
557 val += (int) operandLitValue (IC_RIGHT (ic));
558 else if (ic->op == '-')
559 val -= (int) operandLitValue (IC_RIGHT (ic));
560 else if (IS_CAST_ICODE(ic)) {
561 sym_link *from_type = operandType(IC_RIGHT(ic));
562 aop->aopu.aop_immd.from_cast_remat = 1;
563 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
564 ptr_type = DCL_TYPE(from_type);
568 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
572 sprintf (buffer, "(%s %c 0x%04x)",
573 OP_SYMBOL (IC_LEFT (ic))->rname,
574 val >= 0 ? '+' : '-',
577 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
579 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
580 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
581 /* set immd2 field if required */
582 if (aop->aopu.aop_immd.from_cast_remat) {
583 sprintf(buffer,"#0x%02x",ptr_type);
584 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
585 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
591 /*-----------------------------------------------------------------*/
592 /* regsInCommon - two operands have some registers in common */
593 /*-----------------------------------------------------------------*/
595 regsInCommon (operand * op1, operand * op2)
600 /* if they have registers in common */
601 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
604 sym1 = OP_SYMBOL (op1);
605 sym2 = OP_SYMBOL (op2);
607 if (sym1->nRegs == 0 || sym2->nRegs == 0)
610 for (i = 0; i < sym1->nRegs; i++)
616 for (j = 0; j < sym2->nRegs; j++)
621 if (sym2->regs[j] == sym1->regs[i])
629 /*-----------------------------------------------------------------*/
630 /* operandsEqu - equivalent */
631 /*-----------------------------------------------------------------*/
633 operandsEqu (operand * op1, operand * op2)
637 /* if they not symbols */
638 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
641 sym1 = OP_SYMBOL (op1);
642 sym2 = OP_SYMBOL (op2);
644 /* if both are itemps & one is spilt
645 and the other is not then false */
646 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
647 sym1->isspilt != sym2->isspilt)
650 /* if they are the same */
654 if (strcmp (sym1->rname, sym2->rname) == 0)
658 /* if left is a tmp & right is not */
659 if (IS_ITEMP (op1) &&
662 (sym1->usl.spillLoc == sym2))
665 if (IS_ITEMP (op2) &&
669 (sym2->usl.spillLoc == sym1))
675 /*-----------------------------------------------------------------*/
676 /* sameRegs - two asmops have the same registers */
677 /*-----------------------------------------------------------------*/
679 sameRegs (asmop * aop1, asmop * aop2)
685 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
692 if (aop1->type != AOP_REG ||
693 aop2->type != AOP_REG)
696 if (aop1->size != aop2->size)
699 for (i = 0; i < aop1->size; i++)
700 if (aop1->aopu.aop_reg[i] !=
701 aop2->aopu.aop_reg[i])
707 /*-----------------------------------------------------------------*/
708 /* aopOp - allocates an asmop for an operand : */
709 /*-----------------------------------------------------------------*/
711 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
720 /* if this a literal */
721 if (IS_OP_LITERAL (op))
723 op->aop = aop = newAsmop (AOP_LIT);
724 aop->aopu.aop_lit = op->operand.valOperand;
725 aop->size = getSize (operandType (op));
729 /* if already has a asmop then continue */
733 /* if the underlying symbol has a aop */
734 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
736 op->aop = OP_SYMBOL (op)->aop;
740 /* if this is a true symbol */
741 if (IS_TRUE_SYMOP (op))
743 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
747 /* this is a temporary : this has
753 e) can be a return use only */
755 sym = OP_SYMBOL (op);
758 /* if the type is a conditional */
759 if (sym->regType == REG_CND)
761 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
766 /* if it is spilt then two situations
768 b) has a spill location */
769 if (sym->isspilt || sym->nRegs == 0)
772 /* rematerialize it NOW */
775 sym->aop = op->aop = aop =
777 aop->size = getSize (sym->type);
784 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
785 aop->size = getSize (sym->type);
786 for (i = 0; i < 2; i++)
787 aop->aopu.aop_str[i] = accUse[i];
797 /* a AOP_STR uses DPTR, but DPTR is already in use;
800 fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use!\n");
803 aop = op->aop = sym->aop = newAsmop (AOP_STR);
804 aop->size = getSize (sym->type);
805 for (i = 0; i < (int) fReturnSizeDS390; i++)
806 aop->aopu.aop_str[i] = fReturn[i];
810 /* else spill location */
811 sym->aop = op->aop = aop =
812 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
813 aop->size = getSize (sym->type);
817 /* must be in a register */
818 sym->aop = op->aop = aop = newAsmop (AOP_REG);
819 aop->size = sym->nRegs;
820 for (i = 0; i < sym->nRegs; i++)
821 aop->aopu.aop_reg[i] = sym->regs[i];
824 /*-----------------------------------------------------------------*/
825 /* freeAsmop - free up the asmop given to an operand */
826 /*----------------------------------------------------------------*/
828 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
845 /* depending on the asmop type only three cases need work AOP_RO
846 , AOP_R1 && AOP_STK */
854 emitcode ("pop", "ar0");
858 bitVectUnSetBit (ic->rUsed, R0_IDX);
866 emitcode ("pop", "ar1");
870 bitVectUnSetBit (ic->rUsed, R1_IDX);
876 int stk = aop->aopu.aop_stk + aop->size;
877 bitVectUnSetBit (ic->rUsed, R0_IDX);
878 bitVectUnSetBit (ic->rUsed, R1_IDX);
880 getFreePtr (ic, &aop, FALSE);
882 if (options.stack10bit)
884 /* I'm not sure what to do here yet... */
887 "*** Warning: probably generating bad code for "
888 "10 bit stack mode.\n");
893 emitcode ("mov", "a,_bp");
894 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
895 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
899 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
904 emitcode ("pop", "acc");
905 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
908 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
911 freeAsmop (op, NULL, ic, TRUE);
914 emitcode ("pop", "ar0");
920 emitcode ("pop", "ar1");
927 /* all other cases just dealloc */
933 OP_SYMBOL (op)->aop = NULL;
934 /* if the symbol has a spill */
936 SPIL_LOC (op)->aop = NULL;
941 /*------------------------------------------------------------------*/
942 /* aopGet - for fetching value of the aop */
944 /* Set canClobberACC if you are sure it is OK to clobber the value */
945 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
946 /* just less efficient. */
947 /*------------------------------------------------------------------*/
959 /* offset is greater than
961 if (offset > (aop->size - 1) &&
962 aop->type != AOP_LIT)
965 /* depending on type */
971 /* if we need to increment it */
972 while (offset > aop->coff)
974 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
978 while (offset < aop->coff)
980 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
987 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
988 return (dname ? "acc" : "a");
990 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
991 rs = Safe_calloc (1, strlen (s) + 1);
998 if (aop->type == AOP_DPTR2)
1004 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1010 while (offset > aop->coff)
1012 emitcode ("inc", "dptr");
1016 while (offset < aop->coff)
1018 emitcode ("lcall", "__decdptr");
1025 emitcode ("clr", "a");
1026 emitcode ("movc", "a,@a+dptr");
1030 emitcode ("movx", "a,@dptr");
1033 if (aop->type == AOP_DPTR2)
1039 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1040 return DP2_RESULT_REG;
1043 return (dname ? "acc" : "a");
1046 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1047 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1049 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1051 sprintf (s, "#(%s >> %d)",
1052 aop->aopu.aop_immd.aop_immd1,
1056 aop->aopu.aop_immd.aop_immd1);
1057 rs = Safe_calloc (1, strlen (s) + 1);
1063 sprintf (s, "(%s + %d)",
1067 sprintf (s, "%s", aop->aopu.aop_dir);
1068 rs = Safe_calloc (1, strlen (s) + 1);
1074 return aop->aopu.aop_reg[offset]->dname;
1076 return aop->aopu.aop_reg[offset]->name;
1079 emitcode ("clr", "a");
1080 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1081 emitcode ("rlc", "a");
1082 return (dname ? "acc" : "a");
1085 if (!offset && dname)
1087 return aop->aopu.aop_str[offset];
1090 return aopLiteral (aop->aopu.aop_lit, offset);
1094 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1098 return aop->aopu.aop_str[offset];
1102 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1103 "aopget got unsupported aop->type");
1106 /*-----------------------------------------------------------------*/
1107 /* aopPut - puts a string for a aop */
1108 /*-----------------------------------------------------------------*/
1110 aopPut (asmop * aop, char *s, int offset)
1114 if (aop->size && offset > (aop->size - 1))
1116 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1117 "aopPut got offset > aop->size");
1121 /* will assign value to value */
1122 /* depending on where it is ofcourse */
1127 sprintf (d, "(%s + %d)",
1128 aop->aopu.aop_dir, offset);
1130 sprintf (d, "%s", aop->aopu.aop_dir);
1133 emitcode ("mov", "%s,%s", d, s);
1138 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1139 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1142 strcmp (s, "r0") == 0 ||
1143 strcmp (s, "r1") == 0 ||
1144 strcmp (s, "r2") == 0 ||
1145 strcmp (s, "r3") == 0 ||
1146 strcmp (s, "r4") == 0 ||
1147 strcmp (s, "r5") == 0 ||
1148 strcmp (s, "r6") == 0 ||
1149 strcmp (s, "r7") == 0)
1150 emitcode ("mov", "%s,%s",
1151 aop->aopu.aop_reg[offset]->dname, s);
1153 emitcode ("mov", "%s,%s",
1154 aop->aopu.aop_reg[offset]->name, s);
1161 if (aop->type == AOP_DPTR2)
1169 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1170 "aopPut writting to code space");
1174 while (offset > aop->coff)
1177 emitcode ("inc", "dptr");
1180 while (offset < aop->coff)
1183 emitcode ("lcall", "__decdptr");
1188 /* if not in accumulater */
1191 emitcode ("movx", "@dptr,a");
1193 if (aop->type == AOP_DPTR2)
1201 while (offset > aop->coff)
1204 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1206 while (offset < aop->coff)
1209 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1216 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1222 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1224 else if (strcmp (s, "r0") == 0 ||
1225 strcmp (s, "r1") == 0 ||
1226 strcmp (s, "r2") == 0 ||
1227 strcmp (s, "r3") == 0 ||
1228 strcmp (s, "r4") == 0 ||
1229 strcmp (s, "r5") == 0 ||
1230 strcmp (s, "r6") == 0 ||
1231 strcmp (s, "r7") == 0)
1234 sprintf (buffer, "a%s", s);
1235 emitcode ("mov", "@%s,%s",
1236 aop->aopu.aop_ptr->name, buffer);
1239 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1244 if (strcmp (s, "a") == 0)
1245 emitcode ("push", "acc");
1247 emitcode ("push", "%s", s);
1252 /* if bit variable */
1253 if (!aop->aopu.aop_dir)
1255 emitcode ("clr", "a");
1256 emitcode ("rlc", "a");
1261 emitcode ("clr", "%s", aop->aopu.aop_dir);
1263 emitcode ("setb", "%s", aop->aopu.aop_dir);
1264 else if (!strcmp (s, "c"))
1265 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1268 if (strcmp (s, "a"))
1273 symbol *lbl = newiTempLabel (NULL);
1274 emitcode ("clr", "c");
1275 emitcode ("jz", "%05d$", lbl->key + 100);
1276 emitcode ("cpl", "c");
1277 emitcode ("", "%05d$:", lbl->key + 100);
1278 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1286 if (strcmp (aop->aopu.aop_str[offset], s))
1287 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1292 if (!offset && (strcmp (s, "acc") == 0))
1295 if (strcmp (aop->aopu.aop_str[offset], s))
1296 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1300 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1301 "aopPut got unsupported aop->type");
1308 /*--------------------------------------------------------------------*/
1309 /* reAdjustPreg - points a register back to where it should (coff==0) */
1310 /*--------------------------------------------------------------------*/
1312 reAdjustPreg (asmop * aop)
1314 if ((aop->coff==0) || (aop->size <= 1)) {
1323 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1327 if (aop->type == AOP_DPTR2)
1334 emitcode ("lcall", "__decdptr");
1337 if (aop->type == AOP_DPTR2)
1347 #define AOP(op) op->aop
1348 #define AOP_TYPE(op) AOP(op)->type
1349 #define AOP_SIZE(op) AOP(op)->size
1350 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1351 AOP_TYPE(x) == AOP_R0))
1353 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1354 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1357 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1358 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1359 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1361 /* Workaround for DS80C390 bug: div ab may return bogus results
1362 * if A is accessed in instruction immediately before the div.
1364 * Will be fixed in B4 rev of processor, Dallas claims.
1367 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1368 if (!AOP_NEEDSACC(RIGHT)) \
1370 /* We can load A first, then B, since \
1371 * B (the RIGHT operand) won't clobber A, \
1372 * thus avoiding touching A right before the div. \
1374 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1375 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1377 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1381 /* Just stuff in a nop after loading A. */ \
1382 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1383 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1385 emitcode("nop", "; workaround for DS80C390 div bug."); \
1388 /*-----------------------------------------------------------------*/
1389 /* genNotFloat - generates not for float operations */
1390 /*-----------------------------------------------------------------*/
1392 genNotFloat (operand * op, operand * res)
1398 D (emitcode (";", "genNotFloat ");
1401 /* we will put 127 in the first byte of
1403 aopPut (AOP (res), "#127", 0);
1404 size = AOP_SIZE (op) - 1;
1407 _startLazyDPSEvaluation ();
1408 l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1413 emitcode ("orl", "a,%s",
1415 offset++, FALSE, FALSE, FALSE));
1417 _endLazyDPSEvaluation ();
1419 tlbl = newiTempLabel (NULL);
1420 aopPut (res->aop, one, 1);
1421 emitcode ("jz", "%05d$", (tlbl->key + 100));
1422 aopPut (res->aop, zero, 1);
1423 emitcode ("", "%05d$:", (tlbl->key + 100));
1425 size = res->aop->size - 2;
1427 /* put zeros in the rest */
1429 aopPut (res->aop, zero, offset++);
1432 /*-----------------------------------------------------------------*/
1433 /* opIsGptr: returns non-zero if the passed operand is */
1434 /* a generic pointer type. */
1435 /*-----------------------------------------------------------------*/
1437 opIsGptr (operand * op)
1439 sym_link *type = operandType (op);
1441 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1448 /*-----------------------------------------------------------------*/
1449 /* getDataSize - get the operand data size */
1450 /*-----------------------------------------------------------------*/
1452 getDataSize (operand * op)
1455 size = AOP_SIZE (op);
1456 if (size == GPTRSIZE)
1458 sym_link *type = operandType (op);
1459 if (IS_GENPTR (type))
1461 /* generic pointer; arithmetic operations
1462 * should ignore the high byte (pointer type).
1470 /*-----------------------------------------------------------------*/
1471 /* outAcc - output Acc */
1472 /*-----------------------------------------------------------------*/
1474 outAcc (operand * result)
1477 size = getDataSize (result);
1480 aopPut (AOP (result), "a", 0);
1483 /* unsigned or positive */
1486 aopPut (AOP (result), zero, offset++);
1491 /*-----------------------------------------------------------------*/
1492 /* outBitC - output a bit C */
1493 /*-----------------------------------------------------------------*/
1495 outBitC (operand * result)
1497 /* if the result is bit */
1498 if (AOP_TYPE (result) == AOP_CRY)
1500 aopPut (AOP (result), "c", 0);
1504 emitcode ("clr", "a");
1505 emitcode ("rlc", "a");
1510 /*-----------------------------------------------------------------*/
1511 /* toBoolean - emit code for orl a,operator(sizeop) */
1512 /*-----------------------------------------------------------------*/
1514 toBoolean (operand * oper)
1516 int size = AOP_SIZE (oper) - 1;
1520 /* The generic part of a generic pointer should
1521 * not participate in it's truth value.
1523 * i.e. 0x10000000 is zero.
1525 if (opIsGptr (oper))
1527 D (emitcode (";", "toBoolean: generic ptr special case.");
1532 _startLazyDPSEvaluation ();
1533 if (AOP_NEEDSACC (oper) && size)
1536 emitcode ("push", "b");
1537 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1541 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1547 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1551 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1554 _endLazyDPSEvaluation ();
1558 emitcode ("mov", "a,b");
1559 emitcode ("pop", "b");
1564 /*-----------------------------------------------------------------*/
1565 /* genNot - generate code for ! operation */
1566 /*-----------------------------------------------------------------*/
1571 sym_link *optype = operandType (IC_LEFT (ic));
1573 D (emitcode (";", "genNot ");
1576 /* assign asmOps to operand & result */
1577 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1578 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1580 /* if in bit space then a special case */
1581 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1583 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1584 emitcode ("cpl", "c");
1585 outBitC (IC_RESULT (ic));
1589 /* if type float then do float */
1590 if (IS_FLOAT (optype))
1592 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1596 toBoolean (IC_LEFT (ic));
1598 tlbl = newiTempLabel (NULL);
1599 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1600 emitcode ("", "%05d$:", tlbl->key + 100);
1601 outBitC (IC_RESULT (ic));
1604 /* release the aops */
1605 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1606 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1610 /*-----------------------------------------------------------------*/
1611 /* genCpl - generate code for complement */
1612 /*-----------------------------------------------------------------*/
1619 D (emitcode (";", "genCpl ");
1623 /* assign asmOps to operand & result */
1624 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1625 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1627 /* if both are in bit space then
1629 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1630 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1633 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1634 emitcode ("cpl", "c");
1635 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1639 size = AOP_SIZE (IC_RESULT (ic));
1640 _startLazyDPSEvaluation ();
1643 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1645 emitcode ("cpl", "a");
1646 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1648 _endLazyDPSEvaluation ();
1652 /* release the aops */
1653 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1654 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1657 /*-----------------------------------------------------------------*/
1658 /* genUminusFloat - unary minus for floating points */
1659 /*-----------------------------------------------------------------*/
1661 genUminusFloat (operand * op, operand * result)
1663 int size, offset = 0;
1665 /* for this we just need to flip the
1666 first it then copy the rest in place */
1667 D (emitcode (";", "genUminusFloat");
1670 _startLazyDPSEvaluation ();
1671 size = AOP_SIZE (op) - 1;
1672 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1675 emitcode ("cpl", "acc.7");
1676 aopPut (AOP (result), "a", 3);
1680 aopPut (AOP (result),
1681 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1685 _endLazyDPSEvaluation ();
1688 /*-----------------------------------------------------------------*/
1689 /* genUminus - unary minus code generation */
1690 /*-----------------------------------------------------------------*/
1692 genUminus (iCode * ic)
1695 sym_link *optype, *rtype;
1697 D (emitcode (";", "genUminus ");
1702 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1703 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1705 /* if both in bit space then special
1707 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1708 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1711 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1712 emitcode ("cpl", "c");
1713 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1717 optype = operandType (IC_LEFT (ic));
1718 rtype = operandType (IC_RESULT (ic));
1720 /* if float then do float stuff */
1721 if (IS_FLOAT (optype))
1723 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1727 /* otherwise subtract from zero */
1728 size = AOP_SIZE (IC_LEFT (ic));
1730 _startLazyDPSEvaluation ();
1733 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1734 if (!strcmp (l, "a"))
1738 emitcode ("cpl", "a");
1739 emitcode ("addc", "a,#0");
1745 emitcode ("clr", "a");
1746 emitcode ("subb", "a,%s", l);
1748 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1750 _endLazyDPSEvaluation ();
1752 /* if any remaining bytes in the result */
1753 /* we just need to propagate the sign */
1754 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1756 emitcode ("rlc", "a");
1757 emitcode ("subb", "a,acc");
1759 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1763 /* release the aops */
1764 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1765 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1768 /*-----------------------------------------------------------------*/
1769 /* saveRegisters - will look for a call and save the registers */
1770 /*-----------------------------------------------------------------*/
1772 saveRegisters (iCode * lic)
1780 for (ic = lic; ic; ic = ic->next)
1781 if (ic->op == CALL || ic->op == PCALL)
1786 fprintf (stderr, "found parameter push with no function call\n");
1790 /* if the registers have been saved already then
1792 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type) ||
1793 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))))
1796 /* find the registers in use at this time
1797 and push them away to safety */
1798 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1802 if (options.useXstack)
1804 if (bitVectBitValue (rsave, R0_IDX))
1805 emitcode ("mov", "b,r0");
1806 emitcode ("mov", "r0,%s", spname);
1807 for (i = 0; i < ds390_nRegs; i++)
1809 if (bitVectBitValue (rsave, i))
1812 emitcode ("mov", "a,b");
1814 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1815 emitcode ("movx", "@r0,a");
1816 emitcode ("inc", "r0");
1819 emitcode ("mov", "%s,r0", spname);
1820 if (bitVectBitValue (rsave, R0_IDX))
1821 emitcode ("mov", "r0,b");
1824 for (i = 0; i < ds390_nRegs; i++)
1826 if (bitVectBitValue (rsave, i))
1827 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1830 detype = getSpec (operandType (IC_LEFT (ic)));
1833 /*-----------------------------------------------------------------*/
1834 /* unsaveRegisters - pop the pushed registers */
1835 /*-----------------------------------------------------------------*/
1837 unsaveRegisters (iCode * ic)
1841 /* find the registers in use at this time
1842 and push them away to safety */
1843 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1846 if (options.useXstack)
1848 emitcode ("mov", "r0,%s", spname);
1849 for (i = ds390_nRegs; i >= 0; i--)
1851 if (bitVectBitValue (rsave, i))
1853 emitcode ("dec", "r0");
1854 emitcode ("movx", "a,@r0");
1856 emitcode ("mov", "b,a");
1858 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1862 emitcode ("mov", "%s,r0", spname);
1863 if (bitVectBitValue (rsave, R0_IDX))
1864 emitcode ("mov", "r0,b");
1867 for (i = ds390_nRegs; i >= 0; i--)
1869 if (bitVectBitValue (rsave, i))
1870 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1876 /*-----------------------------------------------------------------*/
1878 /*-----------------------------------------------------------------*/
1880 pushSide (operand * oper, int size)
1883 _startLazyDPSEvaluation ();
1886 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1887 if (AOP_TYPE (oper) != AOP_REG &&
1888 AOP_TYPE (oper) != AOP_DIR &&
1891 emitcode ("mov", "a,%s", l);
1892 emitcode ("push", "acc");
1895 emitcode ("push", "%s", l);
1897 _endLazyDPSEvaluation ();
1900 /*-----------------------------------------------------------------*/
1901 /* assignResultValue - */
1902 /*-----------------------------------------------------------------*/
1904 assignResultValue (operand * oper)
1907 int size = AOP_SIZE (oper);
1909 _startLazyDPSEvaluation ();
1912 aopPut (AOP (oper), fReturn[offset], offset);
1915 _endLazyDPSEvaluation ();
1919 /*-----------------------------------------------------------------*/
1920 /* genXpush - pushes onto the external stack */
1921 /*-----------------------------------------------------------------*/
1923 genXpush (iCode * ic)
1925 asmop *aop = newAsmop (0);
1927 int size, offset = 0;
1929 D (emitcode (";", "genXpush ");
1932 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1933 r = getFreePtr (ic, &aop, FALSE);
1936 emitcode ("mov", "%s,_spx", r->name);
1938 size = AOP_SIZE (IC_LEFT (ic));
1939 _startLazyDPSEvaluation ();
1943 char *l = aopGet (AOP (IC_LEFT (ic)),
1944 offset++, FALSE, FALSE, TRUE);
1946 emitcode ("movx", "@%s,a", r->name);
1947 emitcode ("inc", "%s", r->name);
1950 _endLazyDPSEvaluation ();
1953 emitcode ("mov", "_spx,%s", r->name);
1955 freeAsmop (NULL, aop, ic, TRUE);
1956 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1959 /*-----------------------------------------------------------------*/
1960 /* genIpush - genrate code for pushing this gets a little complex */
1961 /*-----------------------------------------------------------------*/
1963 genIpush (iCode * ic)
1965 int size, offset = 0;
1968 D (emitcode (";", "genIpush ");
1971 /* if this is not a parm push : ie. it is spill push
1972 and spill push is always done on the local stack */
1976 /* and the item is spilt then do nothing */
1977 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1980 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1981 size = AOP_SIZE (IC_LEFT (ic));
1982 /* push it on the stack */
1983 _startLazyDPSEvaluation ();
1986 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1992 emitcode ("push", "%s", l);
1994 _endLazyDPSEvaluation ();
1998 /* this is a paramter push: in this case we call
1999 the routine to find the call and save those
2000 registers that need to be saved */
2003 /* if use external stack then call the external
2004 stack pushing routine */
2005 if (options.useXstack)
2011 /* then do the push */
2012 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2014 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2015 size = AOP_SIZE (IC_LEFT (ic));
2017 _startLazyDPSEvaluation ();
2020 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2021 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2022 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2025 emitcode ("mov", "a,%s", l);
2026 emitcode ("push", "acc");
2029 emitcode ("push", "%s", l);
2031 _endLazyDPSEvaluation ();
2033 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2036 /*-----------------------------------------------------------------*/
2037 /* genIpop - recover the registers: can happen only for spilling */
2038 /*-----------------------------------------------------------------*/
2040 genIpop (iCode * ic)
2044 D (emitcode (";", "genIpop ");
2048 /* if the temp was not pushed then */
2049 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2052 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2053 size = AOP_SIZE (IC_LEFT (ic));
2054 offset = (size - 1);
2055 _startLazyDPSEvaluation ();
2058 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2059 FALSE, TRUE, TRUE));
2061 _endLazyDPSEvaluation ();
2063 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2066 /*-----------------------------------------------------------------*/
2067 /* unsaveRBank - restores the resgister bank from stack */
2068 /*-----------------------------------------------------------------*/
2070 unsaveRBank (int bank, iCode * ic, bool popPsw)
2076 if (options.useXstack)
2080 /* Assume r0 is available for use. */
2081 r = ds390_regWithIdx (R0_IDX);;
2086 r = getFreePtr (ic, &aop, FALSE);
2088 emitcode ("mov", "%s,_spx", r->name);
2093 if (options.useXstack)
2095 emitcode ("movx", "a,@%s", r->name);
2096 emitcode ("mov", "psw,a");
2097 emitcode ("dec", "%s", r->name);
2101 emitcode ("pop", "psw");
2105 for (i = (ds390_nRegs - 1); i >= 0; i--)
2107 if (options.useXstack)
2109 emitcode ("movx", "a,@%s", r->name);
2110 emitcode ("mov", "(%s+%d),a",
2111 regs390[i].base, 8 * bank + regs390[i].offset);
2112 emitcode ("dec", "%s", r->name);
2116 emitcode ("pop", "(%s+%d)",
2117 regs390[i].base, 8 * bank + regs390[i].offset);
2120 if (options.useXstack)
2122 emitcode ("mov", "_spx,%s", r->name);
2127 freeAsmop (NULL, aop, ic, TRUE);
2131 /*-----------------------------------------------------------------*/
2132 /* saveRBank - saves an entire register bank on the stack */
2133 /*-----------------------------------------------------------------*/
2135 saveRBank (int bank, iCode * ic, bool pushPsw)
2141 if (options.useXstack)
2145 /* Assume r0 is available for use. */
2146 r = ds390_regWithIdx (R0_IDX);;
2151 r = getFreePtr (ic, &aop, FALSE);
2153 emitcode ("mov", "%s,_spx", r->name);
2156 for (i = 0; i < ds390_nRegs; i++)
2158 if (options.useXstack)
2160 emitcode ("inc", "%s", r->name);
2161 emitcode ("mov", "a,(%s+%d)",
2162 regs390[i].base, 8 * bank + regs390[i].offset);
2163 emitcode ("movx", "@%s,a", r->name);
2166 emitcode ("push", "(%s+%d)",
2167 regs390[i].base, 8 * bank + regs390[i].offset);
2172 if (options.useXstack)
2174 emitcode ("mov", "a,psw");
2175 emitcode ("movx", "@%s,a", r->name);
2176 emitcode ("inc", "%s", r->name);
2177 emitcode ("mov", "_spx,%s", r->name);
2181 emitcode ("push", "psw");
2184 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2189 freeAsmop (NULL, aop, ic, TRUE);
2198 /*-----------------------------------------------------------------*/
2199 /* genCall - generates a call statement */
2200 /*-----------------------------------------------------------------*/
2202 genCall (iCode * ic)
2205 bool restoreBank = FALSE;
2206 bool swapBanks = FALSE;
2208 D (emitcode (";", "genCall "););
2210 /* if we are calling a not _naked function that is not using
2211 the same register bank then we need to save the
2212 destination registers on the stack */
2213 dtype = operandType (IC_LEFT (ic));
2214 if (dtype && !IFFUNC_ISNAKED(dtype) &&
2215 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2216 IFFUNC_ISISR (currFunc->type))
2220 /* This is unexpected; the bank should have been saved in
2223 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2229 /* if caller saves & we have not saved then */
2233 /* if send set is not empty the assign */
2234 /* We've saved all the registers we care about;
2235 * therefore, we may clobber any register not used
2236 * in the calling convention (i.e. anything not in
2243 for (sic = setFirstItem (_G.sendSet); sic;
2244 sic = setNextItem (_G.sendSet))
2246 int size, offset = 0;
2248 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2249 size = AOP_SIZE (IC_LEFT (sic));
2251 _startLazyDPSEvaluation ();
2254 char *l = aopGet (AOP(IC_LEFT(sic)), offset,
2255 FALSE, FALSE, TRUE);
2256 if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size)
2258 emitcode("mov", "%s,%s", regs390[offset].name, l);
2260 else if (strcmp (l, fReturn[offset]))
2262 emitcode ("mov", "%s,%s",
2268 _endLazyDPSEvaluation ();
2269 if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR)
2271 size = AOP_SIZE (IC_LEFT (sic));
2279 emitcode("mov", "%s,%s",
2280 fReturn[size], regs390[size].name);
2283 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2290 emitcode ("mov", "psw,#0x%02x",
2291 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2295 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2296 OP_SYMBOL (IC_LEFT (ic))->rname :
2297 OP_SYMBOL (IC_LEFT (ic))->name));
2301 emitcode ("mov", "psw,#0x%02x",
2302 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2305 /* if we need assign a result value */
2306 if ((IS_ITEMP (IC_RESULT (ic)) &&
2307 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2308 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2309 IS_TRUE_SYMOP (IC_RESULT (ic)))
2311 if (isOperandInFarSpace (IC_RESULT (ic))
2312 && getSize (operandType (IC_RESULT (ic))) <= 2)
2314 int size = getSize (operandType (IC_RESULT (ic)));
2316 /* Special case for 1 or 2 byte return in far space. */
2320 emitcode ("mov", "b,%s", fReturn[1]);
2323 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2324 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2328 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2330 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2335 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2338 assignResultValue (IC_RESULT (ic));
2340 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2344 /* adjust the stack for parameters if
2349 if (ic->parmBytes > 3)
2351 emitcode ("mov", "a,%s", spname);
2352 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2353 emitcode ("mov", "%s,a", spname);
2356 for (i = 0; i < ic->parmBytes; i++)
2357 emitcode ("dec", "%s", spname);
2360 /* if we hade saved some registers then unsave them */
2361 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2362 unsaveRegisters (ic);
2364 /* if register bank was saved then pop them */
2366 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2369 /*-----------------------------------------------------------------*/
2370 /* genPcall - generates a call by pointer statement */
2371 /*-----------------------------------------------------------------*/
2373 genPcall (iCode * ic)
2376 symbol *rlbl = newiTempLabel (NULL);
2378 D (emitcode (";", "genPcall ");
2382 /* if caller saves & we have not saved then */
2386 /* if we are calling a function that is not using
2387 the same register bank then we need to save the
2388 destination registers on the stack */
2389 dtype = operandType (IC_LEFT (ic));
2391 IFFUNC_ISISR (currFunc->type) &&
2392 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)))
2393 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2396 /* push the return address on to the stack */
2397 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2398 emitcode ("push", "acc");
2399 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2400 emitcode ("push", "acc");
2402 if (options.model == MODEL_FLAT24)
2404 emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2405 emitcode ("push", "acc");
2408 /* now push the calling address */
2409 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2411 pushSide (IC_LEFT (ic), FPTRSIZE);
2413 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2415 /* if send set is not empty the assign */
2420 for (sic = setFirstItem (_G.sendSet); sic;
2421 sic = setNextItem (_G.sendSet))
2423 int size, offset = 0;
2425 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2426 size = AOP_SIZE (IC_LEFT (sic));
2427 _startLazyDPSEvaluation ();
2430 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2431 FALSE, FALSE, TRUE);
2432 if (strcmp (l, fReturn[offset]))
2434 emitcode ("mov", "%s,%s",
2440 _endLazyDPSEvaluation ();
2441 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2446 emitcode ("ret", "");
2447 emitcode ("", "%05d$:", (rlbl->key + 100));
2450 /* if we need assign a result value */
2451 if ((IS_ITEMP (IC_RESULT (ic)) &&
2452 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2453 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2454 IS_TRUE_SYMOP (IC_RESULT (ic)))
2458 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2461 assignResultValue (IC_RESULT (ic));
2463 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2466 /* adjust the stack for parameters if
2471 if (ic->parmBytes > 3)
2473 emitcode ("mov", "a,%s", spname);
2474 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2475 emitcode ("mov", "%s,a", spname);
2478 for (i = 0; i < ic->parmBytes; i++)
2479 emitcode ("dec", "%s", spname);
2483 /* if register bank was saved then unsave them */
2485 (FUNC_REGBANK (currFunc->type) !=
2486 FUNC_REGBANK (dtype)))
2487 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2489 /* if we hade saved some registers then
2492 unsaveRegisters (ic);
2496 /*-----------------------------------------------------------------*/
2497 /* resultRemat - result is rematerializable */
2498 /*-----------------------------------------------------------------*/
2500 resultRemat (iCode * ic)
2502 if (SKIP_IC (ic) || ic->op == IFX)
2505 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2507 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2508 if (sym->remat && !POINTER_SET (ic))
2515 #if defined(__BORLANDC__) || defined(_MSC_VER)
2516 #define STRCASECMP stricmp
2518 #define STRCASECMP strcasecmp
2521 /*-----------------------------------------------------------------*/
2522 /* inExcludeList - return 1 if the string is in exclude Reg list */
2523 /*-----------------------------------------------------------------*/
2525 inExcludeList (char *s)
2529 if (options.excludeRegs[i] &&
2530 STRCASECMP (options.excludeRegs[i], "none") == 0)
2533 for (i = 0; options.excludeRegs[i]; i++)
2535 if (options.excludeRegs[i] &&
2536 STRCASECMP (s, options.excludeRegs[i]) == 0)
2542 /*-----------------------------------------------------------------*/
2543 /* genFunction - generated code for function entry */
2544 /*-----------------------------------------------------------------*/
2546 genFunction (iCode * ic)
2550 bool switchedPSW = FALSE;
2552 D (emitcode (";", "genFunction "););
2555 /* create the function header */
2556 emitcode (";", "-----------------------------------------");
2557 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2558 emitcode (";", "-----------------------------------------");
2560 emitcode ("", "%s:", sym->rname);
2561 ftype = operandType (IC_LEFT (ic));
2563 if (IFFUNC_ISNAKED(ftype))
2565 emitcode(";", "naked function: no prologue.");
2569 /* if critical function then turn interrupts off */
2570 if (IFFUNC_ISCRITICAL (ftype))
2571 emitcode ("clr", "ea");
2573 /* here we need to generate the equates for the
2574 register bank if required */
2575 if (FUNC_REGBANK (ftype) != rbank)
2579 rbank = FUNC_REGBANK (ftype);
2580 for (i = 0; i < ds390_nRegs; i++)
2582 if (strcmp (regs390[i].base, "0") == 0)
2583 emitcode ("", "%s = 0x%02x",
2585 8 * rbank + regs390[i].offset);
2587 emitcode ("", "%s = %s + 0x%02x",
2590 8 * rbank + regs390[i].offset);
2594 /* if this is an interrupt service routine then
2595 save acc, b, dpl, dph */
2596 if (IFFUNC_ISISR (sym->type))
2599 if (!inExcludeList ("acc"))
2600 emitcode ("push", "acc");
2601 if (!inExcludeList ("b"))
2602 emitcode ("push", "b");
2603 if (!inExcludeList ("dpl"))
2604 emitcode ("push", "dpl");
2605 if (!inExcludeList ("dph"))
2606 emitcode ("push", "dph");
2607 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2609 emitcode ("push", "dpx");
2610 /* Make sure we're using standard DPTR */
2611 emitcode ("push", "dps");
2612 emitcode ("mov", "dps, #0x00");
2613 if (options.stack10bit)
2615 /* This ISR could conceivably use DPTR2. Better save it. */
2616 emitcode ("push", "dpl1");
2617 emitcode ("push", "dph1");
2618 emitcode ("push", "dpx1");
2619 emitcode ("push", DP2_RESULT_REG);
2622 /* if this isr has no bank i.e. is going to
2623 run with bank 0 , then we need to save more
2625 if (!FUNC_REGBANK (sym->type))
2628 /* if this function does not call any other
2629 function then we can be economical and
2630 save only those registers that are used */
2631 if (!IFFUNC_HASFCALL(sym->type))
2635 /* if any registers used */
2638 /* save the registers used */
2639 for (i = 0; i < sym->regsUsed->size; i++)
2641 if (bitVectBitValue (sym->regsUsed, i) ||
2642 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2643 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2650 /* this function has a function call cannot
2651 determines register usage so we will have to push the
2653 saveRBank (0, ic, FALSE);
2658 /* This ISR uses a non-zero bank.
2660 * We assume that the bank is available for our
2663 * However, if this ISR calls a function which uses some
2664 * other bank, we must save that bank entirely.
2666 unsigned long banksToSave = 0;
2668 if (IFFUNC_HASFCALL(sym->type))
2671 #define MAX_REGISTER_BANKS 4
2676 for (i = ic; i; i = i->next)
2678 if (i->op == ENDFUNCTION)
2680 /* we got to the end OK. */
2688 dtype = operandType (IC_LEFT(i));
2690 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2692 /* Mark this bank for saving. */
2693 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2695 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2699 banksToSave |= (1 << FUNC_REGBANK(dtype));
2702 /* And note that we don't need to do it in
2710 /* This is a mess; we have no idea what
2711 * register bank the called function might
2714 * The only thing I can think of to do is
2715 * throw a warning and hope.
2717 werror(W_FUNCPTR_IN_USING_ISR);
2721 if (banksToSave && options.useXstack)
2723 /* Since we aren't passing it an ic,
2724 * saveRBank will assume r0 is available to abuse.
2726 * So switch to our (trashable) bank now, so
2727 * the caller's R0 isn't trashed.
2729 emitcode ("push", "psw");
2730 emitcode ("mov", "psw,#0x%02x",
2731 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2735 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2737 if (banksToSave & (1 << ix))
2739 saveRBank(ix, NULL, FALSE);
2743 // jwk: this needs a closer look
2744 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2749 /* if callee-save to be used for this function
2750 then save the registers being used in this function */
2751 if (IFFUNC_CALLEESAVES(sym->type))
2755 /* if any registers used */
2758 /* save the registers used */
2759 for (i = 0; i < sym->regsUsed->size; i++)
2761 if (bitVectBitValue (sym->regsUsed, i) ||
2762 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2764 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2772 /* set the register bank to the desired value */
2773 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2776 emitcode ("push", "psw");
2777 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2780 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2783 if (options.useXstack)
2785 emitcode ("mov", "r0,%s", spname);
2786 emitcode ("mov", "a,_bp");
2787 emitcode ("movx", "@r0,a");
2788 emitcode ("inc", "%s", spname);
2792 /* set up the stack */
2793 emitcode ("push", "_bp"); /* save the callers stack */
2795 emitcode ("mov", "_bp,%s", spname);
2798 /* adjust the stack for the function */
2804 werror (W_STACK_OVERFLOW, sym->name);
2806 if (i > 3 && sym->recvSize < 4)
2809 emitcode ("mov", "a,sp");
2810 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2811 emitcode ("mov", "sp,a");
2816 emitcode ("inc", "sp");
2822 emitcode ("mov", "a,_spx");
2823 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2824 emitcode ("mov", "_spx,a");
2829 /*-----------------------------------------------------------------*/
2830 /* genEndFunction - generates epilogue for functions */
2831 /*-----------------------------------------------------------------*/
2833 genEndFunction (iCode * ic)
2835 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2837 D (emitcode (";", "genEndFunction "););
2839 if (IFFUNC_ISNAKED(sym->type))
2841 emitcode(";", "naked function: no epilogue.");
2845 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2847 emitcode ("mov", "%s,_bp", spname);
2850 /* if use external stack but some variables were
2851 added to the local stack then decrement the
2853 if (options.useXstack && sym->stack)
2855 emitcode ("mov", "a,sp");
2856 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2857 emitcode ("mov", "sp,a");
2861 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2863 if (options.useXstack)
2865 emitcode ("mov", "r0,%s", spname);
2866 emitcode ("movx", "a,@r0");
2867 emitcode ("mov", "_bp,a");
2868 emitcode ("dec", "%s", spname);
2872 emitcode ("pop", "_bp");
2876 /* restore the register bank */
2877 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2879 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
2880 || !options.useXstack)
2882 /* Special case of ISR using non-zero bank with useXstack
2885 emitcode ("pop", "psw");
2889 if (IFFUNC_ISISR (sym->type))
2892 /* now we need to restore the registers */
2893 /* if this isr has no bank i.e. is going to
2894 run with bank 0 , then we need to save more
2896 if (!FUNC_REGBANK (sym->type))
2898 /* if this function does not call any other
2899 function then we can be economical and
2900 save only those registers that are used */
2901 if (!IFFUNC_HASFCALL(sym->type))
2905 /* if any registers used */
2908 /* save the registers used */
2909 for (i = sym->regsUsed->size; i >= 0; i--)
2911 if (bitVectBitValue (sym->regsUsed, i) ||
2912 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2913 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2920 /* this function has a function call cannot
2921 determines register usage so we will have to pop the
2923 unsaveRBank (0, ic, FALSE);
2928 /* This ISR uses a non-zero bank.
2930 * Restore any register banks saved by genFunction
2933 // jwk: this needs a closer look
2934 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2937 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2939 if (savedBanks & (1 << ix))
2941 unsaveRBank(ix, NULL, FALSE);
2945 if (options.useXstack)
2947 /* Restore bank AFTER calling unsaveRBank,
2948 * since it can trash r0.
2950 emitcode ("pop", "psw");
2954 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2956 if (options.stack10bit)
2958 emitcode ("pop", DP2_RESULT_REG);
2959 emitcode ("pop", "dpx1");
2960 emitcode ("pop", "dph1");
2961 emitcode ("pop", "dpl1");
2963 emitcode ("pop", "dps");
2964 emitcode ("pop", "dpx");
2966 if (!inExcludeList ("dph"))
2967 emitcode ("pop", "dph");
2968 if (!inExcludeList ("dpl"))
2969 emitcode ("pop", "dpl");
2970 if (!inExcludeList ("b"))
2971 emitcode ("pop", "b");
2972 if (!inExcludeList ("acc"))
2973 emitcode ("pop", "acc");
2975 if (IFFUNC_ISCRITICAL (sym->type))
2976 emitcode ("setb", "ea");
2978 /* if debug then send end of function */
2979 if (options.debug && currFunc) {
2981 emitcode ("", "C$%s$%d$%d$%d ==.",
2982 FileBaseName (ic->filename), currFunc->lastLine,
2983 ic->level, ic->block);
2984 if (IS_STATIC (currFunc->etype))
2985 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2987 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2991 emitcode ("reti", "");
2995 if (IFFUNC_ISCRITICAL (sym->type))
2996 emitcode ("setb", "ea");
2998 if (IFFUNC_CALLEESAVES(sym->type))
3002 /* if any registers used */
3005 /* save the registers used */
3006 for (i = sym->regsUsed->size; i >= 0; i--)
3008 if (bitVectBitValue (sym->regsUsed, i) ||
3009 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3010 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3016 /* if debug then send end of function */
3017 if (options.debug && currFunc)
3020 emitcode ("", "C$%s$%d$%d$%d ==.",
3021 FileBaseName (ic->filename), currFunc->lastLine,
3022 ic->level, ic->block);
3023 if (IS_STATIC (currFunc->etype))
3024 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3026 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3030 emitcode ("ret", "");
3035 /*-----------------------------------------------------------------*/
3036 /* genRet - generate code for return statement */
3037 /*-----------------------------------------------------------------*/
3041 int size, offset = 0, pushed = 0;
3043 D (emitcode (";", "genRet ");
3046 /* if we have no return value then
3047 just generate the "ret" */
3051 /* we have something to return then
3052 move the return value into place */
3053 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
3054 size = AOP_SIZE (IC_LEFT (ic));
3056 _startLazyDPSEvaluation ();
3060 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3062 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3063 FALSE, TRUE, FALSE);
3064 emitcode ("push", "%s", l);
3069 /* Since A is the last element of fReturn,
3070 * is is OK to clobber it in the aopGet.
3072 l = aopGet (AOP (IC_LEFT (ic)), offset,
3073 FALSE, FALSE, TRUE);
3074 if (strcmp (fReturn[offset], l))
3075 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3078 _endLazyDPSEvaluation ();
3085 if (strcmp (fReturn[pushed], "a"))
3086 emitcode ("pop", fReturn[pushed]);
3088 emitcode ("pop", "acc");
3091 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3094 /* generate a jump to the return label
3095 if the next is not the return statement */
3096 if (!(ic->next && ic->next->op == LABEL &&
3097 IC_LABEL (ic->next) == returnLabel))
3099 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3103 /*-----------------------------------------------------------------*/
3104 /* genLabel - generates a label */
3105 /*-----------------------------------------------------------------*/
3107 genLabel (iCode * ic)
3109 /* special case never generate */
3110 if (IC_LABEL (ic) == entryLabel)
3113 D (emitcode (";", "genLabel ");
3116 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3119 /*-----------------------------------------------------------------*/
3120 /* genGoto - generates a ljmp */
3121 /*-----------------------------------------------------------------*/
3123 genGoto (iCode * ic)
3125 D (emitcode (";", "genGoto ");
3127 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3130 /*-----------------------------------------------------------------*/
3131 /* findLabelBackwards: walks back through the iCode chain looking */
3132 /* for the given label. Returns number of iCode instructions */
3133 /* between that label and given ic. */
3134 /* Returns zero if label not found. */
3135 /*-----------------------------------------------------------------*/
3137 findLabelBackwards (iCode * ic, int key)
3146 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3148 /* printf("findLabelBackwards = %d\n", count); */
3156 /*-----------------------------------------------------------------*/
3157 /* genPlusIncr :- does addition with increment if possible */
3158 /*-----------------------------------------------------------------*/
3160 genPlusIncr (iCode * ic)
3162 unsigned int icount;
3163 unsigned int size = getDataSize (IC_RESULT (ic));
3165 /* will try to generate an increment */
3166 /* if the right side is not a literal
3168 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3171 /* if the literal value of the right hand side
3172 is greater than 4 then it is not worth it */
3173 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3176 /* if increment 16 bits in register */
3178 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3179 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3180 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3188 /* If the next instruction is a goto and the goto target
3189 * is <= 5 instructions previous to this, we can generate
3190 * jumps straight to that target.
3192 if (ic->next && ic->next->op == GOTO
3193 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3196 emitcode (";", "tail increment optimized (range %d)", labelRange);
3197 tlbl = IC_LABEL (ic->next);
3202 tlbl = newiTempLabel (NULL);
3205 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3206 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3207 IS_AOP_PREG (IC_RESULT (ic)))
3208 emitcode ("cjne", "%s,#0x00,%05d$"
3209 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3213 emitcode ("clr", "a");
3214 emitcode ("cjne", "a,%s,%05d$"
3215 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3219 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3222 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3223 IS_AOP_PREG (IC_RESULT (ic)))
3224 emitcode ("cjne", "%s,#0x00,%05d$"
3225 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3228 emitcode ("cjne", "a,%s,%05d$"
3229 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3232 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3236 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3237 IS_AOP_PREG (IC_RESULT (ic)))
3238 emitcode ("cjne", "%s,#0x00,%05d$"
3239 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3243 emitcode ("cjne", "a,%s,%05d$"
3244 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3247 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3252 emitcode ("", "%05d$:", tlbl->key + 100);
3257 /* if the sizes are greater than 1 then we cannot */
3258 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3259 AOP_SIZE (IC_LEFT (ic)) > 1)
3262 /* we can if the aops of the left & result match or
3263 if they are in registers and the registers are the
3266 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3267 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3268 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3273 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3274 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3275 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3280 _startLazyDPSEvaluation ();
3283 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3285 _endLazyDPSEvaluation ();
3294 /*-----------------------------------------------------------------*/
3295 /* outBitAcc - output a bit in acc */
3296 /*-----------------------------------------------------------------*/
3298 outBitAcc (operand * result)
3300 symbol *tlbl = newiTempLabel (NULL);
3301 /* if the result is a bit */
3302 if (AOP_TYPE (result) == AOP_CRY)
3304 aopPut (AOP (result), "a", 0);
3308 emitcode ("jz", "%05d$", tlbl->key + 100);
3309 emitcode ("mov", "a,%s", one);
3310 emitcode ("", "%05d$:", tlbl->key + 100);
3315 /*-----------------------------------------------------------------*/
3316 /* genPlusBits - generates code for addition of two bits */
3317 /*-----------------------------------------------------------------*/
3319 genPlusBits (iCode * ic)
3321 D (emitcode (";", "genPlusBits ");
3323 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3325 symbol *lbl = newiTempLabel (NULL);
3326 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3327 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3328 emitcode ("cpl", "c");
3329 emitcode ("", "%05d$:", (lbl->key + 100));
3330 outBitC (IC_RESULT (ic));
3334 emitcode ("clr", "a");
3335 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3336 emitcode ("rlc", "a");
3337 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3338 emitcode ("addc", "a,#0x00");
3339 outAcc (IC_RESULT (ic));
3344 adjustArithmeticResult (iCode * ic)
3346 if (opIsGptr (IC_RESULT (ic)) &&
3347 opIsGptr (IC_LEFT (ic)) &&
3348 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3350 aopPut (AOP (IC_RESULT (ic)),
3351 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3355 if (opIsGptr (IC_RESULT (ic)) &&
3356 opIsGptr (IC_RIGHT (ic)) &&
3357 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3359 aopPut (AOP (IC_RESULT (ic)),
3360 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3364 if (opIsGptr (IC_RESULT (ic)) &&
3365 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3366 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3367 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3368 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3371 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3372 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3376 #if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
3377 // Please don't bring it back without a really good reason.
3378 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3379 // (because all three operands are in far space).
3380 #define AOP_OP_3(ic) \
3381 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3382 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3383 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3384 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3385 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3386 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3388 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3390 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3394 // Macro to aopOp all three operands of an ic. If this cannot be done,
3395 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3396 // will be set TRUE. The caller must then handle the case specially, noting
3397 // that the IC_RESULT operand is not aopOp'd.
3398 #define AOP_OP_3_NOFATAL(ic, rc) \
3399 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3400 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3401 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3402 isOperandInFarSpace(IC_RESULT(ic))) \
3404 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3409 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3410 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3412 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3413 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3415 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3417 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3421 // aopOp the left & right operands of an ic.
3422 #define AOP_OP_2(ic) \
3423 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3424 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3426 // convienience macro.
3427 #define AOP_SET_LOCALS(ic) \
3428 left = IC_LEFT(ic); \
3429 right = IC_RIGHT(ic); \
3430 result = IC_RESULT(ic);
3433 // Given an integer value of pushedSize bytes on the stack,
3434 // adjust it to be resultSize bytes, either by discarding
3435 // the most significant bytes or by zero-padding.
3437 // On exit from this macro, pushedSize will have been adjusted to
3438 // equal resultSize, and ACC may be trashed.
3439 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3440 /* If the pushed data is bigger than the result, \
3441 * simply discard unused bytes. Icky, but works. \
3443 while (pushedSize > resultSize) \
3445 D (emitcode (";", "discarding unused result byte."););\
3446 emitcode ("pop", "acc"); \
3449 if (pushedSize < resultSize) \
3451 emitcode ("clr", "a"); \
3452 /* Conversly, we haven't pushed enough here. \
3453 * just zero-pad, and all is well. \
3455 while (pushedSize < resultSize) \
3457 emitcode("push", "acc"); \
3461 assert(pushedSize == resultSize);
3463 /*-----------------------------------------------------------------*/
3464 /* genPlus - generates code for addition */
3465 /*-----------------------------------------------------------------*/
3467 genPlus (iCode * ic)
3469 int size, offset = 0;
3470 bool pushResult = FALSE;
3473 D (emitcode (";", "genPlus "););
3475 /* special cases :- */
3477 AOP_OP_3_NOFATAL (ic, pushResult);
3480 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3485 /* if literal, literal on the right or
3486 if left requires ACC or right is already
3488 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3489 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3490 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3492 operand *t = IC_RIGHT (ic);
3493 IC_RIGHT (ic) = IC_LEFT (ic);
3495 emitcode (";", "Swapped plus args.");
3498 /* if both left & right are in bit
3500 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3501 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3507 /* if left in bit space & right literal */
3508 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3509 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3511 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3512 /* if result in bit space */
3513 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3515 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3516 emitcode ("cpl", "c");
3517 outBitC (IC_RESULT (ic));
3521 size = getDataSize (IC_RESULT (ic));
3522 _startLazyDPSEvaluation ();
3525 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3526 emitcode ("addc", "a,#00");
3527 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3529 _endLazyDPSEvaluation ();
3534 /* if I can do an increment instead
3535 of add then GOOD for ME */
3536 if (genPlusIncr (ic) == TRUE)
3538 emitcode (";", "did genPlusIncr");
3543 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3545 _startLazyDPSEvaluation ();
3548 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3550 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3552 emitcode ("add", "a,%s",
3553 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3555 emitcode ("addc", "a,%s",
3556 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3560 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3562 /* right is going to use ACC or we would have taken the
3565 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3567 D(emitcode(";", "+ AOP_ACC special case."););
3568 emitcode("xch", "a, %s", DP2_RESULT_REG);
3570 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3573 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3576 emitcode("add", "a, %s", DP2_RESULT_REG);
3580 emitcode ("add", "a,%s",
3581 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3586 emitcode ("addc", "a,%s",
3587 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3592 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3596 emitcode ("push", "acc");
3600 _endLazyDPSEvaluation ();
3604 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3606 size = getDataSize (IC_LEFT (ic));
3607 rSize = getDataSize (IC_RESULT (ic));
3609 ADJUST_PUSHED_RESULT(size, rSize);
3611 _startLazyDPSEvaluation ();
3614 emitcode ("pop", "acc");
3615 aopPut (AOP (IC_RESULT (ic)), "a", size);
3617 _endLazyDPSEvaluation ();
3620 adjustArithmeticResult (ic);
3623 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3624 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3625 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3628 /*-----------------------------------------------------------------*/
3629 /* genMinusDec :- does subtraction with deccrement if possible */
3630 /*-----------------------------------------------------------------*/
3632 genMinusDec (iCode * ic)
3634 unsigned int icount;
3635 unsigned int size = getDataSize (IC_RESULT (ic));
3637 /* will try to generate an increment */
3638 /* if the right side is not a literal
3640 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3643 /* if the literal value of the right hand side
3644 is greater than 4 then it is not worth it */
3645 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3648 /* if decrement 16 bits in register */
3649 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3650 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3651 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3659 /* If the next instruction is a goto and the goto target
3660 * is <= 5 instructions previous to this, we can generate
3661 * jumps straight to that target.
3663 if (ic->next && ic->next->op == GOTO
3664 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3667 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3668 tlbl = IC_LABEL (ic->next);
3673 tlbl = newiTempLabel (NULL);
3677 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3678 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3679 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3680 IS_AOP_PREG (IC_RESULT (ic)))
3681 emitcode ("cjne", "%s,#0xff,%05d$"
3682 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3686 emitcode ("mov", "a,#0xff");
3687 emitcode ("cjne", "a,%s,%05d$"
3688 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3691 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3694 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3695 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3696 IS_AOP_PREG (IC_RESULT (ic)))
3697 emitcode ("cjne", "%s,#0xff,%05d$"
3698 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3702 emitcode ("cjne", "a,%s,%05d$"
3703 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3706 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3710 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3711 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3712 IS_AOP_PREG (IC_RESULT (ic)))
3713 emitcode ("cjne", "%s,#0xff,%05d$"
3714 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3718 emitcode ("cjne", "a,%s,%05d$"
3719 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3722 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3726 emitcode ("", "%05d$:", tlbl->key + 100);
3731 /* if the sizes are greater than 1 then we cannot */
3732 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3733 AOP_SIZE (IC_LEFT (ic)) > 1)
3736 /* we can if the aops of the left & result match or
3737 if they are in registers and the registers are the
3740 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3741 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3742 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3745 _startLazyDPSEvaluation ();
3748 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3750 _endLazyDPSEvaluation ();
3758 /*-----------------------------------------------------------------*/
3759 /* addSign - complete with sign */
3760 /*-----------------------------------------------------------------*/
3762 addSign (operand * result, int offset, int sign)
3764 int size = (getDataSize (result) - offset);
3767 _startLazyDPSEvaluation();
3770 emitcode ("rlc", "a");
3771 emitcode ("subb", "a,acc");
3774 aopPut (AOP (result), "a", offset++);
3781 aopPut (AOP (result), zero, offset++);
3784 _endLazyDPSEvaluation();
3788 /*-----------------------------------------------------------------*/
3789 /* genMinusBits - generates code for subtraction of two bits */
3790 /*-----------------------------------------------------------------*/
3792 genMinusBits (iCode * ic)
3794 symbol *lbl = newiTempLabel (NULL);
3796 D (emitcode (";", "genMinusBits "););
3798 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3800 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3801 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3802 emitcode ("cpl", "c");
3803 emitcode ("", "%05d$:", (lbl->key + 100));
3804 outBitC (IC_RESULT (ic));
3808 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3809 emitcode ("subb", "a,acc");
3810 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3811 emitcode ("inc", "a");
3812 emitcode ("", "%05d$:", (lbl->key + 100));
3813 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3814 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3818 /*-----------------------------------------------------------------*/
3819 /* genMinus - generates code for subtraction */
3820 /*-----------------------------------------------------------------*/
3822 genMinus (iCode * ic)
3824 int size, offset = 0;
3826 unsigned long lit = 0L;
3827 bool pushResult = FALSE;
3829 D (emitcode (";", "genMinus "););
3831 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3832 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3833 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3834 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3840 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3842 /* special cases :- */
3843 /* if both left & right are in bit space */
3844 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3845 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3851 /* if I can do an decrement instead
3852 of subtract then GOOD for ME */
3853 if (genMinusDec (ic) == TRUE)
3858 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3860 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3866 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3871 /* if literal, add a,#-lit, else normal subb */
3872 _startLazyDPSEvaluation ();
3875 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3876 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3877 emitcode ("subb", "a,%s",
3878 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3881 /* first add without previous c */
3883 if (!size && lit==-1) {
3884 emitcode ("dec", "a");
3886 emitcode ("add", "a,#0x%02x",
3887 (unsigned int) (lit & 0x0FFL));
3890 emitcode ("addc", "a,#0x%02x",
3891 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3897 emitcode ("push", "acc");
3901 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3905 _endLazyDPSEvaluation ();
3909 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3911 size = getDataSize (IC_LEFT (ic));
3912 rSize = getDataSize (IC_RESULT (ic));
3914 ADJUST_PUSHED_RESULT(size, rSize);
3916 _startLazyDPSEvaluation ();
3919 emitcode ("pop", "acc");
3920 aopPut (AOP (IC_RESULT (ic)), "a", size);
3922 _endLazyDPSEvaluation ();
3925 adjustArithmeticResult (ic);
3928 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3929 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3930 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3934 /*-----------------------------------------------------------------*/
3935 /* genMultbits :- multiplication of bits */
3936 /*-----------------------------------------------------------------*/
3938 genMultbits (operand * left,
3943 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3944 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3945 aopOp(result, ic, TRUE, FALSE);
3950 /*-----------------------------------------------------------------*/
3951 /* genMultOneByte : 8*8=8/16 bit multiplication */
3952 /*-----------------------------------------------------------------*/
3954 genMultOneByte (operand * left,
3959 sym_link *opetype = operandType (result);
3963 /* (if two literals: the value is computed before) */
3964 /* if one literal, literal on the right */
3965 if (AOP_TYPE (left) == AOP_LIT)
3970 emitcode (";", "swapped left and right");
3973 if (SPEC_USIGN(opetype)
3974 // ignore the sign of left and right, what else can we do?
3975 || (SPEC_USIGN(operandType(left)) &&
3976 SPEC_USIGN(operandType(right)))) {
3977 // just an unsigned 8*8=8/16 multiply
3978 //emitcode (";","unsigned");
3979 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3980 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3981 emitcode ("mul", "ab");
3984 aopOp(result, ic, TRUE, FALSE);
3986 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
3988 // this should never happen
3989 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3990 AOP_SIZE(result), __FILE__, lineno);
3994 aopPut (AOP (result), "a", 0);
3996 if (AOP_SIZE(result)==2)
3998 aopPut (AOP (result), "b", 1);
4003 // we have to do a signed multiply
4005 emitcode (";", "signed");
4006 emitcode ("clr", "F0"); // reset sign flag
4007 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4009 lbl=newiTempLabel(NULL);
4010 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
4011 // left side is negative, 8-bit two's complement, this fails for -128
4012 emitcode ("setb", "F0"); // set sign flag
4013 emitcode ("cpl", "a");
4014 emitcode ("inc", "a");
4016 emitcode ("", "%05d$:", lbl->key+100);
4019 if (AOP_TYPE(right)==AOP_LIT) {
4020 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4021 /* AND literal negative */
4022 if ((int) val < 0) {
4023 emitcode ("cpl", "F0"); // complement sign flag
4024 emitcode ("mov", "b,#0x%02x", -val);
4026 emitcode ("mov", "b,#0x%02x", val);
4029 lbl=newiTempLabel(NULL);
4030 emitcode ("mov", "b,a");
4031 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4032 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
4033 // right side is negative, 8-bit two's complement
4034 emitcode ("cpl", "F0"); // complement sign flag
4035 emitcode ("cpl", "a");
4036 emitcode ("inc", "a");
4037 emitcode ("", "%05d$:", lbl->key+100);
4039 emitcode ("mul", "ab");
4042 aopOp(result, ic, TRUE, FALSE);
4044 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4046 // this should never happen
4047 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4048 AOP_SIZE(result), __FILE__, lineno);
4052 lbl=newiTempLabel(NULL);
4053 emitcode ("jnb", "F0,%05d$", lbl->key+100);
4054 // only ONE op was negative, we have to do a 8/16-bit two's complement
4055 emitcode ("cpl", "a"); // lsb
4056 if (AOP_SIZE(result)==1) {
4057 emitcode ("inc", "a");
4059 emitcode ("add", "a,#1");
4060 emitcode ("xch", "a,b");
4061 emitcode ("cpl", "a"); // msb
4062 emitcode ("addc", "a,#0");
4063 emitcode ("xch", "a,b");
4066 emitcode ("", "%05d$:", lbl->key+100);
4067 aopPut (AOP (result), "a", 0);
4069 if (AOP_SIZE(result)==2) {
4070 aopPut (AOP (result), "b", 1);
4074 /*-----------------------------------------------------------------*/
4075 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4076 /*-----------------------------------------------------------------*/
4077 static void genMultTwoByte (operand *left, operand *right,
4078 operand *result, iCode *ic)
4080 sym_link *retype = getSpec(operandType(right));
4081 sym_link *letype = getSpec(operandType(left));
4082 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4085 if (AOP_TYPE (left) == AOP_LIT) {
4090 /* load up MB with right */
4092 emitcode("clr","F0");
4093 if (AOP_TYPE(right) == AOP_LIT) {
4094 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4096 emitcode("setb","F0");
4099 emitcode ("mov","mb,#0x%02x",val & 0xff);
4100 emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4102 lbl = newiTempLabel(NULL);
4103 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4104 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4105 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4106 emitcode ("xch", "a,b");
4107 emitcode ("cpl","a");
4108 emitcode ("add", "a,#1");
4109 emitcode ("xch", "a,b");
4110 emitcode ("cpl", "a"); // msb
4111 emitcode ("addc", "a,#0");
4112 emitcode ("setb","F0");
4113 emitcode ("","%05d$:",lbl->key+100);
4114 emitcode ("mov","mb,b");
4115 emitcode ("mov","mb,a");
4118 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4119 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4121 /* load up MA with left */
4123 lbl = newiTempLabel(NULL);
4124 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4125 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4126 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4127 emitcode ("xch", "a,b");
4128 emitcode ("cpl","a");
4129 emitcode ("add", "a,#1");
4130 emitcode ("xch", "a,b");
4131 emitcode ("cpl", "a"); // msb
4132 emitcode ("addc","a,#0");
4133 emitcode ("jbc","F0,%05d$",lbl->key+100);
4134 emitcode ("setb","F0");
4135 emitcode ("","%05d$:",lbl->key+100);
4136 emitcode ("mov","ma,b");
4137 emitcode ("mov","ma,a");
4139 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4140 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4142 /* wait for multiplication to finish */
4143 lbl = newiTempLabel(NULL);
4144 emitcode("","%05d$:", lbl->key+100);
4145 emitcode("mov","a,mcnt1");
4146 emitcode("anl","a,#0x80");
4147 emitcode("jnz","%05d$",lbl->key+100);
4149 freeAsmop (left, NULL, ic, TRUE);
4150 freeAsmop (right, NULL, ic,TRUE);
4151 aopOp(result, ic, TRUE, FALSE);
4153 /* if unsigned then simple */
4155 emitcode ("mov","a,ma");
4156 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4157 emitcode ("mov","a,ma");
4158 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4159 aopPut(AOP(result),"ma",1);
4160 aopPut(AOP(result),"ma",0);
4162 emitcode("push","ma");
4163 emitcode("push","ma");
4164 emitcode("push","ma");
4166 /* negate result if needed */
4167 lbl = newiTempLabel(NULL);
4168 emitcode("jnb","F0,%05d$",lbl->key+100);
4169 emitcode("cpl","a");
4170 emitcode("add","a,#1");
4171 emitcode("","%05d$:", lbl->key+100);
4172 if (AOP_TYPE(result) == AOP_ACC)
4174 D(emitcode(";", "ACC special case."););
4175 /* We know result is the only live aop, and
4176 * it's obviously not a DPTR2, so AP is available.
4178 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4182 aopPut(AOP(result),"a",0);
4185 emitcode("pop","acc");
4186 lbl = newiTempLabel(NULL);
4187 emitcode("jnb","F0,%05d$",lbl->key+100);
4188 emitcode("cpl","a");
4189 emitcode("addc","a,#0");
4190 emitcode("","%05d$:", lbl->key+100);
4191 aopPut(AOP(result),"a",1);
4192 emitcode("pop","acc");
4193 if (AOP_SIZE(result) >= 3) {
4194 lbl = newiTempLabel(NULL);
4195 emitcode("jnb","F0,%05d$",lbl->key+100);
4196 emitcode("cpl","a");
4197 emitcode("addc","a,#0");
4198 emitcode("","%05d$:", lbl->key+100);
4199 aopPut(AOP(result),"a",2);
4201 emitcode("pop","acc");
4202 if (AOP_SIZE(result) >= 4) {
4203 lbl = newiTempLabel(NULL);
4204 emitcode("jnb","F0,%05d$",lbl->key+100);
4205 emitcode("cpl","a");
4206 emitcode("addc","a,#0");
4207 emitcode("","%05d$:", lbl->key+100);
4208 aopPut(AOP(result),"a",3);
4210 if (AOP_TYPE(result) == AOP_ACC)
4212 /* We stashed the result away above. */
4213 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4217 freeAsmop (result, NULL, ic, TRUE);
4221 /*-----------------------------------------------------------------*/
4222 /* genMult - generates code for multiplication */
4223 /*-----------------------------------------------------------------*/
4225 genMult (iCode * ic)
4227 operand *left = IC_LEFT (ic);
4228 operand *right = IC_RIGHT (ic);
4229 operand *result = IC_RESULT (ic);
4231 D (emitcode (";", "genMult "););
4233 /* assign the amsops */
4236 /* special cases first */
4238 if (AOP_TYPE (left) == AOP_CRY &&
4239 AOP_TYPE (right) == AOP_CRY)
4241 genMultbits (left, right, result, ic);
4245 /* if both are of size == 1 */
4246 if (AOP_SIZE (left) == 1 &&
4247 AOP_SIZE (right) == 1)
4249 genMultOneByte (left, right, result, ic);
4253 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4254 /* use the ds390 ARITHMETIC accel UNIT */
4255 genMultTwoByte (left, right, result, ic);
4258 /* should have been converted to function call */
4262 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4263 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4264 freeAsmop (result, NULL, ic, TRUE);
4267 /*-----------------------------------------------------------------*/
4268 /* genDivbits :- division of bits */
4269 /*-----------------------------------------------------------------*/
4271 genDivbits (operand * left,
4279 /* the result must be bit */
4280 LOAD_AB_FOR_DIV (left, right, l);
4281 emitcode ("div", "ab");
4282 emitcode ("rrc", "a");
4283 aopOp(result, ic, TRUE, FALSE);
4285 aopPut (AOP (result), "c", 0);
4288 /*-----------------------------------------------------------------*/
4289 /* genDivOneByte : 8 bit division */
4290 /*-----------------------------------------------------------------*/
4292 genDivOneByte (operand * left,
4297 sym_link *opetype = operandType (result);
4303 /* signed or unsigned */
4304 if (SPEC_USIGN (opetype))
4306 /* unsigned is easy */
4307 LOAD_AB_FOR_DIV (left, right, l);
4308 emitcode ("div", "ab");
4311 aopOp(result, ic, TRUE, FALSE);
4312 aopPut (AOP (result), "a", 0);
4315 size = AOP_SIZE (result) - 1;
4319 aopPut (AOP (result), zero, offset++);
4324 /* signed is a little bit more difficult */
4326 /* save the signs of the operands */
4327 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4329 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4330 emitcode ("push", "acc"); /* save it on the stack */
4332 /* now sign adjust for both left & right */
4333 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4335 lbl = newiTempLabel (NULL);
4336 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4337 emitcode ("cpl", "a");
4338 emitcode ("inc", "a");
4339 emitcode ("", "%05d$:", (lbl->key + 100));
4340 emitcode ("mov", "b,a");
4342 /* sign adjust left side */
4343 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4346 lbl = newiTempLabel (NULL);
4347 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4348 emitcode ("cpl", "a");
4349 emitcode ("inc", "a");
4350 emitcode ("", "%05d$:", (lbl->key + 100));
4352 /* now the division */
4353 emitcode ("nop", "; workaround for DS80C390 div bug.");
4354 emitcode ("div", "ab");
4355 /* we are interested in the lower order
4357 emitcode ("mov", "b,a");
4358 lbl = newiTempLabel (NULL);
4359 emitcode ("pop", "acc");
4360 /* if there was an over flow we don't
4361 adjust the sign of the result */
4362 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4363 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4365 emitcode ("clr", "a");
4366 emitcode ("subb", "a,b");
4367 emitcode ("mov", "b,a");
4368 emitcode ("", "%05d$:", (lbl->key + 100));
4370 /* now we are done */
4372 aopOp(result, ic, TRUE, FALSE);
4374 aopPut (AOP (result), "b", 0);
4376 size = AOP_SIZE (result) - 1;
4380 emitcode ("mov", "c,b.7");
4381 emitcode ("subb", "a,acc");
4385 aopPut (AOP (result), "a", offset++);
4391 /*-----------------------------------------------------------------*/
4392 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4393 /*-----------------------------------------------------------------*/
4394 static void genDivTwoByte (operand *left, operand *right,
4395 operand *result, iCode *ic)
4397 sym_link *retype = getSpec(operandType(right));
4398 sym_link *letype = getSpec(operandType(left));
4399 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4402 /* load up MA with left */
4404 emitcode("clr","F0");
4405 lbl = newiTempLabel(NULL);
4406 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4407 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4408 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4409 emitcode ("xch", "a,b");
4410 emitcode ("cpl","a");
4411 emitcode ("add", "a,#1");
4412 emitcode ("xch", "a,b");
4413 emitcode ("cpl", "a"); // msb
4414 emitcode ("addc","a,#0");
4415 emitcode ("setb","F0");
4416 emitcode ("","%05d$:",lbl->key+100);
4417 emitcode ("mov","ma,b");
4418 emitcode ("mov","ma,a");
4420 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4421 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4424 /* load up MB with right */
4426 if (AOP_TYPE(right) == AOP_LIT) {
4427 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4429 lbl = newiTempLabel(NULL);
4430 emitcode ("jbc","F0,%05d$",lbl->key+100);
4431 emitcode("setb","F0");
4432 emitcode ("","%05d$:",lbl->key+100);
4435 emitcode ("mov","mb,#0x%02x",val & 0xff);
4436 emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4438 lbl = newiTempLabel(NULL);
4439 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4440 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4441 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4442 emitcode ("xch", "a,b");
4443 emitcode ("cpl","a");
4444 emitcode ("add", "a,#1");
4445 emitcode ("xch", "a,b");
4446 emitcode ("cpl", "a"); // msb
4447 emitcode ("addc", "a,#0");
4448 emitcode ("jbc","F0,%05d$",lbl->key+100);
4449 emitcode ("setb","F0");
4450 emitcode ("","%05d$:",lbl->key+100);
4451 emitcode ("mov","mb,b");
4452 emitcode ("mov","mb,a");
4455 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4456 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4459 /* wait for multiplication to finish */
4460 lbl = newiTempLabel(NULL);
4461 emitcode("","%05d$:", lbl->key+100);
4462 emitcode("mov","a,mcnt1");
4463 emitcode("anl","a,#0x80");
4464 emitcode("jnz","%05d$",lbl->key+100);
4466 freeAsmop (left, NULL, ic, TRUE);
4467 freeAsmop (right, NULL, ic,TRUE);
4468 aopOp(result, ic, TRUE, FALSE);
4470 /* if unsigned then simple */
4472 aopPut(AOP(result),"ma",1);
4473 aopPut(AOP(result),"ma",0);
4475 emitcode("push","ma");
4477 /* negate result if needed */
4478 lbl = newiTempLabel(NULL);
4479 emitcode("jnb","F0,%05d$",lbl->key+100);
4480 emitcode("cpl","a");
4481 emitcode("add","a,#1");
4482 emitcode("","%05d$:", lbl->key+100);
4483 aopPut(AOP(result),"a",0);
4484 emitcode("pop","acc");
4485 lbl = newiTempLabel(NULL);
4486 emitcode("jnb","F0,%05d$",lbl->key+100);
4487 emitcode("cpl","a");
4488 emitcode("addc","a,#0");
4489 emitcode("","%05d$:", lbl->key+100);
4490 aopPut(AOP(result),"a",1);
4492 freeAsmop (result, NULL, ic, TRUE);
4496 /*-----------------------------------------------------------------*/
4497 /* genDiv - generates code for division */
4498 /*-----------------------------------------------------------------*/
4502 operand *left = IC_LEFT (ic);
4503 operand *right = IC_RIGHT (ic);
4504 operand *result = IC_RESULT (ic);
4506 D (emitcode (";", "genDiv "););
4508 /* assign the amsops */
4511 /* special cases first */
4513 if (AOP_TYPE (left) == AOP_CRY &&
4514 AOP_TYPE (right) == AOP_CRY)
4516 genDivbits (left, right, result, ic);
4520 /* if both are of size == 1 */
4521 if (AOP_SIZE (left) == 1 &&
4522 AOP_SIZE (right) == 1)
4524 genDivOneByte (left, right, result, ic);
4528 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4529 /* use the ds390 ARITHMETIC accel UNIT */
4530 genDivTwoByte (left, right, result, ic);
4533 /* should have been converted to function call */
4536 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4537 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4538 freeAsmop (result, NULL, ic, TRUE);
4541 /*-----------------------------------------------------------------*/
4542 /* genModbits :- modulus of bits */
4543 /*-----------------------------------------------------------------*/
4545 genModbits (operand * left,
4553 /* the result must be bit */
4554 LOAD_AB_FOR_DIV (left, right, l);
4555 emitcode ("div", "ab");
4556 emitcode ("mov", "a,b");
4557 emitcode ("rrc", "a");
4558 aopOp(result, ic, TRUE, FALSE);
4559 aopPut (AOP (result), "c", 0);
4562 /*-----------------------------------------------------------------*/
4563 /* genModOneByte : 8 bit modulus */
4564 /*-----------------------------------------------------------------*/
4566 genModOneByte (operand * left,
4571 sym_link *opetype = operandType (result);
4575 /* signed or unsigned */
4576 if (SPEC_USIGN (opetype))
4578 /* unsigned is easy */
4579 LOAD_AB_FOR_DIV (left, right, l);
4580 emitcode ("div", "ab");
4581 aopOp(result, ic, TRUE, FALSE);
4582 aopPut (AOP (result), "b", 0);
4586 /* signed is a little bit more difficult */
4588 /* save the signs of the operands */
4589 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4592 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4593 emitcode ("push", "acc"); /* save it on the stack */
4595 /* now sign adjust for both left & right */
4596 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4599 lbl = newiTempLabel (NULL);
4600 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4601 emitcode ("cpl", "a");
4602 emitcode ("inc", "a");
4603 emitcode ("", "%05d$:", (lbl->key + 100));
4604 emitcode ("mov", "b,a");
4606 /* sign adjust left side */
4607 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4610 lbl = newiTempLabel (NULL);
4611 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4612 emitcode ("cpl", "a");
4613 emitcode ("inc", "a");
4614 emitcode ("", "%05d$:", (lbl->key + 100));
4616 /* now the multiplication */
4617 emitcode ("nop", "; workaround for DS80C390 div bug.");
4618 emitcode ("div", "ab");
4619 /* we are interested in the lower order
4621 lbl = newiTempLabel (NULL);
4622 emitcode ("pop", "acc");
4623 /* if there was an over flow we don't
4624 adjust the sign of the result */
4625 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4626 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4628 emitcode ("clr", "a");
4629 emitcode ("subb", "a,b");
4630 emitcode ("mov", "b,a");
4631 emitcode ("", "%05d$:", (lbl->key + 100));
4633 /* now we are done */
4634 aopOp(result, ic, TRUE, FALSE);
4635 aopPut (AOP (result), "b", 0);
4639 /*-----------------------------------------------------------------*/
4640 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
4641 /*-----------------------------------------------------------------*/
4642 static void genModTwoByte (operand *left, operand *right,
4643 operand *result, iCode *ic)
4645 sym_link *retype = getSpec(operandType(right));
4646 sym_link *letype = getSpec(operandType(left));
4647 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4650 /* load up MA with left */
4652 lbl = newiTempLabel(NULL);
4653 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4654 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4655 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4656 emitcode ("xch", "a,b");
4657 emitcode ("cpl","a");
4658 emitcode ("add", "a,#1");
4659 emitcode ("xch", "a,b");
4660 emitcode ("cpl", "a"); // msb
4661 emitcode ("addc","a,#0");
4662 emitcode ("","%05d$:",lbl->key+100);
4663 emitcode ("mov","ma,b");
4664 emitcode ("mov","ma,a");
4666 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4667 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4670 /* load up MB with right */
4672 if (AOP_TYPE(right) == AOP_LIT) {
4673 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4677 emitcode ("mov","mb,#0x%02x",val & 0xff);
4678 emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4680 lbl = newiTempLabel(NULL);
4681 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4682 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4683 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4684 emitcode ("xch", "a,b");
4685 emitcode ("cpl","a");
4686 emitcode ("add", "a,#1");
4687 emitcode ("xch", "a,b");
4688 emitcode ("cpl", "a"); // msb
4689 emitcode ("addc", "a,#0");
4690 emitcode ("","%05d$:",lbl->key+100);
4691 emitcode ("mov","mb,b");
4692 emitcode ("mov","mb,a");
4695 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4696 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4699 /* wait for multiplication to finish */
4700 lbl = newiTempLabel(NULL);
4701 emitcode("","%05d$:", lbl->key+100);
4702 emitcode("mov","a,mcnt1");
4703 emitcode("anl","a,#0x80");
4704 emitcode("jnz","%05d$",lbl->key+100);
4706 freeAsmop (left, NULL, ic, TRUE);
4707 freeAsmop (right, NULL, ic,TRUE);
4708 aopOp(result, ic, TRUE, FALSE);
4710 aopPut(AOP(result),"mb",1);
4711 aopPut(AOP(result),"mb",0);
4712 freeAsmop (result, NULL, ic, TRUE);
4716 /*-----------------------------------------------------------------*/
4717 /* genMod - generates code for division */
4718 /*-----------------------------------------------------------------*/
4722 operand *left = IC_LEFT (ic);
4723 operand *right = IC_RIGHT (ic);
4724 operand *result = IC_RESULT (ic);
4726 D (emitcode (";", "genMod "); );
4728 /* assign the amsops */
4731 /* special cases first */
4733 if (AOP_TYPE (left) == AOP_CRY &&
4734 AOP_TYPE (right) == AOP_CRY)
4736 genModbits (left, right, result, ic);
4740 /* if both are of size == 1 */
4741 if (AOP_SIZE (left) == 1 &&
4742 AOP_SIZE (right) == 1)
4744 genModOneByte (left, right, result, ic);
4748 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4749 /* use the ds390 ARITHMETIC accel UNIT */
4750 genModTwoByte (left, right, result, ic);
4754 /* should have been converted to function call */
4758 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4759 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4760 freeAsmop (result, NULL, ic, TRUE);
4763 /*-----------------------------------------------------------------*/
4764 /* genIfxJump :- will create a jump depending on the ifx */
4765 /*-----------------------------------------------------------------*/
4767 genIfxJump (iCode * ic, char *jval)
4770 symbol *tlbl = newiTempLabel (NULL);
4773 D (emitcode (";", "genIfxJump ");
4776 /* if true label then we jump if condition
4780 jlbl = IC_TRUE (ic);
4781 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4782 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4786 /* false label is present */
4787 jlbl = IC_FALSE (ic);
4788 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4789 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4791 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4792 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4794 emitcode (inst, "%05d$", tlbl->key + 100);
4795 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4796 emitcode ("", "%05d$:", tlbl->key + 100);
4798 /* mark the icode as generated */
4802 /*-----------------------------------------------------------------*/
4803 /* genCmp :- greater or less than comparison */
4804 /*-----------------------------------------------------------------*/
4806 genCmp (operand * left, operand * right,
4807 iCode * ic, iCode * ifx, int sign)
4809 int size, offset = 0;
4810 unsigned long lit = 0L;
4813 D (emitcode (";", "genCmp");
4816 result = IC_RESULT (ic);
4818 /* if left & right are bit variables */
4819 if (AOP_TYPE (left) == AOP_CRY &&
4820 AOP_TYPE (right) == AOP_CRY)
4822 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4823 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4827 /* subtract right from left if at the
4828 end the carry flag is set then we know that
4829 left is greater than right */
4830 size = max (AOP_SIZE (left), AOP_SIZE (right));
4832 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4833 if ((size == 1) && !sign &&
4834 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4836 symbol *lbl = newiTempLabel (NULL);
4837 emitcode ("cjne", "%s,%s,%05d$",
4838 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4839 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4841 emitcode ("", "%05d$:", lbl->key + 100);
4845 if (AOP_TYPE (right) == AOP_LIT)
4847 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4848 /* optimize if(x < 0) or if(x >= 0) */
4857 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4859 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4860 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4862 aopOp (result, ic, FALSE, FALSE);
4864 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4866 freeAsmop (result, NULL, ic, TRUE);
4867 genIfxJump (ifx, "acc.7");
4872 emitcode ("rlc", "a");
4874 goto release_freedLR;
4882 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4883 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4884 emitcode (";", "genCmp #2");
4885 if (sign && (size == 0))
4887 emitcode (";", "genCmp #3");
4888 emitcode ("xrl", "a,#0x80");
4889 if (AOP_TYPE (right) == AOP_LIT)
4891 unsigned long lit = (unsigned long)
4892 floatFromVal (AOP (right)->aopu.aop_lit);
4893 emitcode (";", "genCmp #3.1");
4894 emitcode ("subb", "a,#0x%02x",
4895 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4899 emitcode (";", "genCmp #3.2");
4900 if (AOP_NEEDSACC (right))
4902 emitcode ("push", "acc");
4904 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4905 FALSE, FALSE, FALSE));
4906 emitcode ("xrl", "b,#0x80");
4907 if (AOP_NEEDSACC (right))
4909 emitcode ("pop", "acc");
4911 emitcode ("subb", "a,b");
4918 emitcode (";", "genCmp #4");
4919 if (AOP_NEEDSACC (right))
4922 emitcode (";", "genCmp #4.1");
4923 emitcode ("xch", "a, b");
4924 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4925 emitcode ("xch", "a, b");
4930 emitcode (";", "genCmp #4.2");
4931 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4934 emitcode ("subb", "a,%s", s);
4941 /* Don't need the left & right operands any more; do need the result. */
4942 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4943 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4945 aopOp (result, ic, FALSE, FALSE);
4949 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4955 /* if the result is used in the next
4956 ifx conditional branch then generate
4957 code a little differently */
4960 genIfxJump (ifx, "c");
4966 /* leave the result in acc */
4968 freeAsmop (result, NULL, ic, TRUE);
4971 /*-----------------------------------------------------------------*/
4972 /* genCmpGt :- greater than comparison */
4973 /*-----------------------------------------------------------------*/
4975 genCmpGt (iCode * ic, iCode * ifx)
4977 operand *left, *right;
4978 sym_link *letype, *retype;
4981 D (emitcode (";", "genCmpGt ");
4984 left = IC_LEFT (ic);
4985 right = IC_RIGHT (ic);
4987 letype = getSpec (operandType (left));
4988 retype = getSpec (operandType (right));
4989 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4991 /* assign the left & right amsops */
4994 genCmp (right, left, ic, ifx, sign);
4997 /*-----------------------------------------------------------------*/
4998 /* genCmpLt - less than comparisons */
4999 /*-----------------------------------------------------------------*/
5001 genCmpLt (iCode * ic, iCode * ifx)
5003 operand *left, *right;
5004 sym_link *letype, *retype;
5007 D (emitcode (";", "genCmpLt "););
5009 left = IC_LEFT (ic);
5010 right = IC_RIGHT (ic);
5012 letype = getSpec (operandType (left));
5013 retype = getSpec (operandType (right));
5014 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5016 /* assign the left & right amsops */
5019 genCmp (left, right, ic, ifx, sign);
5022 /*-----------------------------------------------------------------*/
5023 /* gencjneshort - compare and jump if not equal */
5024 /*-----------------------------------------------------------------*/
5026 gencjneshort (operand * left, operand * right, symbol * lbl)
5028 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5030 unsigned long lit = 0L;
5032 D (emitcode (";", "gencjneshort");
5035 /* if the left side is a literal or
5036 if the right is in a pointer register and left
5038 if ((AOP_TYPE (left) == AOP_LIT) ||
5039 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5046 if (AOP_TYPE (right) == AOP_LIT)
5047 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5049 if (opIsGptr (left) || opIsGptr (right))
5051 /* We are comparing a generic pointer to something.
5052 * Exclude the generic type byte from the comparison.
5055 D (emitcode (";", "cjneshort: generic ptr special case.");
5060 /* if the right side is a literal then anything goes */
5061 if (AOP_TYPE (right) == AOP_LIT &&
5062 AOP_TYPE (left) != AOP_DIR)
5066 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5068 emitcode ("cjne", "a,%s,%05d$",
5069 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5075 /* if the right side is in a register or in direct space or
5076 if the left is a pointer register & right is not */
5077 else if (AOP_TYPE (right) == AOP_REG ||
5078 AOP_TYPE (right) == AOP_DIR ||
5079 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5080 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5084 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5085 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5086 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5087 emitcode ("jnz", "%05d$", lbl->key + 100);
5089 emitcode ("cjne", "a,%s,%05d$",
5090 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5097 /* right is a pointer reg need both a & b */
5100 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5101 if (strcmp (l, "b"))
5102 emitcode ("mov", "b,%s", l);
5103 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5104 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5110 /*-----------------------------------------------------------------*/
5111 /* gencjne - compare and jump if not equal */
5112 /*-----------------------------------------------------------------*/
5114 gencjne (operand * left, operand * right, symbol * lbl)
5116 symbol *tlbl = newiTempLabel (NULL);
5118 D (emitcode (";", "gencjne");
5121 gencjneshort (left, right, lbl);
5123 emitcode ("mov", "a,%s", one);
5124 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5125 emitcode ("", "%05d$:", lbl->key + 100);
5126 emitcode ("clr", "a");
5127 emitcode ("", "%05d$:", tlbl->key + 100);
5130 /*-----------------------------------------------------------------*/
5131 /* genCmpEq - generates code for equal to */
5132 /*-----------------------------------------------------------------*/
5134 genCmpEq (iCode * ic, iCode * ifx)
5136 operand *left, *right, *result;
5138 D (emitcode (";", "genCmpEq ");
5142 AOP_SET_LOCALS (ic);
5144 /* if literal, literal on the right or
5145 if the right is in a pointer register and left
5147 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5148 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5150 operand *t = IC_RIGHT (ic);
5151 IC_RIGHT (ic) = IC_LEFT (ic);
5155 if (ifx && /* !AOP_SIZE(result) */
5156 OP_SYMBOL (result) &&
5157 OP_SYMBOL (result)->regType == REG_CND)
5160 /* if they are both bit variables */
5161 if (AOP_TYPE (left) == AOP_CRY &&
5162 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5164 if (AOP_TYPE (right) == AOP_LIT)
5166 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5169 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5170 emitcode ("cpl", "c");
5174 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5178 emitcode ("clr", "c");
5180 /* AOP_TYPE(right) == AOP_CRY */
5184 symbol *lbl = newiTempLabel (NULL);
5185 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5186 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5187 emitcode ("cpl", "c");
5188 emitcode ("", "%05d$:", (lbl->key + 100));
5190 /* if true label then we jump if condition
5192 tlbl = newiTempLabel (NULL);
5195 emitcode ("jnc", "%05d$", tlbl->key + 100);
5196 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5200 emitcode ("jc", "%05d$", tlbl->key + 100);
5201 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5203 emitcode ("", "%05d$:", tlbl->key + 100);
5207 tlbl = newiTempLabel (NULL);
5208 gencjneshort (left, right, tlbl);
5211 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5212 emitcode ("", "%05d$:", tlbl->key + 100);
5216 symbol *lbl = newiTempLabel (NULL);
5217 emitcode ("sjmp", "%05d$", lbl->key + 100);
5218 emitcode ("", "%05d$:", tlbl->key + 100);
5219 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5220 emitcode ("", "%05d$:", lbl->key + 100);
5223 /* mark the icode as generated */
5226 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5227 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5231 /* if they are both bit variables */
5232 if (AOP_TYPE (left) == AOP_CRY &&
5233 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5235 if (AOP_TYPE (right) == AOP_LIT)
5237 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5240 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5241 emitcode ("cpl", "c");
5245 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5249 emitcode ("clr", "c");
5251 /* AOP_TYPE(right) == AOP_CRY */
5255 symbol *lbl = newiTempLabel (NULL);
5256 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5257 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5258 emitcode ("cpl", "c");
5259 emitcode ("", "%05d$:", (lbl->key + 100));
5262 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5263 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5265 aopOp (result, ic, TRUE, FALSE);
5268 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5275 genIfxJump (ifx, "c");
5278 /* if the result is used in an arithmetic operation
5279 then put the result in place */
5284 gencjne (left, right, newiTempLabel (NULL));
5286 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5287 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5289 aopOp (result, ic, TRUE, FALSE);
5291 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5293 aopPut (AOP (result), "a", 0);
5298 genIfxJump (ifx, "a");
5301 /* if the result is used in an arithmetic operation
5302 then put the result in place */
5303 if (AOP_TYPE (result) != AOP_CRY)
5305 /* leave the result in acc */
5309 freeAsmop (result, NULL, ic, TRUE);
5312 /*-----------------------------------------------------------------*/
5313 /* ifxForOp - returns the icode containing the ifx for operand */
5314 /*-----------------------------------------------------------------*/
5316 ifxForOp (operand * op, iCode * ic)
5318 /* if true symbol then needs to be assigned */
5319 if (IS_TRUE_SYMOP (op))
5322 /* if this has register type condition and
5323 the next instruction is ifx with the same operand
5324 and live to of the operand is upto the ifx only then */
5326 ic->next->op == IFX &&
5327 IC_COND (ic->next)->key == op->key &&
5328 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5333 /*-----------------------------------------------------------------*/
5334 /* genAndOp - for && operation */
5335 /*-----------------------------------------------------------------*/
5337 genAndOp (iCode * ic)
5339 operand *left, *right, *result;
5342 D (emitcode (";", "genAndOp "););
5344 /* note here that && operations that are in an
5345 if statement are taken away by backPatchLabels
5346 only those used in arthmetic operations remain */
5348 AOP_SET_LOCALS (ic);
5350 /* if both are bit variables */
5351 if (AOP_TYPE (left) == AOP_CRY &&
5352 AOP_TYPE (right) == AOP_CRY)
5354 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5355 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5356 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5357 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5359 aopOp (result,ic,FALSE, FALSE);
5364 tlbl = newiTempLabel (NULL);
5366 emitcode ("jz", "%05d$", tlbl->key + 100);
5368 emitcode ("", "%05d$:", tlbl->key + 100);
5369 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5370 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5372 aopOp (result,ic,FALSE, FALSE);
5375 freeAsmop (result, NULL, ic, TRUE);
5379 /*-----------------------------------------------------------------*/
5380 /* genOrOp - for || operation */
5381 /*-----------------------------------------------------------------*/
5383 genOrOp (iCode * ic)
5385 operand *left, *right, *result;
5388 D (emitcode (";", "genOrOp "););
5390 /* note here that || operations that are in an
5391 if statement are taken away by backPatchLabels
5392 only those used in arthmetic operations remain */
5394 AOP_SET_LOCALS (ic);
5396 /* if both are bit variables */
5397 if (AOP_TYPE (left) == AOP_CRY &&
5398 AOP_TYPE (right) == AOP_CRY)
5400 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5401 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5402 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5403 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5405 aopOp (result,ic,FALSE, FALSE);
5411 tlbl = newiTempLabel (NULL);
5413 emitcode ("jnz", "%05d$", tlbl->key + 100);
5415 emitcode ("", "%05d$:", tlbl->key + 100);
5416 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5417 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5419 aopOp (result,ic,FALSE, FALSE);
5424 freeAsmop (result, NULL, ic, TRUE);
5427 /*-----------------------------------------------------------------*/
5428 /* isLiteralBit - test if lit == 2^n */
5429 /*-----------------------------------------------------------------*/
5431 isLiteralBit (unsigned long lit)
5433 unsigned long pw[32] =
5434 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5435 0x100L, 0x200L, 0x400L, 0x800L,
5436 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5437 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5438 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5439 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5440 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5443 for (idx = 0; idx < 32; idx++)
5449 /*-----------------------------------------------------------------*/
5450 /* continueIfTrue - */
5451 /*-----------------------------------------------------------------*/
5453 continueIfTrue (iCode * ic)
5456 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5460 /*-----------------------------------------------------------------*/
5462 /*-----------------------------------------------------------------*/
5464 jumpIfTrue (iCode * ic)
5467 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5471 /*-----------------------------------------------------------------*/
5472 /* jmpTrueOrFalse - */
5473 /*-----------------------------------------------------------------*/
5475 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5477 // ugly but optimized by peephole
5480 symbol *nlbl = newiTempLabel (NULL);
5481 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5482 emitcode ("", "%05d$:", tlbl->key + 100);
5483 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5484 emitcode ("", "%05d$:", nlbl->key + 100);
5488 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5489 emitcode ("", "%05d$:", tlbl->key + 100);
5494 // Generate code to perform a bit-wise logic operation
5495 // on two operands in far space (assumed to already have been
5496 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5497 // in far space. This requires pushing the result on the stack
5498 // then popping it into the result.
5500 genFarFarLogicOp(iCode *ic, char *logicOp)
5502 int size, resultSize, compSize;
5506 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5507 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5508 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5510 _startLazyDPSEvaluation();
5511 for (size = compSize; (size--); offset++)
5513 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5514 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5515 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5517 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5518 emitcode ("push", "acc");
5520 _endLazyDPSEvaluation();
5522 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5523 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5524 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5526 resultSize = AOP_SIZE(IC_RESULT(ic));
5528 ADJUST_PUSHED_RESULT(compSize, resultSize);
5530 _startLazyDPSEvaluation();
5533 emitcode ("pop", "acc");
5534 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5536 _endLazyDPSEvaluation();
5537 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5541 /*-----------------------------------------------------------------*/
5542 /* genAnd - code for and */
5543 /*-----------------------------------------------------------------*/
5545 genAnd (iCode * ic, iCode * ifx)
5547 operand *left, *right, *result;
5548 int size, offset = 0;
5549 unsigned long lit = 0L;
5554 D (emitcode (";", "genAnd "););
5556 AOP_OP_3_NOFATAL (ic, pushResult);
5557 AOP_SET_LOCALS (ic);
5561 genFarFarLogicOp(ic, "anl");
5566 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5568 AOP_TYPE (left), AOP_TYPE (right));
5569 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5571 AOP_SIZE (left), AOP_SIZE (right));
5574 /* if left is a literal & right is not then exchange them */
5575 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5576 #ifdef LOGIC_OPS_BROKEN
5577 || AOP_NEEDSACC (left)
5581 operand *tmp = right;
5586 /* if result = right then exchange them */
5587 if (sameRegs (AOP (result), AOP (right)))
5589 operand *tmp = right;
5594 /* if right is bit then exchange them */
5595 if (AOP_TYPE (right) == AOP_CRY &&
5596 AOP_TYPE (left) != AOP_CRY)
5598 operand *tmp = right;
5602 if (AOP_TYPE (right) == AOP_LIT)
5603 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5605 size = AOP_SIZE (result);
5608 // result = bit & yy;
5609 if (AOP_TYPE (left) == AOP_CRY)
5611 // c = bit & literal;
5612 if (AOP_TYPE (right) == AOP_LIT)
5616 if (size && sameRegs (AOP (result), AOP (left)))
5619 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5624 if (size && (AOP_TYPE (result) == AOP_CRY))
5626 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5629 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5634 emitcode ("clr", "c");
5639 if (AOP_TYPE (right) == AOP_CRY)
5642 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5643 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5648 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5650 emitcode ("rrc", "a");
5651 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5659 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5660 genIfxJump (ifx, "c");
5664 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5665 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5666 if ((AOP_TYPE (right) == AOP_LIT) &&
5667 (AOP_TYPE (result) == AOP_CRY) &&
5668 (AOP_TYPE (left) != AOP_CRY))
5670 int posbit = isLiteralBit (lit);
5675 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5678 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5684 sprintf (buffer, "acc.%d", posbit & 0x07);
5685 genIfxJump (ifx, buffer);
5692 symbol *tlbl = newiTempLabel (NULL);
5693 int sizel = AOP_SIZE (left);
5695 emitcode ("setb", "c");
5698 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5700 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5702 if ((posbit = isLiteralBit (bytelit)) != 0)
5703 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5706 if (bytelit != 0x0FFL)
5707 emitcode ("anl", "a,%s",
5708 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5709 emitcode ("jnz", "%05d$", tlbl->key + 100);
5714 // bit = left & literal
5717 emitcode ("clr", "c");
5718 emitcode ("", "%05d$:", tlbl->key + 100);
5720 // if(left & literal)
5724 jmpTrueOrFalse (ifx, tlbl);
5732 /* if left is same as result */
5733 if (sameRegs (AOP (result), AOP (left)))
5735 for (; size--; offset++)
5737 if (AOP_TYPE (right) == AOP_LIT)
5739 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5741 else if (bytelit == 0)
5742 aopPut (AOP (result), zero, offset);
5743 else if (IS_AOP_PREG (result))
5745 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5746 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5747 aopPut (AOP (result), "a", offset);
5750 emitcode ("anl", "%s,%s",
5751 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5752 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5756 if (AOP_TYPE (left) == AOP_ACC)
5757 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5760 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5761 if (IS_AOP_PREG (result))
5763 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5764 aopPut (AOP (result), "a", offset);
5768 emitcode ("anl", "%s,a",
5769 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5776 // left & result in different registers
5777 if (AOP_TYPE (result) == AOP_CRY)
5780 // if(size), result in bit
5781 // if(!size && ifx), conditional oper: if(left & right)
5782 symbol *tlbl = newiTempLabel (NULL);
5783 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5785 emitcode ("setb", "c");
5788 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5789 emitcode ("anl", "a,%s",
5790 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5792 if (AOP_TYPE(left)==AOP_ACC) {
5793 emitcode("mov", "b,a");
5794 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5795 emitcode("anl", "a,b");
5797 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5798 emitcode ("anl", "a,%s",
5799 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5802 emitcode ("jnz", "%05d$", tlbl->key + 100);
5808 emitcode ("", "%05d$:", tlbl->key + 100);
5812 jmpTrueOrFalse (ifx, tlbl);
5816 for (; (size--); offset++)
5819 // result = left & right
5820 if (AOP_TYPE (right) == AOP_LIT)
5822 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5824 aopPut (AOP (result),
5825 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5829 else if (bytelit == 0)
5831 aopPut (AOP (result), zero, offset);
5834 D (emitcode (";", "better literal AND."););
5835 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5836 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5837 FALSE, FALSE, FALSE));
5842 // faster than result <- left, anl result,right
5843 // and better if result is SFR
5844 if (AOP_TYPE (left) == AOP_ACC)
5846 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5847 FALSE, FALSE, FALSE));
5851 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
5852 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
5854 emitcode("mov", "b,a");
5858 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5859 emitcode ("anl", "a,%s", rOp);
5862 aopPut (AOP (result), "a", offset);
5868 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5869 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5870 freeAsmop (result, NULL, ic, TRUE);
5874 /*-----------------------------------------------------------------*/
5875 /* genOr - code for or */
5876 /*-----------------------------------------------------------------*/
5878 genOr (iCode * ic, iCode * ifx)
5880 operand *left, *right, *result;
5881 int size, offset = 0;
5882 unsigned long lit = 0L;
5885 D (emitcode (";", "genOr "););
5887 AOP_OP_3_NOFATAL (ic, pushResult);
5888 AOP_SET_LOCALS (ic);
5892 genFarFarLogicOp(ic, "orl");
5898 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5900 AOP_TYPE (left), AOP_TYPE (right));
5901 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5903 AOP_SIZE (left), AOP_SIZE (right));
5906 /* if left is a literal & right is not then exchange them */
5907 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5908 #ifdef LOGIC_OPS_BROKEN
5909 || AOP_NEEDSACC (left) // I think this is a net loss now.
5913 operand *tmp = right;
5918 /* if result = right then exchange them */
5919 if (sameRegs (AOP (result), AOP (right)))
5921 operand *tmp = right;
5926 /* if right is bit then exchange them */
5927 if (AOP_TYPE (right) == AOP_CRY &&
5928 AOP_TYPE (left) != AOP_CRY)
5930 operand *tmp = right;
5934 if (AOP_TYPE (right) == AOP_LIT)
5935 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5937 size = AOP_SIZE (result);
5941 if (AOP_TYPE (left) == AOP_CRY)
5943 if (AOP_TYPE (right) == AOP_LIT)
5945 // c = bit & literal;
5948 // lit != 0 => result = 1
5949 if (AOP_TYPE (result) == AOP_CRY)
5952 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5954 continueIfTrue (ifx);
5957 emitcode ("setb", "c");
5961 // lit == 0 => result = left
5962 if (size && sameRegs (AOP (result), AOP (left)))
5964 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5969 if (AOP_TYPE (right) == AOP_CRY)
5972 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5973 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5978 symbol *tlbl = newiTempLabel (NULL);
5979 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5980 emitcode ("setb", "c");
5981 emitcode ("jb", "%s,%05d$",
5982 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5984 emitcode ("jnz", "%05d$", tlbl->key + 100);
5985 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5987 jmpTrueOrFalse (ifx, tlbl);
5993 emitcode ("", "%05d$:", tlbl->key + 100);
6002 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6003 genIfxJump (ifx, "c");
6007 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6008 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6009 if ((AOP_TYPE (right) == AOP_LIT) &&
6010 (AOP_TYPE (result) == AOP_CRY) &&
6011 (AOP_TYPE (left) != AOP_CRY))
6017 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6019 continueIfTrue (ifx);
6024 // lit = 0, result = boolean(left)
6026 emitcode ("setb", "c");
6030 symbol *tlbl = newiTempLabel (NULL);
6031 emitcode ("jnz", "%05d$", tlbl->key + 100);
6033 emitcode ("", "%05d$:", tlbl->key + 100);
6037 genIfxJump (ifx, "a");
6045 /* if left is same as result */
6046 if (sameRegs (AOP (result), AOP (left)))
6048 for (; size--; offset++)
6050 if (AOP_TYPE (right) == AOP_LIT)
6052 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6058 if (IS_AOP_PREG (left))
6060 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6061 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6062 aopPut (AOP (result), "a", offset);
6066 emitcode ("orl", "%s,%s",
6067 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6068 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6074 if (AOP_TYPE (left) == AOP_ACC)
6076 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6080 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6081 if (IS_AOP_PREG (left))
6083 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6084 aopPut (AOP (result), "a", offset);
6088 emitcode ("orl", "%s,a",
6089 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6097 // left & result in different registers
6098 if (AOP_TYPE (result) == AOP_CRY)
6101 // if(size), result in bit
6102 // if(!size && ifx), conditional oper: if(left | right)
6103 symbol *tlbl = newiTempLabel (NULL);
6104 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6106 emitcode ("setb", "c");
6109 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6110 emitcode ("orl", "a,%s",
6111 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6113 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6114 emitcode ("orl", "a,%s",
6115 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6117 emitcode ("jnz", "%05d$", tlbl->key + 100);
6123 emitcode ("", "%05d$:", tlbl->key + 100);
6127 jmpTrueOrFalse (ifx, tlbl);
6131 _startLazyDPSEvaluation();
6132 for (; (size--); offset++)
6135 // result = left & right
6136 if (AOP_TYPE (right) == AOP_LIT)
6138 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6140 aopPut (AOP (result),
6141 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6145 D (emitcode (";", "better literal OR."););
6146 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6147 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6148 FALSE, FALSE, FALSE));
6153 // faster than result <- left, anl result,right
6154 // and better if result is SFR
6155 if (AOP_TYPE (left) == AOP_ACC)
6157 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6158 FALSE, FALSE, FALSE));
6162 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6164 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6166 emitcode("mov", "b,a");
6170 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6171 emitcode ("orl", "a,%s", rOp);
6174 aopPut (AOP (result), "a", offset);
6176 _endLazyDPSEvaluation();
6181 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6182 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6183 freeAsmop (result, NULL, ic, TRUE);
6186 /*-----------------------------------------------------------------*/
6187 /* genXor - code for xclusive or */
6188 /*-----------------------------------------------------------------*/
6190 genXor (iCode * ic, iCode * ifx)
6192 operand *left, *right, *result;
6193 int size, offset = 0;
6194 unsigned long lit = 0L;
6197 D (emitcode (";", "genXor "););
6199 AOP_OP_3_NOFATAL (ic, pushResult);
6200 AOP_SET_LOCALS (ic);
6204 genFarFarLogicOp(ic, "xrl");
6209 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6211 AOP_TYPE (left), AOP_TYPE (right));
6212 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6214 AOP_SIZE (left), AOP_SIZE (right));
6217 /* if left is a literal & right is not ||
6218 if left needs acc & right does not */
6219 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6220 #ifdef LOGIC_OPS_BROKEN
6221 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6225 operand *tmp = right;
6230 /* if result = right then exchange them */
6231 if (sameRegs (AOP (result), AOP (right)))
6233 operand *tmp = right;
6238 /* if right is bit then exchange them */
6239 if (AOP_TYPE (right) == AOP_CRY &&
6240 AOP_TYPE (left) != AOP_CRY)
6242 operand *tmp = right;
6246 if (AOP_TYPE (right) == AOP_LIT)
6247 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6249 size = AOP_SIZE (result);
6253 if (AOP_TYPE (left) == AOP_CRY)
6255 if (AOP_TYPE (right) == AOP_LIT)
6257 // c = bit & literal;
6260 // lit>>1 != 0 => result = 1
6261 if (AOP_TYPE (result) == AOP_CRY)
6264 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6266 continueIfTrue (ifx);
6269 emitcode ("setb", "c");
6276 // lit == 0, result = left
6277 if (size && sameRegs (AOP (result), AOP (left)))
6279 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6283 // lit == 1, result = not(left)
6284 if (size && sameRegs (AOP (result), AOP (left)))
6286 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6291 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6292 emitcode ("cpl", "c");
6301 symbol *tlbl = newiTempLabel (NULL);
6302 if (AOP_TYPE (right) == AOP_CRY)
6305 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6309 int sizer = AOP_SIZE (right);
6311 // if val>>1 != 0, result = 1
6312 emitcode ("setb", "c");
6315 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6317 // test the msb of the lsb
6318 emitcode ("anl", "a,#0xfe");
6319 emitcode ("jnz", "%05d$", tlbl->key + 100);
6323 emitcode ("rrc", "a");
6325 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6326 emitcode ("cpl", "c");
6327 emitcode ("", "%05d$:", (tlbl->key + 100));
6334 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6335 genIfxJump (ifx, "c");
6339 if (sameRegs (AOP (result), AOP (left)))
6341 /* if left is same as result */
6342 for (; size--; offset++)
6344 if (AOP_TYPE (right) == AOP_LIT)
6346 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6348 else if (IS_AOP_PREG (left))
6350 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6351 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6352 aopPut (AOP (result), "a", offset);
6355 emitcode ("xrl", "%s,%s",
6356 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6357 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6361 if (AOP_TYPE (left) == AOP_ACC)
6362 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6365 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6366 if (IS_AOP_PREG (left))
6368 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6369 aopPut (AOP (result), "a", offset);
6372 emitcode ("xrl", "%s,a",
6373 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6380 // left & result in different registers
6381 if (AOP_TYPE (result) == AOP_CRY)
6384 // if(size), result in bit
6385 // if(!size && ifx), conditional oper: if(left ^ right)
6386 symbol *tlbl = newiTempLabel (NULL);
6387 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6389 emitcode ("setb", "c");
6392 if ((AOP_TYPE (right) == AOP_LIT) &&
6393 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6395 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6399 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6400 emitcode ("xrl", "a,%s",
6401 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6403 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6404 emitcode ("xrl", "a,%s",
6405 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6408 emitcode ("jnz", "%05d$", tlbl->key + 100);
6414 emitcode ("", "%05d$:", tlbl->key + 100);
6418 jmpTrueOrFalse (ifx, tlbl);
6421 for (; (size--); offset++)
6424 // result = left & right
6425 if (AOP_TYPE (right) == AOP_LIT)
6427 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6429 aopPut (AOP (result),
6430 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6434 D (emitcode (";", "better literal XOR.");
6436 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6437 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6438 FALSE, FALSE, FALSE));
6442 // faster than result <- left, anl result,right
6443 // and better if result is SFR
6444 if (AOP_TYPE (left) == AOP_ACC)
6446 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6447 FALSE, FALSE, FALSE));
6451 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6452 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6454 emitcode("mov", "b,a");
6458 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6459 emitcode ("xrl", "a,%s", rOp);
6462 aopPut (AOP (result), "a", offset);
6467 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6468 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6469 freeAsmop (result, NULL, ic, TRUE);
6472 /*-----------------------------------------------------------------*/
6473 /* genInline - write the inline code out */
6474 /*-----------------------------------------------------------------*/
6476 genInline (iCode * ic)
6478 char *buffer, *bp, *bp1;
6480 D (emitcode (";", "genInline ");
6483 _G.inLine += (!options.asmpeep);
6485 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6486 strcpy (buffer, IC_INLINE (ic));
6488 /* emit each line as a code */
6513 /* emitcode("",buffer); */
6514 _G.inLine -= (!options.asmpeep);
6517 /*-----------------------------------------------------------------*/
6518 /* genRRC - rotate right with carry */
6519 /*-----------------------------------------------------------------*/
6523 operand *left, *result;
6524 int size, offset = 0;
6527 D (emitcode (";", "genRRC ");
6530 /* rotate right with carry */
6531 left = IC_LEFT (ic);
6532 result = IC_RESULT (ic);
6533 aopOp (left, ic, FALSE, FALSE);
6534 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6536 /* move it to the result */
6537 size = AOP_SIZE (result);
6541 _startLazyDPSEvaluation ();
6544 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6546 emitcode ("rrc", "a");
6547 if (AOP_SIZE (result) > 1)
6548 aopPut (AOP (result), "a", offset--);
6550 _endLazyDPSEvaluation ();
6552 /* now we need to put the carry into the
6553 highest order byte of the result */
6554 if (AOP_SIZE (result) > 1)
6556 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6559 emitcode ("mov", "acc.7,c");
6560 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6561 freeAsmop (left, NULL, ic, TRUE);
6562 freeAsmop (result, NULL, ic, TRUE);
6565 /*-----------------------------------------------------------------*/
6566 /* genRLC - generate code for rotate left with carry */
6567 /*-----------------------------------------------------------------*/
6571 operand *left, *result;
6572 int size, offset = 0;
6575 D (emitcode (";", "genRLC ");
6578 /* rotate right with carry */
6579 left = IC_LEFT (ic);
6580 result = IC_RESULT (ic);
6581 aopOp (left, ic, FALSE, FALSE);
6582 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6584 /* move it to the result */
6585 size = AOP_SIZE (result);
6589 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6591 emitcode ("add", "a,acc");
6592 if (AOP_SIZE (result) > 1)
6594 aopPut (AOP (result), "a", offset++);
6597 _startLazyDPSEvaluation ();
6600 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6602 emitcode ("rlc", "a");
6603 if (AOP_SIZE (result) > 1)
6604 aopPut (AOP (result), "a", offset++);
6606 _endLazyDPSEvaluation ();
6608 /* now we need to put the carry into the
6609 highest order byte of the result */
6610 if (AOP_SIZE (result) > 1)
6612 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6615 emitcode ("mov", "acc.0,c");
6616 aopPut (AOP (result), "a", 0);
6617 freeAsmop (left, NULL, ic, TRUE);
6618 freeAsmop (result, NULL, ic, TRUE);
6621 /*-----------------------------------------------------------------*/
6622 /* genGetHbit - generates code get highest order bit */
6623 /*-----------------------------------------------------------------*/
6625 genGetHbit (iCode * ic)
6627 operand *left, *result;
6628 left = IC_LEFT (ic);
6629 result = IC_RESULT (ic);
6630 aopOp (left, ic, FALSE, FALSE);
6631 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6633 D (emitcode (";", "genGetHbit ");
6636 /* get the highest order byte into a */
6637 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6638 if (AOP_TYPE (result) == AOP_CRY)
6640 emitcode ("rlc", "a");
6645 emitcode ("rl", "a");
6646 emitcode ("anl", "a,#0x01");
6651 freeAsmop (left, NULL, ic, TRUE);
6652 freeAsmop (result, NULL, ic, TRUE);
6655 /*-----------------------------------------------------------------*/
6656 /* AccRol - rotate left accumulator by known count */
6657 /*-----------------------------------------------------------------*/
6659 AccRol (int shCount)
6661 shCount &= 0x0007; // shCount : 0..7
6668 emitcode ("rl", "a");
6671 emitcode ("rl", "a");
6672 emitcode ("rl", "a");
6675 emitcode ("swap", "a");
6676 emitcode ("rr", "a");
6679 emitcode ("swap", "a");
6682 emitcode ("swap", "a");
6683 emitcode ("rl", "a");
6686 emitcode ("rr", "a");
6687 emitcode ("rr", "a");
6690 emitcode ("rr", "a");
6695 /*-----------------------------------------------------------------*/
6696 /* AccLsh - left shift accumulator by known count */
6697 /*-----------------------------------------------------------------*/
6699 AccLsh (int shCount)
6704 emitcode ("add", "a,acc");
6705 else if (shCount == 2)
6707 emitcode ("add", "a,acc");
6708 emitcode ("add", "a,acc");
6712 /* rotate left accumulator */
6714 /* and kill the lower order bits */
6715 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6720 /*-----------------------------------------------------------------*/
6721 /* AccRsh - right shift accumulator by known count */
6722 /*-----------------------------------------------------------------*/
6724 AccRsh (int shCount)
6731 emitcode ("rrc", "a");
6735 /* rotate right accumulator */
6736 AccRol (8 - shCount);
6737 /* and kill the higher order bits */
6738 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6743 #ifdef BETTER_LITERAL_SHIFT
6744 /*-----------------------------------------------------------------*/
6745 /* AccSRsh - signed right shift accumulator by known count */
6746 /*-----------------------------------------------------------------*/
6748 AccSRsh (int shCount)
6755 emitcode ("mov", "c,acc.7");
6756 emitcode ("rrc", "a");
6758 else if (shCount == 2)
6760 emitcode ("mov", "c,acc.7");
6761 emitcode ("rrc", "a");
6762 emitcode ("mov", "c,acc.7");
6763 emitcode ("rrc", "a");
6767 tlbl = newiTempLabel (NULL);
6768 /* rotate right accumulator */
6769 AccRol (8 - shCount);
6770 /* and kill the higher order bits */
6771 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6772 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6773 emitcode ("orl", "a,#0x%02x",
6774 (unsigned char) ~SRMask[shCount]);
6775 emitcode ("", "%05d$:", tlbl->key + 100);
6781 #ifdef BETTER_LITERAL_SHIFT
6782 /*-----------------------------------------------------------------*/
6783 /* shiftR1Left2Result - shift right one byte from left to result */
6784 /*-----------------------------------------------------------------*/
6786 shiftR1Left2Result (operand * left, int offl,
6787 operand * result, int offr,
6788 int shCount, int sign)
6790 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6791 /* shift right accumulator */
6796 aopPut (AOP (result), "a", offr);
6800 #ifdef BETTER_LITERAL_SHIFT
6801 /*-----------------------------------------------------------------*/
6802 /* shiftL1Left2Result - shift left one byte from left to result */
6803 /*-----------------------------------------------------------------*/
6805 shiftL1Left2Result (operand * left, int offl,
6806 operand * result, int offr, int shCount)
6808 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6809 /* shift left accumulator */
6811 aopPut (AOP (result), "a", offr);
6815 #ifdef BETTER_LITERAL_SHIFT
6816 /*-----------------------------------------------------------------*/
6817 /* movLeft2Result - move byte from left to result */
6818 /*-----------------------------------------------------------------*/
6820 movLeft2Result (operand * left, int offl,
6821 operand * result, int offr, int sign)
6824 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6826 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6828 if (*l == '@' && (IS_AOP_PREG (result)))
6830 emitcode ("mov", "a,%s", l);
6831 aopPut (AOP (result), "a", offr);
6837 aopPut (AOP (result), l, offr);
6841 /* MSB sign in acc.7 ! */
6842 if (getDataSize (left) == offl + 1)
6844 emitcode ("mov", "a,%s", l);
6845 aopPut (AOP (result), "a", offr);
6853 #ifdef BETTER_LITERAL_SHIFT
6854 /*-----------------------------------------------------------------*/
6855 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6856 /*-----------------------------------------------------------------*/
6860 emitcode ("rrc", "a");
6861 emitcode ("xch", "a,%s", x);
6862 emitcode ("rrc", "a");
6863 emitcode ("xch", "a,%s", x);
6867 #ifdef BETTER_LITERAL_SHIFT
6869 /*-----------------------------------------------------------------*/
6870 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6871 /*-----------------------------------------------------------------*/
6875 emitcode ("xch", "a,%s", x);
6876 emitcode ("rlc", "a");
6877 emitcode ("xch", "a,%s", x);
6878 emitcode ("rlc", "a");
6882 #ifdef BETTER_LITERAL_SHIFT
6883 /*-----------------------------------------------------------------*/
6884 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6885 /*-----------------------------------------------------------------*/
6889 emitcode ("xch", "a,%s", x);
6890 emitcode ("add", "a,acc");
6891 emitcode ("xch", "a,%s", x);
6892 emitcode ("rlc", "a");
6896 #ifdef BETTER_LITERAL_SHIFT
6897 /*-----------------------------------------------------------------*/
6898 /* AccAXLsh - left shift a:x by known count (0..7) */
6899 /*-----------------------------------------------------------------*/
6901 AccAXLsh (char *x, int shCount)
6916 case 5: // AAAAABBB:CCCCCDDD
6918 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6920 emitcode ("anl", "a,#0x%02x",
6921 SLMask[shCount]); // BBB00000:CCCCCDDD
6923 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6925 AccRol (shCount); // DDDCCCCC:BBB00000
6927 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6929 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6931 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6933 emitcode ("anl", "a,#0x%02x",
6934 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6936 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6938 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6941 case 6: // AAAAAABB:CCCCCCDD
6942 emitcode ("anl", "a,#0x%02x",
6943 SRMask[shCount]); // 000000BB:CCCCCCDD
6944 emitcode ("mov", "c,acc.0"); // c = B
6945 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6947 AccAXRrl1 (x); // BCCCCCCD:D000000B
6948 AccAXRrl1 (x); // BBCCCCCC:DD000000
6950 emitcode("rrc","a");
6951 emitcode("xch","a,%s", x);
6952 emitcode("rrc","a");
6953 emitcode("mov","c,acc.0"); //<< get correct bit
6954 emitcode("xch","a,%s", x);
6956 emitcode("rrc","a");
6957 emitcode("xch","a,%s", x);
6958 emitcode("rrc","a");
6959 emitcode("xch","a,%s", x);
6962 case 7: // a:x <<= 7
6964 emitcode ("anl", "a,#0x%02x",
6965 SRMask[shCount]); // 0000000B:CCCCCCCD
6967 emitcode ("mov", "c,acc.0"); // c = B
6969 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6971 AccAXRrl1 (x); // BCCCCCCC:D0000000
6980 #ifdef BETTER_LITERAL_SHIFT
6982 /*-----------------------------------------------------------------*/
6983 /* AccAXRsh - right shift a:x known count (0..7) */
6984 /*-----------------------------------------------------------------*/
6986 AccAXRsh (char *x, int shCount)
6994 AccAXRrl1 (x); // 0->a:x
6999 AccAXRrl1 (x); // 0->a:x
7002 AccAXRrl1 (x); // 0->a:x
7007 case 5: // AAAAABBB:CCCCCDDD = a:x
7009 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7011 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7013 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7015 emitcode ("anl", "a,#0x%02x",
7016 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7018 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7020 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7022 emitcode ("anl", "a,#0x%02x",
7023 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7025 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7027 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7029 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7032 case 6: // AABBBBBB:CCDDDDDD
7034 emitcode ("mov", "c,acc.7");
7035 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7037 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7039 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7041 emitcode ("anl", "a,#0x%02x",
7042 SRMask[shCount]); // 000000AA:BBBBBBCC
7045 case 7: // ABBBBBBB:CDDDDDDD
7047 emitcode ("mov", "c,acc.7"); // c = A
7049 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7051 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7053 emitcode ("anl", "a,#0x%02x",
7054 SRMask[shCount]); // 0000000A:BBBBBBBC
7063 #ifdef BETTER_LITERAL_SHIFT
7064 /*-----------------------------------------------------------------*/
7065 /* AccAXRshS - right shift signed a:x known count (0..7) */
7066 /*-----------------------------------------------------------------*/
7068 AccAXRshS (char *x, int shCount)
7076 emitcode ("mov", "c,acc.7");
7077 AccAXRrl1 (x); // s->a:x
7081 emitcode ("mov", "c,acc.7");
7082 AccAXRrl1 (x); // s->a:x
7084 emitcode ("mov", "c,acc.7");
7085 AccAXRrl1 (x); // s->a:x
7090 case 5: // AAAAABBB:CCCCCDDD = a:x
7092 tlbl = newiTempLabel (NULL);
7093 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7095 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7097 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7099 emitcode ("anl", "a,#0x%02x",
7100 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7102 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7104 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7106 emitcode ("anl", "a,#0x%02x",
7107 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7109 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7111 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7113 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7115 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7116 emitcode ("orl", "a,#0x%02x",
7117 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7119 emitcode ("", "%05d$:", tlbl->key + 100);
7120 break; // SSSSAAAA:BBBCCCCC
7122 case 6: // AABBBBBB:CCDDDDDD
7124 tlbl = newiTempLabel (NULL);
7125 emitcode ("mov", "c,acc.7");
7126 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7128 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7130 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7132 emitcode ("anl", "a,#0x%02x",
7133 SRMask[shCount]); // 000000AA:BBBBBBCC
7135 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7136 emitcode ("orl", "a,#0x%02x",
7137 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7139 emitcode ("", "%05d$:", tlbl->key + 100);
7141 case 7: // ABBBBBBB:CDDDDDDD
7143 tlbl = newiTempLabel (NULL);
7144 emitcode ("mov", "c,acc.7"); // c = A
7146 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7148 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7150 emitcode ("anl", "a,#0x%02x",
7151 SRMask[shCount]); // 0000000A:BBBBBBBC
7153 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7154 emitcode ("orl", "a,#0x%02x",
7155 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7157 emitcode ("", "%05d$:", tlbl->key + 100);
7165 #ifdef BETTER_LITERAL_SHIFT
7167 _loadLeftIntoAx(char **lsb,
7173 // Get the initial value from left into a pair of registers.
7174 // MSB must be in A, LSB can be any register.
7176 // If the result is held in registers, it is an optimization
7177 // if the LSB can be held in the register which will hold the,
7178 // result LSB since this saves us from having to copy it into
7179 // the result following AccAXLsh.
7181 // If the result is addressed indirectly, this is not a gain.
7182 if (AOP_NEEDSACC(result))
7186 _startLazyDPSEvaluation();
7187 if (AOP_TYPE(left) == AOP_DPTR2)
7190 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7191 // get LSB in DP2_RESULT_REG.
7192 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7193 assert(!strcmp(leftByte, DP2_RESULT_REG));
7197 // get LSB into DP2_RESULT_REG
7198 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7199 if (strcmp(leftByte, DP2_RESULT_REG))
7202 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7205 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7206 assert(strcmp(leftByte, DP2_RESULT_REG));
7209 _endLazyDPSEvaluation();
7210 *lsb = DP2_RESULT_REG;
7214 if (sameRegs (AOP (result), AOP (left)) &&
7215 ((offl + MSB16) == offr))
7217 /* don't crash result[offr] */
7218 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7219 emitcode ("xch", "a,%s",
7220 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7224 movLeft2Result (left, offl, result, offr, 0);
7225 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7227 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7228 assert(strcmp(*lsb,"a"));
7233 _storeAxResults(char *lsb,
7237 _startLazyDPSEvaluation();
7238 if (AOP_NEEDSACC(result))
7240 /* We have to explicitly update the result LSB.
7242 emitcode("xch","a,%s", lsb);
7243 aopPut(AOP(result), "a", offr);
7244 emitcode("mov","a,%s", lsb);
7246 if (getDataSize (result) > 1)
7248 aopPut (AOP (result), "a", offr + MSB16);
7250 _endLazyDPSEvaluation();
7253 /*-----------------------------------------------------------------*/
7254 /* shiftL2Left2Result - shift left two bytes from left to result */
7255 /*-----------------------------------------------------------------*/
7257 shiftL2Left2Result (operand * left, int offl,
7258 operand * result, int offr, int shCount)
7262 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7264 AccAXLsh (lsb, shCount);
7266 _storeAxResults(lsb, result, offr);
7270 #ifdef BETTER_LITERAL_SHIFT
7271 /*-----------------------------------------------------------------*/
7272 /* shiftR2Left2Result - shift right two bytes from left to result */
7273 /*-----------------------------------------------------------------*/
7275 shiftR2Left2Result (operand * left, int offl,
7276 operand * result, int offr,
7277 int shCount, int sign)
7281 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7283 /* a:x >> shCount (x = lsb(result)) */
7286 AccAXRshS(lsb, shCount);
7290 AccAXRsh(lsb, shCount);
7293 _storeAxResults(lsb, result, offr);
7299 /*-----------------------------------------------------------------*/
7300 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7301 /*-----------------------------------------------------------------*/
7303 shiftLLeftOrResult (operand * left, int offl,
7304 operand * result, int offr, int shCount)
7306 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7307 /* shift left accumulator */
7309 /* or with result */
7310 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7311 /* back to result */
7312 aopPut (AOP (result), "a", offr);
7318 /*-----------------------------------------------------------------*/
7319 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7320 /*-----------------------------------------------------------------*/
7322 shiftRLeftOrResult (operand * left, int offl,
7323 operand * result, int offr, int shCount)
7325 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7326 /* shift right accumulator */
7328 /* or with result */
7329 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7330 /* back to result */
7331 aopPut (AOP (result), "a", offr);
7335 #ifdef BETTER_LITERAL_SHIFT
7336 /*-----------------------------------------------------------------*/
7337 /* genlshOne - left shift a one byte quantity by known count */
7338 /*-----------------------------------------------------------------*/
7340 genlshOne (operand * result, operand * left, int shCount)
7342 D (emitcode (";", "genlshOne "););
7343 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7347 #ifdef BETTER_LITERAL_SHIFT
7348 /*-----------------------------------------------------------------*/
7349 /* genlshTwo - left shift two bytes by known amount != 0 */
7350 /*-----------------------------------------------------------------*/
7352 genlshTwo (operand * result, operand * left, int shCount)
7356 D (emitcode (";", "genlshTwo "););
7358 size = getDataSize (result);
7360 /* if shCount >= 8 */
7365 _startLazyDPSEvaluation();
7371 _endLazyDPSEvaluation();
7372 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7373 aopPut (AOP (result), zero, LSB);
7377 movLeft2Result (left, LSB, result, MSB16, 0);
7378 aopPut (AOP (result), zero, LSB);
7379 _endLazyDPSEvaluation();
7384 aopPut (AOP (result), zero, LSB);
7385 _endLazyDPSEvaluation();
7389 /* 1 <= shCount <= 7 */
7394 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7398 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7406 /*-----------------------------------------------------------------*/
7407 /* shiftLLong - shift left one long from left to result */
7408 /* offl = LSB or MSB16 */
7409 /*-----------------------------------------------------------------*/
7411 shiftLLong (operand * left, operand * result, int offr)
7414 int size = AOP_SIZE (result);
7416 if (size >= LSB + offr)
7418 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7420 emitcode ("add", "a,acc");
7421 if (sameRegs (AOP (left), AOP (result)) &&
7422 size >= MSB16 + offr && offr != LSB)
7423 emitcode ("xch", "a,%s",
7424 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7426 aopPut (AOP (result), "a", LSB + offr);
7429 if (size >= MSB16 + offr)
7431 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7433 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7436 emitcode ("rlc", "a");
7437 if (sameRegs (AOP (left), AOP (result)) &&
7438 size >= MSB24 + offr && offr != LSB)
7439 emitcode ("xch", "a,%s",
7440 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7442 aopPut (AOP (result), "a", MSB16 + offr);
7445 if (size >= MSB24 + offr)
7447 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7449 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7452 emitcode ("rlc", "a");
7453 if (sameRegs (AOP (left), AOP (result)) &&
7454 size >= MSB32 + offr && offr != LSB)
7455 emitcode ("xch", "a,%s",
7456 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7458 aopPut (AOP (result), "a", MSB24 + offr);
7461 if (size > MSB32 + offr)
7463 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7465 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7468 emitcode ("rlc", "a");
7469 aopPut (AOP (result), "a", MSB32 + offr);
7472 aopPut (AOP (result), zero, LSB);
7478 /*-----------------------------------------------------------------*/
7479 /* genlshFour - shift four byte by a known amount != 0 */
7480 /*-----------------------------------------------------------------*/
7482 genlshFour (operand * result, operand * left, int shCount)
7486 D (emitcode (";", "genlshFour ");
7489 size = AOP_SIZE (result);
7491 /* if shifting more that 3 bytes */
7496 /* lowest order of left goes to the highest
7497 order of the destination */
7498 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7500 movLeft2Result (left, LSB, result, MSB32, 0);
7501 aopPut (AOP (result), zero, LSB);
7502 aopPut (AOP (result), zero, MSB16);
7503 aopPut (AOP (result), zero, MSB24);
7507 /* more than two bytes */
7508 else if (shCount >= 16)
7510 /* lower order two bytes goes to higher order two bytes */
7512 /* if some more remaining */
7514 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7517 movLeft2Result (left, MSB16, result, MSB32, 0);
7518 movLeft2Result (left, LSB, result, MSB24, 0);
7520 aopPut (AOP (result), zero, MSB16);
7521 aopPut (AOP (result), zero, LSB);
7525 /* if more than 1 byte */
7526 else if (shCount >= 8)
7528 /* lower order three bytes goes to higher order three bytes */
7533 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7535 movLeft2Result (left, LSB, result, MSB16, 0);
7541 movLeft2Result (left, MSB24, result, MSB32, 0);
7542 movLeft2Result (left, MSB16, result, MSB24, 0);
7543 movLeft2Result (left, LSB, result, MSB16, 0);
7544 aopPut (AOP (result), zero, LSB);
7546 else if (shCount == 1)
7547 shiftLLong (left, result, MSB16);
7550 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7551 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7552 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7553 aopPut (AOP (result), zero, LSB);
7558 /* 1 <= shCount <= 7 */
7559 else if (shCount <= 2)
7561 shiftLLong (left, result, LSB);
7563 shiftLLong (result, result, LSB);
7565 /* 3 <= shCount <= 7, optimize */
7568 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7569 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7570 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7575 #ifdef BETTER_LITERAL_SHIFT
7576 /*-----------------------------------------------------------------*/
7577 /* genLeftShiftLiteral - left shifting by known count */
7578 /*-----------------------------------------------------------------*/
7580 genLeftShiftLiteral (operand * left,
7585 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7588 size = getSize (operandType (result));
7590 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7592 /* We only handle certain easy cases so far. */
7594 && (shCount < (size * 8))
7598 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7602 freeAsmop (right, NULL, ic, TRUE);
7604 aopOp(left, ic, FALSE, FALSE);
7605 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7608 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7610 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7611 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7613 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7616 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7618 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7619 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7621 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7627 emitcode ("; shift left ", "result %d, left %d", size,
7631 /* I suppose that the left size >= result size */
7634 _startLazyDPSEvaluation();
7637 movLeft2Result (left, size, result, size, 0);
7639 _endLazyDPSEvaluation();
7641 else if (shCount >= (size * 8))
7643 _startLazyDPSEvaluation();
7646 aopPut (AOP (result), zero, size);
7648 _endLazyDPSEvaluation();
7655 genlshOne (result, left, shCount);
7659 genlshTwo (result, left, shCount);
7663 genlshFour (result, left, shCount);
7667 fprintf(stderr, "*** ack! mystery literal shift!\n");
7671 freeAsmop (left, NULL, ic, TRUE);
7672 freeAsmop (result, NULL, ic, TRUE);
7677 /*-----------------------------------------------------------------*/
7678 /* genLeftShift - generates code for left shifting */
7679 /*-----------------------------------------------------------------*/
7681 genLeftShift (iCode * ic)
7683 operand *left, *right, *result;
7686 symbol *tlbl, *tlbl1;
7688 D (emitcode (";", "genLeftShift "););
7690 right = IC_RIGHT (ic);
7691 left = IC_LEFT (ic);
7692 result = IC_RESULT (ic);
7694 aopOp (right, ic, FALSE, FALSE);
7697 #ifdef BETTER_LITERAL_SHIFT
7698 /* if the shift count is known then do it
7699 as efficiently as possible */
7700 if (AOP_TYPE (right) == AOP_LIT)
7702 if (genLeftShiftLiteral (left, right, result, ic))
7709 /* shift count is unknown then we have to form
7710 a loop get the loop count in B : Note: we take
7711 only the lower order byte since shifting
7712 more that 32 bits make no sense anyway, ( the
7713 largest size of an object can be only 32 bits ) */
7715 if (AOP_TYPE (right) == AOP_LIT)
7717 /* Really should be handled by genLeftShiftLiteral,
7718 * but since I'm too lazy to fix that today, at least we can make
7719 * some small improvement.
7721 emitcode("mov", "b,#0x%02x",
7722 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7726 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7727 emitcode ("inc", "b");
7729 freeAsmop (right, NULL, ic, TRUE);
7730 aopOp (left, ic, FALSE, FALSE);
7731 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7733 /* now move the left to the result if they are not the
7735 if (!sameRegs (AOP (left), AOP (result)) &&
7736 AOP_SIZE (result) > 1)
7739 size = AOP_SIZE (result);
7741 _startLazyDPSEvaluation ();
7744 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7745 if (*l == '@' && (IS_AOP_PREG (result)))
7748 emitcode ("mov", "a,%s", l);
7749 aopPut (AOP (result), "a", offset);
7752 aopPut (AOP (result), l, offset);
7755 _endLazyDPSEvaluation ();
7758 tlbl = newiTempLabel (NULL);
7759 size = AOP_SIZE (result);
7761 tlbl1 = newiTempLabel (NULL);
7763 /* if it is only one byte then */
7766 symbol *tlbl1 = newiTempLabel (NULL);
7768 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7770 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7771 emitcode ("", "%05d$:", tlbl->key + 100);
7772 emitcode ("add", "a,acc");
7773 emitcode ("", "%05d$:", tlbl1->key + 100);
7774 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7775 aopPut (AOP (result), "a", 0);
7779 reAdjustPreg (AOP (result));
7781 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7782 emitcode ("", "%05d$:", tlbl->key + 100);
7783 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7785 emitcode ("add", "a,acc");
7786 aopPut (AOP (result), "a", offset++);
7787 _startLazyDPSEvaluation ();
7790 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7792 emitcode ("rlc", "a");
7793 aopPut (AOP (result), "a", offset++);
7795 _endLazyDPSEvaluation ();
7796 reAdjustPreg (AOP (result));
7798 emitcode ("", "%05d$:", tlbl1->key + 100);
7799 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7801 freeAsmop (left, NULL, ic, TRUE);
7802 freeAsmop (result, NULL, ic, TRUE);
7805 #ifdef BETTER_LITERAL_SHIFT
7806 /*-----------------------------------------------------------------*/
7807 /* genrshOne - right shift a one byte quantity by known count */
7808 /*-----------------------------------------------------------------*/
7810 genrshOne (operand * result, operand * left,
7811 int shCount, int sign)
7813 D (emitcode (";", "genrshOne"););
7814 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7818 #ifdef BETTER_LITERAL_SHIFT
7819 /*-----------------------------------------------------------------*/
7820 /* genrshTwo - right shift two bytes by known amount != 0 */
7821 /*-----------------------------------------------------------------*/
7823 genrshTwo (operand * result, operand * left,
7824 int shCount, int sign)
7826 D (emitcode (";", "genrshTwo"););
7828 /* if shCount >= 8 */
7832 _startLazyDPSEvaluation();
7835 shiftR1Left2Result (left, MSB16, result, LSB,
7840 movLeft2Result (left, MSB16, result, LSB, sign);
7842 addSign (result, MSB16, sign);
7843 _endLazyDPSEvaluation();
7846 /* 1 <= shCount <= 7 */
7849 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7856 /*-----------------------------------------------------------------*/
7857 /* shiftRLong - shift right one long from left to result */
7858 /* offl = LSB or MSB16 */
7859 /*-----------------------------------------------------------------*/
7861 shiftRLong (operand * left, int offl,
7862 operand * result, int sign)
7864 int isSameRegs=sameRegs(AOP(left),AOP(result));
7866 if (isSameRegs && offl>1) {
7867 // we are in big trouble, but this shouldn't happen
7868 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7871 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7876 emitcode ("rlc", "a");
7877 emitcode ("subb", "a,acc");
7878 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7880 aopPut (AOP(result), zero, MSB32);
7885 emitcode ("clr", "c");
7887 emitcode ("mov", "c,acc.7");
7890 emitcode ("rrc", "a");
7892 if (isSameRegs && offl==MSB16) {
7893 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7895 aopPut (AOP (result), "a", MSB32);
7896 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7899 emitcode ("rrc", "a");
7900 if (isSameRegs && offl==1) {
7901 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7903 aopPut (AOP (result), "a", MSB24);
7904 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7906 emitcode ("rrc", "a");
7907 aopPut (AOP (result), "a", MSB16 - offl);
7911 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7912 emitcode ("rrc", "a");
7913 aopPut (AOP (result), "a", LSB);
7920 /*-----------------------------------------------------------------*/
7921 /* genrshFour - shift four byte by a known amount != 0 */
7922 /*-----------------------------------------------------------------*/
7924 genrshFour (operand * result, operand * left,
7925 int shCount, int sign)
7927 D (emitcode (";", "genrshFour");
7930 /* if shifting more that 3 bytes */
7935 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7937 movLeft2Result (left, MSB32, result, LSB, sign);
7938 addSign (result, MSB16, sign);
7940 else if (shCount >= 16)
7944 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7947 movLeft2Result (left, MSB24, result, LSB, 0);
7948 movLeft2Result (left, MSB32, result, MSB16, sign);
7950 addSign (result, MSB24, sign);
7952 else if (shCount >= 8)
7956 shiftRLong (left, MSB16, result, sign);
7957 else if (shCount == 0)
7959 movLeft2Result (left, MSB16, result, LSB, 0);
7960 movLeft2Result (left, MSB24, result, MSB16, 0);
7961 movLeft2Result (left, MSB32, result, MSB24, sign);
7962 addSign (result, MSB32, sign);
7966 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7967 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7968 /* the last shift is signed */
7969 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7970 addSign (result, MSB32, sign);
7974 { /* 1 <= shCount <= 7 */
7977 shiftRLong (left, LSB, result, sign);
7979 shiftRLong (result, LSB, result, sign);
7983 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7984 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7985 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7991 #ifdef BETTER_LITERAL_SHIFT
7992 /*-----------------------------------------------------------------*/
7993 /* genRightShiftLiteral - right shifting by known count */
7994 /*-----------------------------------------------------------------*/
7996 genRightShiftLiteral (operand * left,
8002 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8005 size = getSize (operandType (result));
8007 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8009 /* We only handle certain easy cases so far. */
8011 && (shCount < (size * 8))
8015 D(emitcode (";", "genRightShiftLiteral wimping out"););
8019 freeAsmop (right, NULL, ic, TRUE);
8021 aopOp (left, ic, FALSE, FALSE);
8022 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8025 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8029 /* test the LEFT size !!! */
8031 /* I suppose that the left size >= result size */
8034 size = getDataSize (result);
8035 _startLazyDPSEvaluation();
8038 movLeft2Result (left, size, result, size, 0);
8040 _endLazyDPSEvaluation();
8042 else if (shCount >= (size * 8))
8046 /* get sign in acc.7 */
8047 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8049 addSign (result, LSB, sign);
8056 genrshOne (result, left, shCount, sign);
8060 genrshTwo (result, left, shCount, sign);
8064 genrshFour (result, left, shCount, sign);
8071 freeAsmop (left, NULL, ic, TRUE);
8072 freeAsmop (result, NULL, ic, TRUE);
8078 /*-----------------------------------------------------------------*/
8079 /* genSignedRightShift - right shift of signed number */
8080 /*-----------------------------------------------------------------*/
8082 genSignedRightShift (iCode * ic)
8084 operand *right, *left, *result;
8087 symbol *tlbl, *tlbl1;
8089 D (emitcode (";", "genSignedRightShift "););
8091 /* we do it the hard way put the shift count in b
8092 and loop thru preserving the sign */
8094 right = IC_RIGHT (ic);
8095 left = IC_LEFT (ic);
8096 result = IC_RESULT (ic);
8098 aopOp (right, ic, FALSE, FALSE);
8100 #ifdef BETTER_LITERAL_SHIFT
8101 if (AOP_TYPE (right) == AOP_LIT)
8103 if (genRightShiftLiteral (left, right, result, ic, 1))
8109 /* shift count is unknown then we have to form
8110 a loop get the loop count in B : Note: we take
8111 only the lower order byte since shifting
8112 more that 32 bits make no sense anyway, ( the
8113 largest size of an object can be only 32 bits ) */
8115 if (AOP_TYPE (right) == AOP_LIT)
8117 /* Really should be handled by genRightShiftLiteral,
8118 * but since I'm too lazy to fix that today, at least we can make
8119 * some small improvement.
8121 emitcode("mov", "b,#0x%02x",
8122 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8126 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8127 emitcode ("inc", "b");
8129 freeAsmop (right, NULL, ic, TRUE);
8130 aopOp (left, ic, FALSE, FALSE);
8131 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8133 /* now move the left to the result if they are not the
8135 if (!sameRegs (AOP (left), AOP (result)) &&
8136 AOP_SIZE (result) > 1)
8139 size = AOP_SIZE (result);
8141 _startLazyDPSEvaluation ();
8144 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8145 if (*l == '@' && IS_AOP_PREG (result))
8148 emitcode ("mov", "a,%s", l);
8149 aopPut (AOP (result), "a", offset);
8152 aopPut (AOP (result), l, offset);
8155 _endLazyDPSEvaluation ();
8158 /* mov the highest order bit to OVR */
8159 tlbl = newiTempLabel (NULL);
8160 tlbl1 = newiTempLabel (NULL);
8162 size = AOP_SIZE (result);
8164 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8165 emitcode ("rlc", "a");
8166 emitcode ("mov", "ov,c");
8167 /* if it is only one byte then */
8170 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8172 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8173 emitcode ("", "%05d$:", tlbl->key + 100);
8174 emitcode ("mov", "c,ov");
8175 emitcode ("rrc", "a");
8176 emitcode ("", "%05d$:", tlbl1->key + 100);
8177 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8178 aopPut (AOP (result), "a", 0);
8182 reAdjustPreg (AOP (result));
8183 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8184 emitcode ("", "%05d$:", tlbl->key + 100);
8185 emitcode ("mov", "c,ov");
8186 _startLazyDPSEvaluation ();
8189 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8191 emitcode ("rrc", "a");
8192 aopPut (AOP (result), "a", offset--);
8194 _endLazyDPSEvaluation ();
8195 reAdjustPreg (AOP (result));
8196 emitcode ("", "%05d$:", tlbl1->key + 100);
8197 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8200 freeAsmop (left, NULL, ic, TRUE);
8201 freeAsmop (result, NULL, ic, TRUE);
8204 /*-----------------------------------------------------------------*/
8205 /* genRightShift - generate code for right shifting */
8206 /*-----------------------------------------------------------------*/
8208 genRightShift (iCode * ic)
8210 operand *right, *left, *result;
8214 symbol *tlbl, *tlbl1;
8216 D (emitcode (";", "genRightShift "););
8218 /* if signed then we do it the hard way preserve the
8219 sign bit moving it inwards */
8220 retype = getSpec (operandType (IC_RESULT (ic)));
8222 if (!SPEC_USIGN (retype))
8224 genSignedRightShift (ic);
8228 /* signed & unsigned types are treated the same : i.e. the
8229 signed is NOT propagated inwards : quoting from the
8230 ANSI - standard : "for E1 >> E2, is equivalent to division
8231 by 2**E2 if unsigned or if it has a non-negative value,
8232 otherwise the result is implementation defined ", MY definition
8233 is that the sign does not get propagated */
8235 right = IC_RIGHT (ic);
8236 left = IC_LEFT (ic);
8237 result = IC_RESULT (ic);
8239 aopOp (right, ic, FALSE, FALSE);
8241 #ifdef BETTER_LITERAL_SHIFT
8242 /* if the shift count is known then do it
8243 as efficiently as possible */
8244 if (AOP_TYPE (right) == AOP_LIT)
8246 if (genRightShiftLiteral (left, right, result, ic, 0))
8253 /* shift count is unknown then we have to form
8254 a loop get the loop count in B : Note: we take
8255 only the lower order byte since shifting
8256 more that 32 bits make no sense anyway, ( the
8257 largest size of an object can be only 32 bits ) */
8259 if (AOP_TYPE (right) == AOP_LIT)
8261 /* Really should be handled by genRightShiftLiteral,
8262 * but since I'm too lazy to fix that today, at least we can make
8263 * some small improvement.
8265 emitcode("mov", "b,#0x%02x",
8266 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8270 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8271 emitcode ("inc", "b");
8273 freeAsmop (right, NULL, ic, TRUE);
8274 aopOp (left, ic, FALSE, FALSE);
8275 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8277 /* now move the left to the result if they are not the
8279 if (!sameRegs (AOP (left), AOP (result)) &&
8280 AOP_SIZE (result) > 1)
8283 size = AOP_SIZE (result);
8285 _startLazyDPSEvaluation ();
8288 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8289 if (*l == '@' && IS_AOP_PREG (result))
8292 emitcode ("mov", "a,%s", l);
8293 aopPut (AOP (result), "a", offset);
8296 aopPut (AOP (result), l, offset);
8299 _endLazyDPSEvaluation ();
8302 tlbl = newiTempLabel (NULL);
8303 tlbl1 = newiTempLabel (NULL);
8304 size = AOP_SIZE (result);
8307 /* if it is only one byte then */
8310 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8312 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8313 emitcode ("", "%05d$:", tlbl->key + 100);
8315 emitcode ("rrc", "a");
8316 emitcode ("", "%05d$:", tlbl1->key + 100);
8317 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8318 aopPut (AOP (result), "a", 0);
8322 reAdjustPreg (AOP (result));
8323 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8324 emitcode ("", "%05d$:", tlbl->key + 100);
8326 _startLazyDPSEvaluation ();
8329 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8331 emitcode ("rrc", "a");
8332 aopPut (AOP (result), "a", offset--);
8334 _endLazyDPSEvaluation ();
8335 reAdjustPreg (AOP (result));
8337 emitcode ("", "%05d$:", tlbl1->key + 100);
8338 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8341 freeAsmop (left, NULL, ic, TRUE);
8342 freeAsmop (result, NULL, ic, TRUE);
8345 /*-----------------------------------------------------------------*/
8346 /* genUnpackBits - generates code for unpacking bits */
8347 /*-----------------------------------------------------------------*/
8349 genUnpackBits (operand * result, char *rname, int ptype)
8356 D (emitcode (";", "genUnpackBits ");
8359 etype = getSpec (operandType (result));
8361 /* read the first byte */
8367 emitcode ("mov", "a,@%s", rname);
8371 emitcode ("movx", "a,@%s", rname);
8375 emitcode ("movx", "a,@dptr");
8379 emitcode ("clr", "a");
8380 emitcode ("movc", "a,@a+dptr");
8384 emitcode ("lcall", "__gptrget");
8388 /* if we have bitdisplacement then it fits */
8389 /* into this byte completely or if length is */
8390 /* less than a byte */
8391 if ((shCnt = SPEC_BSTR (etype)) ||
8392 (SPEC_BLEN (etype) <= 8))
8395 /* shift right acc */
8398 emitcode ("anl", "a,#0x%02x",
8399 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8400 aopPut (AOP (result), "a", offset);
8404 /* bit field did not fit in a byte */
8405 rlen = SPEC_BLEN (etype) - 8;
8406 aopPut (AOP (result), "a", offset++);
8415 emitcode ("inc", "%s", rname);
8416 emitcode ("mov", "a,@%s", rname);
8420 emitcode ("inc", "%s", rname);
8421 emitcode ("movx", "a,@%s", rname);
8425 emitcode ("inc", "dptr");
8426 emitcode ("movx", "a,@dptr");
8430 emitcode ("clr", "a");
8431 emitcode ("inc", "dptr");
8432 emitcode ("movc", "a,@a+dptr");
8436 emitcode ("inc", "dptr");
8437 emitcode ("lcall", "__gptrget");
8442 /* if we are done */
8446 aopPut (AOP (result), "a", offset++);
8452 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
8453 aopPut (AOP (result), "a", offset);
8460 /*-----------------------------------------------------------------*/
8461 /* genDataPointerGet - generates code when ptr offset is known */
8462 /*-----------------------------------------------------------------*/
8464 genDataPointerGet (operand * left,
8470 int size, offset = 0;
8471 aopOp (result, ic, TRUE, FALSE);
8473 /* get the string representation of the name */
8474 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8475 size = AOP_SIZE (result);
8476 _startLazyDPSEvaluation ();
8480 sprintf (buffer, "(%s + %d)", l + 1, offset);
8482 sprintf (buffer, "%s", l + 1);
8483 aopPut (AOP (result), buffer, offset++);
8485 _endLazyDPSEvaluation ();
8487 freeAsmop (left, NULL, ic, TRUE);
8488 freeAsmop (result, NULL, ic, TRUE);
8491 /*-----------------------------------------------------------------*/
8492 /* genNearPointerGet - emitcode for near pointer fetch */
8493 /*-----------------------------------------------------------------*/
8495 genNearPointerGet (operand * left,
8502 sym_link *rtype, *retype, *letype;
8503 sym_link *ltype = operandType (left);
8506 rtype = operandType (result);
8507 retype = getSpec (rtype);
8508 letype = getSpec (ltype);
8510 aopOp (left, ic, FALSE, FALSE);
8512 /* if left is rematerialisable and
8513 result is not bit variable type and
8514 the left is pointer to data space i.e
8515 lower 128 bytes of space */
8516 if (AOP_TYPE (left) == AOP_IMMD &&
8517 !IS_BITVAR (retype) &&
8518 !IS_BITVAR (letype) &&
8519 DCL_TYPE (ltype) == POINTER)
8521 genDataPointerGet (left, result, ic);
8525 /* if the value is already in a pointer register
8526 then don't need anything more */
8527 if (!AOP_INPREG (AOP (left)))
8529 /* otherwise get a free pointer register */
8531 preg = getFreePtr (ic, &aop, FALSE);
8532 emitcode ("mov", "%s,%s",
8534 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8538 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8540 freeAsmop (left, NULL, ic, TRUE);
8541 aopOp (result, ic, FALSE, FALSE);
8543 /* if bitfield then unpack the bits */
8544 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8545 genUnpackBits (result, rname, POINTER);
8548 /* we have can just get the values */
8549 int size = AOP_SIZE (result);
8554 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8557 emitcode ("mov", "a,@%s", rname);
8558 aopPut (AOP (result), "a", offset);
8562 sprintf (buffer, "@%s", rname);
8563 aopPut (AOP (result), buffer, offset);
8567 emitcode ("inc", "%s", rname);
8571 /* now some housekeeping stuff */
8574 /* we had to allocate for this iCode */
8575 freeAsmop (NULL, aop, ic, TRUE);
8579 /* we did not allocate which means left
8580 already in a pointer register, then
8581 if size > 0 && this could be used again
8582 we have to point it back to where it
8584 if (AOP_SIZE (result) > 1 &&
8585 !OP_SYMBOL (left)->remat &&
8586 (OP_SYMBOL (left)->liveTo > ic->seq ||
8589 int size = AOP_SIZE (result) - 1;
8591 emitcode ("dec", "%s", rname);
8596 freeAsmop (result, NULL, ic, TRUE);
8600 /*-----------------------------------------------------------------*/
8601 /* genPagedPointerGet - emitcode for paged pointer fetch */
8602 /*-----------------------------------------------------------------*/
8604 genPagedPointerGet (operand * left,
8611 sym_link *rtype, *retype, *letype;
8613 rtype = operandType (result);
8614 retype = getSpec (rtype);
8615 letype = getSpec (operandType (left));
8616 aopOp (left, ic, FALSE, FALSE);
8618 /* if the value is already in a pointer register
8619 then don't need anything more */
8620 if (!AOP_INPREG (AOP (left)))
8622 /* otherwise get a free pointer register */
8624 preg = getFreePtr (ic, &aop, FALSE);
8625 emitcode ("mov", "%s,%s",
8627 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8631 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8633 freeAsmop (left, NULL, ic, TRUE);
8634 aopOp (result, ic, FALSE, FALSE);
8636 /* if bitfield then unpack the bits */
8637 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8638 genUnpackBits (result, rname, PPOINTER);
8641 /* we have can just get the values */
8642 int size = AOP_SIZE (result);
8648 emitcode ("movx", "a,@%s", rname);
8649 aopPut (AOP (result), "a", offset);
8654 emitcode ("inc", "%s", rname);
8658 /* now some housekeeping stuff */
8661 /* we had to allocate for this iCode */
8662 freeAsmop (NULL, aop, ic, TRUE);
8666 /* we did not allocate which means left
8667 already in a pointer register, then
8668 if size > 0 && this could be used again
8669 we have to point it back to where it
8671 if (AOP_SIZE (result) > 1 &&
8672 !OP_SYMBOL (left)->remat &&
8673 (OP_SYMBOL (left)->liveTo > ic->seq ||
8676 int size = AOP_SIZE (result) - 1;
8678 emitcode ("dec", "%s", rname);
8683 freeAsmop (result, NULL, ic, TRUE);
8688 /*-----------------------------------------------------------------*/
8689 /* genFarPointerGet - gget value from far space */
8690 /*-----------------------------------------------------------------*/
8692 genFarPointerGet (operand * left,
8693 operand * result, iCode * ic)
8696 sym_link *retype = getSpec (operandType (result));
8697 sym_link *letype = getSpec (operandType (left));
8698 D (emitcode (";", "genFarPointerGet");
8701 aopOp (left, ic, FALSE, FALSE);
8703 /* if the operand is already in dptr
8704 then we do nothing else we move the value to dptr */
8705 if (AOP_TYPE (left) != AOP_STR)
8707 /* if this is remateriazable */
8708 if (AOP_TYPE (left) == AOP_IMMD)
8710 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8714 /* we need to get it byte by byte */
8715 _startLazyDPSEvaluation ();
8716 if (AOP_TYPE (left) != AOP_DPTR)
8718 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8719 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8720 if (options.model == MODEL_FLAT24)
8721 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8725 /* We need to generate a load to DPTR indirect through DPTR. */
8726 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8728 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8729 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8730 if (options.model == MODEL_FLAT24)
8731 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8732 emitcode ("pop", "dph");
8733 emitcode ("pop", "dpl");
8735 _endLazyDPSEvaluation ();
8738 /* so dptr know contains the address */
8739 freeAsmop (left, NULL, ic, TRUE);
8740 aopOp (result, ic, FALSE, TRUE);
8742 /* if bit then unpack */
8743 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8744 genUnpackBits (result, "dptr", FPOINTER);
8747 size = AOP_SIZE (result);
8750 _startLazyDPSEvaluation ();
8757 emitcode ("movx", "a,@dptr");
8759 emitcode ("inc", "dptr");
8761 aopPut (AOP (result), "a", offset++);
8763 _endLazyDPSEvaluation ();
8766 freeAsmop (result, NULL, ic, TRUE);
8769 /*-----------------------------------------------------------------*/
8770 /* emitcodePointerGet - gget value from code space */
8771 /*-----------------------------------------------------------------*/
8773 emitcodePointerGet (operand * left,
8774 operand * result, iCode * ic)
8777 sym_link *retype = getSpec (operandType (result));
8779 aopOp (left, ic, FALSE, FALSE);
8781 /* if the operand is already in dptr
8782 then we do nothing else we move the value to dptr */
8783 if (AOP_TYPE (left) != AOP_STR)
8785 /* if this is remateriazable */
8786 if (AOP_TYPE (left) == AOP_IMMD)
8788 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8791 { /* we need to get it byte by byte */
8792 _startLazyDPSEvaluation ();
8793 if (AOP_TYPE (left) != AOP_DPTR)
8795 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8796 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8797 if (options.model == MODEL_FLAT24)
8798 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8802 /* We need to generate a load to DPTR indirect through DPTR. */
8803 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8805 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8806 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8807 if (options.model == MODEL_FLAT24)
8808 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8809 emitcode ("pop", "dph");
8810 emitcode ("pop", "dpl");
8812 _endLazyDPSEvaluation ();
8815 /* so dptr know contains the address */
8816 freeAsmop (left, NULL, ic, TRUE);
8817 aopOp (result, ic, FALSE, TRUE);
8819 /* if bit then unpack */
8820 if (IS_BITVAR (retype))
8821 genUnpackBits (result, "dptr", CPOINTER);
8824 size = AOP_SIZE (result);
8827 _startLazyDPSEvaluation ();
8833 emitcode ("clr", "a");
8834 emitcode ("movc", "a,@a+dptr");
8836 emitcode ("inc", "dptr");
8837 aopPut (AOP (result), "a", offset++);
8839 _endLazyDPSEvaluation ();
8842 freeAsmop (result, NULL, ic, TRUE);
8845 /*-----------------------------------------------------------------*/
8846 /* genGenPointerGet - gget value from generic pointer space */
8847 /*-----------------------------------------------------------------*/
8849 genGenPointerGet (operand * left,
8850 operand * result, iCode * ic)
8853 sym_link *retype = getSpec (operandType (result));
8854 sym_link *letype = getSpec (operandType (left));
8856 D (emitcode (";", "genGenPointerGet "); );
8858 aopOp (left, ic, FALSE, TRUE);
8860 /* if the operand is already in dptr
8861 then we do nothing else we move the value to dptr */
8862 if (AOP_TYPE (left) != AOP_STR)
8864 /* if this is remateriazable */
8865 if (AOP_TYPE (left) == AOP_IMMD)
8867 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8868 emitcode ("mov", "b,#%d", pointerCode (retype));
8871 { /* we need to get it byte by byte */
8872 _startLazyDPSEvaluation ();
8873 if (AOP(left)->type==AOP_DPTR2) {
8875 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8878 emitcode ("mov", "dpl,%s", l);
8879 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8882 emitcode ("mov", "dph,%s", l);
8883 if (options.model == MODEL_FLAT24) {
8884 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8887 emitcode ("mov", "dpx,%s", l);
8888 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8890 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8893 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8894 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8895 if (options.model == MODEL_FLAT24) {
8896 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8897 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8899 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8902 _endLazyDPSEvaluation ();
8905 /* so dptr know contains the address */
8906 freeAsmop (left, NULL, ic, TRUE);
8907 aopOp (result, ic, FALSE, TRUE);
8909 /* if bit then unpack */
8910 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8911 genUnpackBits (result, "dptr", GPOINTER);
8914 size = AOP_SIZE (result);
8919 emitcode ("lcall", "__gptrget");
8920 aopPut (AOP (result), "a", offset++);
8922 emitcode ("inc", "dptr");
8926 freeAsmop (result, NULL, ic, TRUE);
8929 /*-----------------------------------------------------------------*/
8930 /* genPointerGet - generate code for pointer get */
8931 /*-----------------------------------------------------------------*/
8933 genPointerGet (iCode * ic)
8935 operand *left, *result;
8936 sym_link *type, *etype;
8939 D (emitcode (";", "genPointerGet ");
8942 left = IC_LEFT (ic);
8943 result = IC_RESULT (ic);
8945 /* depending on the type of pointer we need to
8946 move it to the correct pointer register */
8947 type = operandType (left);
8948 etype = getSpec (type);
8949 /* if left is of type of pointer then it is simple */
8950 if (IS_PTR (type) && !IS_FUNC (type->next))
8951 p_type = DCL_TYPE (type);
8954 /* we have to go by the storage class */
8955 p_type = PTR_TYPE (SPEC_OCLS (etype));
8958 /* now that we have the pointer type we assign
8959 the pointer values */
8965 genNearPointerGet (left, result, ic);
8969 genPagedPointerGet (left, result, ic);
8973 genFarPointerGet (left, result, ic);
8977 emitcodePointerGet (left, result, ic);
8981 genGenPointerGet (left, result, ic);
8987 /*-----------------------------------------------------------------*/
8988 /* genPackBits - generates code for packed bit storage */
8989 /*-----------------------------------------------------------------*/
8991 genPackBits (sym_link * etype,
8993 char *rname, int p_type)
9001 blen = SPEC_BLEN (etype);
9002 bstr = SPEC_BSTR (etype);
9004 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9007 /* if the bit lenth is less than or */
9008 /* it exactly fits a byte then */
9009 if (SPEC_BLEN (etype) <= 8)
9011 shCount = SPEC_BSTR (etype);
9013 /* shift left acc */
9016 if (SPEC_BLEN (etype) < 8)
9017 { /* if smaller than a byte */
9023 emitcode ("mov", "b,a");
9024 emitcode ("mov", "a,@%s", rname);
9028 emitcode ("mov", "b,a");
9029 emitcode ("movx", "a,@dptr");
9033 emitcode ("push", "b");
9034 emitcode ("push", "acc");
9035 emitcode ("lcall", "__gptrget");
9036 emitcode ("pop", "b");
9040 emitcode ("anl", "a,#0x%02x", (unsigned char)
9041 ((unsigned char) (0xFF << (blen + bstr)) |
9042 (unsigned char) (0xFF >> (8 - bstr))));
9043 emitcode ("orl", "a,b");
9044 if (p_type == GPOINTER)
9045 emitcode ("pop", "b");
9052 emitcode ("mov", "@%s,a", rname);
9056 emitcode ("movx", "@dptr,a");
9060 emitcode ("lcall", "__gptrput");
9065 if (SPEC_BLEN (etype) <= 8)
9068 emitcode ("inc", "%s", rname);
9069 rLen = SPEC_BLEN (etype);
9071 /* now generate for lengths greater than one byte */
9075 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9087 emitcode ("mov", "@%s,a", rname);
9090 emitcode ("mov", "@%s,%s", rname, l);
9095 emitcode ("movx", "@dptr,a");
9100 emitcode ("lcall", "__gptrput");
9103 emitcode ("inc", "%s", rname);
9108 /* last last was not complete */
9111 /* save the byte & read byte */
9115 emitcode ("mov", "b,a");
9116 emitcode ("mov", "a,@%s", rname);
9120 emitcode ("mov", "b,a");
9121 emitcode ("movx", "a,@dptr");
9125 emitcode ("push", "b");
9126 emitcode ("push", "acc");
9127 emitcode ("lcall", "__gptrget");
9128 emitcode ("pop", "b");
9132 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
9133 emitcode ("orl", "a,b");
9136 if (p_type == GPOINTER)
9137 emitcode ("pop", "b");
9143 emitcode ("mov", "@%s,a", rname);
9147 emitcode ("movx", "@dptr,a");
9151 emitcode ("lcall", "__gptrput");
9155 /*-----------------------------------------------------------------*/
9156 /* genDataPointerSet - remat pointer to data space */
9157 /*-----------------------------------------------------------------*/
9159 genDataPointerSet (operand * right,
9163 int size, offset = 0;
9164 char *l, buffer[256];
9166 aopOp (right, ic, FALSE, FALSE);
9168 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9169 size = AOP_SIZE (right);
9173 sprintf (buffer, "(%s + %d)", l + 1, offset);
9175 sprintf (buffer, "%s", l + 1);
9176 emitcode ("mov", "%s,%s", buffer,
9177 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9180 freeAsmop (right, NULL, ic, TRUE);
9181 freeAsmop (result, NULL, ic, TRUE);
9184 /*-----------------------------------------------------------------*/
9185 /* genNearPointerSet - emitcode for near pointer put */
9186 /*-----------------------------------------------------------------*/
9188 genNearPointerSet (operand * right,
9195 sym_link *retype, *letype;
9196 sym_link *ptype = operandType (result);
9198 retype = getSpec (operandType (right));
9199 letype = getSpec (ptype);
9201 aopOp (result, ic, FALSE, FALSE);
9203 /* if the result is rematerializable &
9204 in data space & not a bit variable */
9205 if (AOP_TYPE (result) == AOP_IMMD &&
9206 DCL_TYPE (ptype) == POINTER &&
9207 !IS_BITVAR (retype) &&
9208 !IS_BITVAR (letype))
9210 genDataPointerSet (right, result, ic);
9214 /* if the value is already in a pointer register
9215 then don't need anything more */
9216 if (!AOP_INPREG (AOP (result)))
9218 /* otherwise get a free pointer register */
9220 preg = getFreePtr (ic, &aop, FALSE);
9221 emitcode ("mov", "%s,%s",
9223 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9227 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9229 freeAsmop (result, NULL, ic, TRUE);
9230 aopOp (right, ic, FALSE, FALSE);
9232 /* if bitfield then unpack the bits */
9233 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9234 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9237 /* we have can just get the values */
9238 int size = AOP_SIZE (right);
9243 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9247 emitcode ("mov", "@%s,a", rname);
9250 emitcode ("mov", "@%s,%s", rname, l);
9252 emitcode ("inc", "%s", rname);
9257 /* now some housekeeping stuff */
9260 /* we had to allocate for this iCode */
9261 freeAsmop (NULL, aop, ic, TRUE);
9265 /* we did not allocate which means left
9266 already in a pointer register, then
9267 if size > 0 && this could be used again
9268 we have to point it back to where it
9270 if (AOP_SIZE (right) > 1 &&
9271 !OP_SYMBOL (result)->remat &&
9272 (OP_SYMBOL (result)->liveTo > ic->seq ||
9275 int size = AOP_SIZE (right) - 1;
9277 emitcode ("dec", "%s", rname);
9282 freeAsmop (right, NULL, ic, TRUE);
9287 /*-----------------------------------------------------------------*/
9288 /* genPagedPointerSet - emitcode for Paged pointer put */
9289 /*-----------------------------------------------------------------*/
9291 genPagedPointerSet (operand * right,
9298 sym_link *retype, *letype;
9300 retype = getSpec (operandType (right));
9301 letype = getSpec (operandType (result));
9303 aopOp (result, ic, FALSE, FALSE);
9305 /* if the value is already in a pointer register
9306 then don't need anything more */
9307 if (!AOP_INPREG (AOP (result)))
9309 /* otherwise get a free pointer register */
9311 preg = getFreePtr (ic, &aop, FALSE);
9312 emitcode ("mov", "%s,%s",
9314 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9318 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9320 freeAsmop (result, NULL, ic, TRUE);
9321 aopOp (right, ic, FALSE, FALSE);
9323 /* if bitfield then unpack the bits */
9324 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9325 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9328 /* we have can just get the values */
9329 int size = AOP_SIZE (right);
9334 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9337 emitcode ("movx", "@%s,a", rname);
9340 emitcode ("inc", "%s", rname);
9346 /* now some housekeeping stuff */
9349 /* we had to allocate for this iCode */
9350 freeAsmop (NULL, aop, ic, TRUE);
9354 /* we did not allocate which means left
9355 already in a pointer register, then
9356 if size > 0 && this could be used again
9357 we have to point it back to where it
9359 if (AOP_SIZE (right) > 1 &&
9360 !OP_SYMBOL (result)->remat &&
9361 (OP_SYMBOL (result)->liveTo > ic->seq ||
9364 int size = AOP_SIZE (right) - 1;
9366 emitcode ("dec", "%s", rname);
9371 freeAsmop (right, NULL, ic, TRUE);
9376 /*-----------------------------------------------------------------*/
9377 /* genFarPointerSet - set value from far space */
9378 /*-----------------------------------------------------------------*/
9380 genFarPointerSet (operand * right,
9381 operand * result, iCode * ic)
9384 sym_link *retype = getSpec (operandType (right));
9385 sym_link *letype = getSpec (operandType (result));
9387 aopOp (result, ic, FALSE, FALSE);
9389 /* if the operand is already in dptr
9390 then we do nothing else we move the value to dptr */
9391 if (AOP_TYPE (result) != AOP_STR)
9393 /* if this is remateriazable */
9394 if (AOP_TYPE (result) == AOP_IMMD)
9395 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9398 /* we need to get it byte by byte */
9399 _startLazyDPSEvaluation ();
9400 if (AOP_TYPE (result) != AOP_DPTR)
9402 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9403 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9404 if (options.model == MODEL_FLAT24)
9405 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9409 /* We need to generate a load to DPTR indirect through DPTR. */
9410 D (emitcode (";", "genFarPointerSet -- indirection special case.");
9412 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9413 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9414 if (options.model == MODEL_FLAT24)
9415 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9416 emitcode ("pop", "dph");
9417 emitcode ("pop", "dpl");
9419 _endLazyDPSEvaluation ();
9422 /* so dptr know contains the address */
9423 freeAsmop (result, NULL, ic, TRUE);
9424 aopOp (right, ic, FALSE, TRUE);
9426 /* if bit then unpack */
9427 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9428 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9431 size = AOP_SIZE (right);
9434 _startLazyDPSEvaluation ();
9437 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9443 emitcode ("movx", "@dptr,a");
9445 emitcode ("inc", "dptr");
9447 _endLazyDPSEvaluation ();
9450 freeAsmop (right, NULL, ic, TRUE);
9453 /*-----------------------------------------------------------------*/
9454 /* genGenPointerSet - set value from generic pointer space */
9455 /*-----------------------------------------------------------------*/
9457 genGenPointerSet (operand * right,
9458 operand * result, iCode * ic)
9461 sym_link *retype = getSpec (operandType (right));
9462 sym_link *letype = getSpec (operandType (result));
9464 aopOp (result, ic, FALSE, TRUE);
9466 /* if the operand is already in dptr
9467 then we do nothing else we move the value to dptr */
9468 if (AOP_TYPE (result) != AOP_STR)
9470 _startLazyDPSEvaluation ();
9471 /* if this is remateriazable */
9472 if (AOP_TYPE (result) == AOP_IMMD)
9474 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9475 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9478 { /* we need to get it byte by byte */
9479 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9480 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9481 if (options.model == MODEL_FLAT24) {
9482 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9483 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9485 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9488 _endLazyDPSEvaluation ();
9490 /* so dptr know contains the address */
9491 freeAsmop (result, NULL, ic, TRUE);
9492 aopOp (right, ic, FALSE, TRUE);
9494 /* if bit then unpack */
9495 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9496 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9499 size = AOP_SIZE (right);
9502 _startLazyDPSEvaluation ();
9505 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9511 emitcode ("lcall", "__gptrput");
9513 emitcode ("inc", "dptr");
9515 _endLazyDPSEvaluation ();
9518 freeAsmop (right, NULL, ic, TRUE);
9521 /*-----------------------------------------------------------------*/
9522 /* genPointerSet - stores the value into a pointer location */
9523 /*-----------------------------------------------------------------*/
9525 genPointerSet (iCode * ic)
9527 operand *right, *result;
9528 sym_link *type, *etype;
9531 D (emitcode (";", "genPointerSet ");
9534 right = IC_RIGHT (ic);
9535 result = IC_RESULT (ic);
9537 /* depending on the type of pointer we need to
9538 move it to the correct pointer register */
9539 type = operandType (result);
9540 etype = getSpec (type);
9541 /* if left is of type of pointer then it is simple */
9542 if (IS_PTR (type) && !IS_FUNC (type->next))
9544 p_type = DCL_TYPE (type);
9548 /* we have to go by the storage class */
9549 p_type = PTR_TYPE (SPEC_OCLS (etype));
9552 /* now that we have the pointer type we assign
9553 the pointer values */
9559 genNearPointerSet (right, result, ic);
9563 genPagedPointerSet (right, result, ic);
9567 genFarPointerSet (right, result, ic);
9571 genGenPointerSet (right, result, ic);
9577 /*-----------------------------------------------------------------*/
9578 /* genIfx - generate code for Ifx statement */
9579 /*-----------------------------------------------------------------*/
9581 genIfx (iCode * ic, iCode * popIc)
9583 operand *cond = IC_COND (ic);
9586 D (emitcode (";", "genIfx "););
9588 aopOp (cond, ic, FALSE, FALSE);
9590 /* get the value into acc */
9591 if (AOP_TYPE (cond) != AOP_CRY)
9595 /* the result is now in the accumulator */
9596 freeAsmop (cond, NULL, ic, TRUE);
9598 /* if there was something to be popped then do it */
9602 /* if the condition is a bit variable */
9603 if (isbit && IS_ITEMP (cond) &&
9605 genIfxJump (ic, SPIL_LOC (cond)->rname);
9606 else if (isbit && !IS_ITEMP (cond))
9607 genIfxJump (ic, OP_SYMBOL (cond)->rname);
9609 genIfxJump (ic, "a");
9614 /*-----------------------------------------------------------------*/
9615 /* genAddrOf - generates code for address of */
9616 /*-----------------------------------------------------------------*/
9618 genAddrOf (iCode * ic)
9620 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9623 D (emitcode (";", "genAddrOf ");
9626 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9628 /* if the operand is on the stack then we
9629 need to get the stack offset of this
9633 /* if it has an offset then we need to compute
9637 emitcode ("mov", "a,_bp");
9638 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9639 aopPut (AOP (IC_RESULT (ic)), "a", 0);
9643 /* we can just move _bp */
9644 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9646 /* fill the result with zero */
9647 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9650 if (options.stack10bit && size < (FPTRSIZE - 1))
9653 "*** warning: pointer to stack var truncated.\n");
9660 if (options.stack10bit && offset == 2)
9662 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
9666 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9673 /* object not on stack then we need the name */
9674 size = AOP_SIZE (IC_RESULT (ic));
9679 char s[SDCC_NAME_MAX];
9681 sprintf (s, "#(%s >> %d)",
9685 sprintf (s, "#%s", sym->rname);
9686 aopPut (AOP (IC_RESULT (ic)), s, offset++);
9690 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9694 /*-----------------------------------------------------------------*/
9695 /* genArrayInit - generates code for address of */
9696 /*-----------------------------------------------------------------*/
9698 genArrayInit (iCode * ic)
9702 int elementSize = 0, eIndex;
9703 unsigned val, lastVal;
9705 operand *left=IC_LEFT(ic);
9707 D (emitcode (";", "genArrayInit "););
9709 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
9711 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
9713 // Load immediate value into DPTR.
9714 emitcode("mov", "dptr, %s",
9715 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
9717 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
9720 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9721 "Unexpected operand to genArrayInit.\n");
9724 // a regression because of SDCCcse.c:1.52
9725 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9726 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9727 if (options.model == MODEL_FLAT24)
9728 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9732 type = operandType(IC_LEFT(ic));
9734 if (type && type->next)
9736 elementSize = getSize(type->next);
9740 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9741 "can't determine element size in genArrayInit.\n");
9745 iLoop = IC_ARRAYILIST(ic);
9750 bool firstpass = TRUE;
9752 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
9753 iLoop->count, (int)iLoop->literalValue, elementSize);
9759 symbol *tlbl = NULL;
9761 count = ix > 256 ? 256 : ix;
9765 tlbl = newiTempLabel (NULL);
9766 if (firstpass || (count & 0xff))
9768 emitcode("mov", "b, #0x%x", count & 0xff);
9771 emitcode ("", "%05d$:", tlbl->key + 100);
9776 for (eIndex = 0; eIndex < elementSize; eIndex++)
9778 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
9781 emitcode("mov", "a, #0x%x", val);
9785 emitcode("movx", "@dptr, a");
9786 emitcode("inc", "dptr");
9791 emitcode("djnz", "b, %05d$", tlbl->key + 100);
9797 iLoop = iLoop->next;
9800 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
9803 /*-----------------------------------------------------------------*/
9804 /* genFarFarAssign - assignment when both are in far space */
9805 /*-----------------------------------------------------------------*/
9807 genFarFarAssign (operand * result, operand * right, iCode * ic)
9809 int size = AOP_SIZE (right);
9811 symbol *rSym = NULL;
9815 /* quick & easy case. */
9816 D(emitcode(";","genFarFarAssign (1 byte case)"););
9817 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9818 freeAsmop (right, NULL, ic, FALSE);
9819 /* now assign DPTR to result */
9821 aopOp(result, ic, FALSE, FALSE);
9823 aopPut(AOP(result), "a", 0);
9824 freeAsmop(result, NULL, ic, FALSE);
9828 /* See if we've got an underlying symbol to abuse. */
9829 if (IS_SYMOP(result) && OP_SYMBOL(result))
9831 if (IS_TRUE_SYMOP(result))
9833 rSym = OP_SYMBOL(result);
9835 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9837 rSym = OP_SYMBOL(result)->usl.spillLoc;
9841 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9843 /* We can use the '390 auto-toggle feature to good effect here. */
9845 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
9846 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
9847 emitcode ("mov", "dptr,#%s", rSym->rname);
9848 /* DP2 = result, DP1 = right, DP1 is current. */
9851 emitcode("movx", "a,@dptr");
9852 emitcode("movx", "@dptr,a");
9855 emitcode("inc", "dptr");
9856 emitcode("inc", "dptr");
9859 emitcode("mov", "dps, #0");
9860 freeAsmop (right, NULL, ic, FALSE);
9862 some alternative code for processors without auto-toggle
9863 no time to test now, so later well put in...kpb
9864 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
9865 emitcode("mov", "dps, #0x01"); /* Select DPTR2. */
9866 emitcode ("mov", "dptr,#%s", rSym->rname);
9867 /* DP2 = result, DP1 = right, DP1 is current. */
9871 emitcode("movx", "a,@dptr");
9873 emitcode("inc", "dptr");
9874 emitcode("inc", "dps");
9875 emitcode("movx", "@dptr,a");
9877 emitcode("inc", "dptr");
9878 emitcode("inc", "dps");
9880 emitcode("mov", "dps, #0");
9881 freeAsmop (right, NULL, ic, FALSE);
9886 D (emitcode (";", "genFarFarAssign"););
9887 aopOp (result, ic, TRUE, TRUE);
9889 _startLazyDPSEvaluation ();
9893 aopPut (AOP (result),
9894 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9897 _endLazyDPSEvaluation ();
9898 freeAsmop (result, NULL, ic, FALSE);
9899 freeAsmop (right, NULL, ic, FALSE);
9903 /*-----------------------------------------------------------------*/
9904 /* genAssign - generate code for assignment */
9905 /*-----------------------------------------------------------------*/
9907 genAssign (iCode * ic)
9909 operand *result, *right;
9911 unsigned long lit = 0L;
9913 D (emitcode (";", "genAssign ");
9916 result = IC_RESULT (ic);
9917 right = IC_RIGHT (ic);
9919 /* if they are the same */
9920 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9923 aopOp (right, ic, FALSE, FALSE);
9925 emitcode (";", "genAssign: resultIsFar = %s",
9926 isOperandInFarSpace (result) ?
9929 /* special case both in far space */
9930 if ((AOP_TYPE (right) == AOP_DPTR ||
9931 AOP_TYPE (right) == AOP_DPTR2) &&
9932 /* IS_TRUE_SYMOP(result) && */
9933 isOperandInFarSpace (result))
9935 genFarFarAssign (result, right, ic);
9939 aopOp (result, ic, TRUE, FALSE);
9941 /* if they are the same registers */
9942 if (sameRegs (AOP (right), AOP (result)))
9945 /* if the result is a bit */
9946 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
9948 /* if the right size is a literal then
9949 we know what the value is */
9950 if (AOP_TYPE (right) == AOP_LIT)
9952 if (((int) operandLitValue (right)))
9953 aopPut (AOP (result), one, 0);
9955 aopPut (AOP (result), zero, 0);
9959 /* the right is also a bit variable */
9960 if (AOP_TYPE (right) == AOP_CRY)
9962 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9963 aopPut (AOP (result), "c", 0);
9969 aopPut (AOP (result), "a", 0);
9973 /* bit variables done */
9975 size = AOP_SIZE (result);
9977 if (AOP_TYPE (right) == AOP_LIT)
9978 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9981 (AOP_TYPE (result) != AOP_REG) &&
9982 (AOP_TYPE (right) == AOP_LIT) &&
9983 !IS_FLOAT (operandType (right)))
9985 _startLazyDPSEvaluation ();
9986 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9988 aopPut (AOP (result),
9989 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9994 /* And now fill the rest with zeros. */
9997 emitcode ("clr", "a");
10001 aopPut (AOP (result), "a", offset++);
10003 _endLazyDPSEvaluation ();
10007 _startLazyDPSEvaluation ();
10010 aopPut (AOP (result),
10011 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10015 _endLazyDPSEvaluation ();
10019 freeAsmop (right, NULL, ic, FALSE);
10020 freeAsmop (result, NULL, ic, TRUE);
10023 /*-----------------------------------------------------------------*/
10024 /* genJumpTab - generates code for jump table */
10025 /*-----------------------------------------------------------------*/
10027 genJumpTab (iCode * ic)
10032 D (emitcode (";", "genJumpTab ");
10035 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10036 /* get the condition into accumulator */
10037 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10039 /* multiply by four! */
10040 emitcode ("add", "a,acc");
10041 emitcode ("add", "a,acc");
10042 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10044 jtab = newiTempLabel (NULL);
10045 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10046 emitcode ("jmp", "@a+dptr");
10047 emitcode ("", "%05d$:", jtab->key + 100);
10048 /* now generate the jump labels */
10049 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10050 jtab = setNextItem (IC_JTLABELS (ic)))
10051 emitcode ("ljmp", "%05d$", jtab->key + 100);
10055 /*-----------------------------------------------------------------*/
10056 /* genCast - gen code for casting */
10057 /*-----------------------------------------------------------------*/
10059 genCast (iCode * ic)
10061 operand *result = IC_RESULT (ic);
10062 sym_link *ctype = operandType (IC_LEFT (ic));
10063 sym_link *rtype = operandType (IC_RIGHT (ic));
10064 operand *right = IC_RIGHT (ic);
10067 D (emitcode (";", "genCast ");
10070 /* if they are equivalent then do nothing */
10071 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10074 aopOp (right, ic, FALSE, FALSE);
10075 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10077 /* if the result is a bit */
10078 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10079 if (IS_BITVAR(OP_SYMBOL(result)->type))
10081 /* if the right size is a literal then
10082 we know what the value is */
10083 if (AOP_TYPE (right) == AOP_LIT)
10085 if (((int) operandLitValue (right)))
10086 aopPut (AOP (result), one, 0);
10088 aopPut (AOP (result), zero, 0);
10093 /* the right is also a bit variable */
10094 if (AOP_TYPE (right) == AOP_CRY)
10096 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10097 aopPut (AOP (result), "c", 0);
10101 /* we need to or */
10103 aopPut (AOP (result), "a", 0);
10107 /* if they are the same size : or less */
10108 if (AOP_SIZE (result) <= AOP_SIZE (right))
10111 /* if they are in the same place */
10112 if (sameRegs (AOP (right), AOP (result)))
10115 /* if they in different places then copy */
10116 size = AOP_SIZE (result);
10118 _startLazyDPSEvaluation ();
10121 aopPut (AOP (result),
10122 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10126 _endLazyDPSEvaluation ();
10131 /* if the result is of type pointer */
10132 if (IS_PTR (ctype))
10136 sym_link *type = operandType (right);
10138 /* pointer to generic pointer */
10139 if (IS_GENPTR (ctype))
10145 p_type = DCL_TYPE (type);
10149 #if OLD_CAST_BEHAVIOR
10150 /* KV: we are converting a non-pointer type to
10151 * a generic pointer. This (ifdef'd out) code
10152 * says that the resulting generic pointer
10153 * should have the same class as the storage
10154 * location of the non-pointer variable.
10156 * For example, converting an int (which happens
10157 * to be stored in DATA space) to a pointer results
10158 * in a DATA generic pointer; if the original int
10159 * in XDATA space, so will be the resulting pointer.
10161 * I don't like that behavior, and thus this change:
10162 * all such conversions will be forced to XDATA and
10163 * throw a warning. If you want some non-XDATA
10164 * type, or you want to suppress the warning, you
10165 * must go through an intermediate cast, like so:
10167 * char _generic *gp = (char _xdata *)(intVar);
10169 sym_link *etype = getSpec (type);
10171 /* we have to go by the storage class */
10172 if (SPEC_OCLS (etype) != generic)
10174 p_type = PTR_TYPE (SPEC_OCLS (etype));
10179 /* Converting unknown class (i.e. register variable)
10180 * to generic pointer. This is not good, but
10181 * we'll make a guess (and throw a warning).
10184 werror (W_INT_TO_GEN_PTR_CAST);
10188 /* the first two bytes are known */
10189 size = GPTRSIZE - 1;
10191 _startLazyDPSEvaluation ();
10194 aopPut (AOP (result),
10195 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10199 _endLazyDPSEvaluation ();
10201 /* the last byte depending on type */
10219 /* this should never happen */
10220 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10221 "got unknown pointer type");
10224 aopPut (AOP (result), l, GPTRSIZE - 1);
10228 /* just copy the pointers */
10229 size = AOP_SIZE (result);
10231 _startLazyDPSEvaluation ();
10234 aopPut (AOP (result),
10235 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10239 _endLazyDPSEvaluation ();
10243 /* so we now know that the size of destination is greater
10244 than the size of the source */
10245 /* we move to result for the size of source */
10246 size = AOP_SIZE (right);
10248 _startLazyDPSEvaluation ();
10251 aopPut (AOP (result),
10252 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10256 _endLazyDPSEvaluation ();
10258 /* now depending on the sign of the source && destination */
10259 size = AOP_SIZE (result) - AOP_SIZE (right);
10260 /* if unsigned or not an integral type */
10261 /* also, if the source is a bit, we don't need to sign extend, because
10262 * it can't possibly have set the sign bit.
10264 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10268 aopPut (AOP (result), zero, offset++);
10273 /* we need to extend the sign :{ */
10274 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10275 FALSE, FALSE, TRUE);
10277 emitcode ("rlc", "a");
10278 emitcode ("subb", "a,acc");
10280 aopPut (AOP (result), "a", offset++);
10283 /* we are done hurray !!!! */
10286 freeAsmop (right, NULL, ic, TRUE);
10287 freeAsmop (result, NULL, ic, TRUE);
10291 /*-----------------------------------------------------------------*/
10292 /* genDjnz - generate decrement & jump if not zero instrucion */
10293 /*-----------------------------------------------------------------*/
10295 genDjnz (iCode * ic, iCode * ifx)
10297 symbol *lbl, *lbl1;
10301 /* if the if condition has a false label
10302 then we cannot save */
10303 if (IC_FALSE (ifx))
10306 /* if the minus is not of the form
10308 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10309 !IS_OP_LITERAL (IC_RIGHT (ic)))
10312 if (operandLitValue (IC_RIGHT (ic)) != 1)
10315 /* if the size of this greater than one then no
10317 if (getSize (operandType (IC_RESULT (ic))) > 1)
10320 /* otherwise we can save BIG */
10321 D(emitcode(";", "genDjnz"););
10323 lbl = newiTempLabel (NULL);
10324 lbl1 = newiTempLabel (NULL);
10326 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10328 if (AOP_NEEDSACC(IC_RESULT(ic)))
10330 /* If the result is accessed indirectly via
10331 * the accumulator, we must explicitly write
10332 * it back after the decrement.
10334 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10336 if (strcmp(rByte, "a"))
10338 /* Something is hopelessly wrong */
10339 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10340 __FILE__, __LINE__);
10341 /* We can just give up; the generated code will be inefficient,
10342 * but what the hey.
10344 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10347 emitcode ("dec", "%s", rByte);
10348 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10349 emitcode ("jnz", "%05d$", lbl->key + 100);
10351 else if (IS_AOP_PREG (IC_RESULT (ic)))
10353 emitcode ("dec", "%s",
10354 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10355 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10356 emitcode ("jnz", "%05d$", lbl->key + 100);
10360 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10363 emitcode ("sjmp", "%05d$", lbl1->key + 100);
10364 emitcode ("", "%05d$:", lbl->key + 100);
10365 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10366 emitcode ("", "%05d$:", lbl1->key + 100);
10368 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10369 ifx->generated = 1;
10373 /*-----------------------------------------------------------------*/
10374 /* genReceive - generate code for a receive iCode */
10375 /*-----------------------------------------------------------------*/
10377 genReceive (iCode * ic)
10380 D (emitcode (";", "genReceive ");
10383 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10384 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10385 IS_TRUE_SYMOP (IC_RESULT (ic))))
10387 int size = getSize (operandType (IC_RESULT (ic)));
10388 int offset = fReturnSizeDS390 - size;
10391 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10392 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10395 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10396 size = AOP_SIZE (IC_RESULT (ic));
10400 emitcode ("pop", "acc");
10401 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10408 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10410 assignResultValue (IC_RESULT (ic));
10413 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10416 /*-----------------------------------------------------------------*/
10417 /* gen390Code - generate code for Dallas 390 based controllers */
10418 /*-----------------------------------------------------------------*/
10420 gen390Code (iCode * lic)
10425 lineHead = lineCurr = NULL;
10427 if (options.model == MODEL_FLAT24) {
10428 fReturnSizeDS390 = 5;
10429 fReturn = fReturn24;
10431 fReturnSizeDS390 = 4;
10432 fReturn = fReturn16;
10433 options.stack10bit=0;
10437 /* print the allocation information */
10439 printAllocInfo (currFunc, codeOutFile);
10441 /* if debug information required */
10442 if (options.debug && currFunc)
10444 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
10446 if (IS_STATIC (currFunc->etype))
10447 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
10449 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
10452 /* stack pointer name */
10453 if (options.useXstack)
10459 for (ic = lic; ic; ic = ic->next)
10462 if (cln != ic->lineno)
10467 emitcode ("", "C$%s$%d$%d$%d ==.",
10468 FileBaseName (ic->filename), ic->lineno,
10469 ic->level, ic->block);
10472 emitcode (";", "%s %d", ic->filename, ic->lineno);
10475 /* if the result is marked as
10476 spilt and rematerializable or code for
10477 this has already been generated then
10479 if (resultRemat (ic) || ic->generated)
10482 /* depending on the operation */
10502 /* IPOP happens only when trying to restore a
10503 spilt live range, if there is an ifx statement
10504 following this pop then the if statement might
10505 be using some of the registers being popped which
10506 would destory the contents of the register so
10507 we need to check for this condition and handle it */
10509 ic->next->op == IFX &&
10510 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10511 genIfx (ic->next, ic);
10529 genEndFunction (ic);
10549 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10566 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10570 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10577 /* note these two are xlated by algebraic equivalence
10578 during parsing SDCC.y */
10579 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10580 "got '>=' or '<=' shouldn't have come here");
10584 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10596 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10600 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10604 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10628 genRightShift (ic);
10631 case GET_VALUE_AT_ADDRESS:
10632 genPointerGet (ic);
10636 if (POINTER_SET (ic))
10637 genPointerSet (ic);
10663 addSet (&_G.sendSet, ic);
10676 /* now we are ready to call the
10677 peep hole optimizer */
10678 if (!options.nopeep)
10679 peepHole (&lineHead);
10681 /* now do the actual printing */
10682 printLine (lineHead, codeOutFile);