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");
1249 emitcode ("push", "acc");
1251 emitcode ("push", s);
1257 /* if bit variable */
1258 if (!aop->aopu.aop_dir)
1260 emitcode ("clr", "a");
1261 emitcode ("rlc", "a");
1266 emitcode ("clr", "%s", aop->aopu.aop_dir);
1268 emitcode ("setb", "%s", aop->aopu.aop_dir);
1269 else if (!strcmp (s, "c"))
1270 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1273 if (strcmp (s, "a"))
1278 symbol *lbl = newiTempLabel (NULL);
1279 emitcode ("clr", "c");
1280 emitcode ("jz", "%05d$", lbl->key + 100);
1281 emitcode ("cpl", "c");
1282 emitcode ("", "%05d$:", lbl->key + 100);
1283 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1291 if (strcmp (aop->aopu.aop_str[offset], s))
1292 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1297 if (!offset && (strcmp (s, "acc") == 0))
1300 if (strcmp (aop->aopu.aop_str[offset], s))
1301 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1305 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1306 "aopPut got unsupported aop->type");
1313 /*--------------------------------------------------------------------*/
1314 /* reAdjustPreg - points a register back to where it should (coff==0) */
1315 /*--------------------------------------------------------------------*/
1317 reAdjustPreg (asmop * aop)
1319 if ((aop->coff==0) || (aop->size <= 1)) {
1328 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1332 if (aop->type == AOP_DPTR2)
1339 emitcode ("lcall", "__decdptr");
1342 if (aop->type == AOP_DPTR2)
1352 #define AOP(op) op->aop
1353 #define AOP_TYPE(op) AOP(op)->type
1354 #define AOP_SIZE(op) AOP(op)->size
1355 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1356 AOP_TYPE(x) == AOP_R0))
1358 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1359 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1362 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1363 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1364 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1366 /* Workaround for DS80C390 bug: div ab may return bogus results
1367 * if A is accessed in instruction immediately before the div.
1369 * Will be fixed in B4 rev of processor, Dallas claims.
1372 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1373 if (!AOP_NEEDSACC(RIGHT)) \
1375 /* We can load A first, then B, since \
1376 * B (the RIGHT operand) won't clobber A, \
1377 * thus avoiding touching A right before the div. \
1379 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1380 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1382 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1386 /* Just stuff in a nop after loading A. */ \
1387 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1388 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1390 emitcode("nop", "; workaround for DS80C390 div bug."); \
1393 /*-----------------------------------------------------------------*/
1394 /* genNotFloat - generates not for float operations */
1395 /*-----------------------------------------------------------------*/
1397 genNotFloat (operand * op, operand * res)
1403 D (emitcode (";", "genNotFloat ");
1406 /* we will put 127 in the first byte of
1408 aopPut (AOP (res), "#127", 0);
1409 size = AOP_SIZE (op) - 1;
1412 _startLazyDPSEvaluation ();
1413 l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1418 emitcode ("orl", "a,%s",
1420 offset++, FALSE, FALSE, FALSE));
1422 _endLazyDPSEvaluation ();
1424 tlbl = newiTempLabel (NULL);
1425 aopPut (res->aop, one, 1);
1426 emitcode ("jz", "%05d$", (tlbl->key + 100));
1427 aopPut (res->aop, zero, 1);
1428 emitcode ("", "%05d$:", (tlbl->key + 100));
1430 size = res->aop->size - 2;
1432 /* put zeros in the rest */
1434 aopPut (res->aop, zero, offset++);
1437 /*-----------------------------------------------------------------*/
1438 /* opIsGptr: returns non-zero if the passed operand is */
1439 /* a generic pointer type. */
1440 /*-----------------------------------------------------------------*/
1442 opIsGptr (operand * op)
1444 sym_link *type = operandType (op);
1446 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1453 /*-----------------------------------------------------------------*/
1454 /* getDataSize - get the operand data size */
1455 /*-----------------------------------------------------------------*/
1457 getDataSize (operand * op)
1460 size = AOP_SIZE (op);
1461 if (size == GPTRSIZE)
1463 sym_link *type = operandType (op);
1464 if (IS_GENPTR (type))
1466 /* generic pointer; arithmetic operations
1467 * should ignore the high byte (pointer type).
1475 /*-----------------------------------------------------------------*/
1476 /* outAcc - output Acc */
1477 /*-----------------------------------------------------------------*/
1479 outAcc (operand * result)
1482 size = getDataSize (result);
1485 aopPut (AOP (result), "a", 0);
1488 /* unsigned or positive */
1491 aopPut (AOP (result), zero, offset++);
1496 /*-----------------------------------------------------------------*/
1497 /* outBitC - output a bit C */
1498 /*-----------------------------------------------------------------*/
1500 outBitC (operand * result)
1502 /* if the result is bit */
1503 if (AOP_TYPE (result) == AOP_CRY)
1505 aopPut (AOP (result), "c", 0);
1509 emitcode ("clr", "a");
1510 emitcode ("rlc", "a");
1515 /*-----------------------------------------------------------------*/
1516 /* toBoolean - emit code for orl a,operator(sizeop) */
1517 /*-----------------------------------------------------------------*/
1519 toBoolean (operand * oper)
1521 int size = AOP_SIZE (oper) - 1;
1525 /* The generic part of a generic pointer should
1526 * not participate in it's truth value.
1528 * i.e. 0x10000000 is zero.
1530 if (opIsGptr (oper))
1532 D (emitcode (";", "toBoolean: generic ptr special case.");
1537 _startLazyDPSEvaluation ();
1538 if (AOP_NEEDSACC (oper) && size)
1541 emitcode ("push", "b");
1542 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1546 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1552 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1556 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1559 _endLazyDPSEvaluation ();
1563 emitcode ("mov", "a,b");
1564 emitcode ("pop", "b");
1569 /*-----------------------------------------------------------------*/
1570 /* genNot - generate code for ! operation */
1571 /*-----------------------------------------------------------------*/
1576 sym_link *optype = operandType (IC_LEFT (ic));
1578 D (emitcode (";", "genNot ");
1581 /* assign asmOps to operand & result */
1582 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1583 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1585 /* if in bit space then a special case */
1586 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1588 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1589 emitcode ("cpl", "c");
1590 outBitC (IC_RESULT (ic));
1594 /* if type float then do float */
1595 if (IS_FLOAT (optype))
1597 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1601 toBoolean (IC_LEFT (ic));
1603 tlbl = newiTempLabel (NULL);
1604 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1605 emitcode ("", "%05d$:", tlbl->key + 100);
1606 outBitC (IC_RESULT (ic));
1609 /* release the aops */
1610 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1611 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1615 /*-----------------------------------------------------------------*/
1616 /* genCpl - generate code for complement */
1617 /*-----------------------------------------------------------------*/
1624 D (emitcode (";", "genCpl ");
1628 /* assign asmOps to operand & result */
1629 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1630 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1632 /* if both are in bit space then
1634 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1635 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1638 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1639 emitcode ("cpl", "c");
1640 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1644 size = AOP_SIZE (IC_RESULT (ic));
1645 _startLazyDPSEvaluation ();
1648 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1650 emitcode ("cpl", "a");
1651 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1653 _endLazyDPSEvaluation ();
1657 /* release the aops */
1658 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1659 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1662 /*-----------------------------------------------------------------*/
1663 /* genUminusFloat - unary minus for floating points */
1664 /*-----------------------------------------------------------------*/
1666 genUminusFloat (operand * op, operand * result)
1668 int size, offset = 0;
1670 /* for this we just need to flip the
1671 first it then copy the rest in place */
1672 D (emitcode (";", "genUminusFloat");
1675 _startLazyDPSEvaluation ();
1676 size = AOP_SIZE (op) - 1;
1677 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1680 emitcode ("cpl", "acc.7");
1681 aopPut (AOP (result), "a", 3);
1685 aopPut (AOP (result),
1686 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1690 _endLazyDPSEvaluation ();
1693 /*-----------------------------------------------------------------*/
1694 /* genUminus - unary minus code generation */
1695 /*-----------------------------------------------------------------*/
1697 genUminus (iCode * ic)
1700 sym_link *optype, *rtype;
1702 D (emitcode (";", "genUminus ");
1707 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1708 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1710 /* if both in bit space then special
1712 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1713 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1716 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1717 emitcode ("cpl", "c");
1718 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1722 optype = operandType (IC_LEFT (ic));
1723 rtype = operandType (IC_RESULT (ic));
1725 /* if float then do float stuff */
1726 if (IS_FLOAT (optype))
1728 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1732 /* otherwise subtract from zero */
1733 size = AOP_SIZE (IC_LEFT (ic));
1735 _startLazyDPSEvaluation ();
1738 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1739 if (!strcmp (l, "a"))
1743 emitcode ("cpl", "a");
1744 emitcode ("addc", "a,#0");
1750 emitcode ("clr", "a");
1751 emitcode ("subb", "a,%s", l);
1753 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1755 _endLazyDPSEvaluation ();
1757 /* if any remaining bytes in the result */
1758 /* we just need to propagate the sign */
1759 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1761 emitcode ("rlc", "a");
1762 emitcode ("subb", "a,acc");
1764 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1768 /* release the aops */
1769 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1770 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1773 /*-----------------------------------------------------------------*/
1774 /* saveRegisters - will look for a call and save the registers */
1775 /*-----------------------------------------------------------------*/
1777 saveRegisters (iCode * lic)
1785 for (ic = lic; ic; ic = ic->next)
1786 if (ic->op == CALL || ic->op == PCALL)
1791 fprintf (stderr, "found parameter push with no function call\n");
1795 /* if the registers have been saved already then
1797 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type) ||
1798 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))))
1801 /* find the registers in use at this time
1802 and push them away to safety */
1803 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1807 if (options.useXstack)
1809 if (bitVectBitValue (rsave, R0_IDX))
1810 emitcode ("mov", "b,r0");
1811 emitcode ("mov", "r0,%s", spname);
1812 for (i = 0; i < ds390_nRegs; i++)
1814 if (bitVectBitValue (rsave, i))
1817 emitcode ("mov", "a,b");
1819 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1820 emitcode ("movx", "@r0,a");
1821 emitcode ("inc", "r0");
1824 emitcode ("mov", "%s,r0", spname);
1825 if (bitVectBitValue (rsave, R0_IDX))
1826 emitcode ("mov", "r0,b");
1829 for (i = 0; i < ds390_nRegs; i++)
1831 if (bitVectBitValue (rsave, i))
1832 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1835 detype = getSpec (operandType (IC_LEFT (ic)));
1838 /*-----------------------------------------------------------------*/
1839 /* unsaveRegisters - pop the pushed registers */
1840 /*-----------------------------------------------------------------*/
1842 unsaveRegisters (iCode * ic)
1846 /* find the registers in use at this time
1847 and push them away to safety */
1848 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1851 if (options.useXstack)
1853 emitcode ("mov", "r0,%s", spname);
1854 for (i = ds390_nRegs; i >= 0; i--)
1856 if (bitVectBitValue (rsave, i))
1858 emitcode ("dec", "r0");
1859 emitcode ("movx", "a,@r0");
1861 emitcode ("mov", "b,a");
1863 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1867 emitcode ("mov", "%s,r0", spname);
1868 if (bitVectBitValue (rsave, R0_IDX))
1869 emitcode ("mov", "r0,b");
1872 for (i = ds390_nRegs; i >= 0; i--)
1874 if (bitVectBitValue (rsave, i))
1875 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1881 /*-----------------------------------------------------------------*/
1883 /*-----------------------------------------------------------------*/
1885 pushSide (operand * oper, int size)
1888 _startLazyDPSEvaluation ();
1891 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1892 if (AOP_TYPE (oper) != AOP_REG &&
1893 AOP_TYPE (oper) != AOP_DIR &&
1896 emitcode ("mov", "a,%s", l);
1897 emitcode ("push", "acc");
1900 emitcode ("push", "%s", l);
1902 _endLazyDPSEvaluation ();
1905 /*-----------------------------------------------------------------*/
1906 /* assignResultValue - */
1907 /*-----------------------------------------------------------------*/
1909 assignResultValue (operand * oper)
1912 int size = AOP_SIZE (oper);
1914 _startLazyDPSEvaluation ();
1917 aopPut (AOP (oper), fReturn[offset], offset);
1920 _endLazyDPSEvaluation ();
1924 /*-----------------------------------------------------------------*/
1925 /* genXpush - pushes onto the external stack */
1926 /*-----------------------------------------------------------------*/
1928 genXpush (iCode * ic)
1930 asmop *aop = newAsmop (0);
1932 int size, offset = 0;
1934 D (emitcode (";", "genXpush ");
1937 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1938 r = getFreePtr (ic, &aop, FALSE);
1941 emitcode ("mov", "%s,_spx", r->name);
1943 size = AOP_SIZE (IC_LEFT (ic));
1944 _startLazyDPSEvaluation ();
1948 char *l = aopGet (AOP (IC_LEFT (ic)),
1949 offset++, FALSE, FALSE, TRUE);
1951 emitcode ("movx", "@%s,a", r->name);
1952 emitcode ("inc", "%s", r->name);
1955 _endLazyDPSEvaluation ();
1958 emitcode ("mov", "_spx,%s", r->name);
1960 freeAsmop (NULL, aop, ic, TRUE);
1961 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1964 /*-----------------------------------------------------------------*/
1965 /* genIpush - genrate code for pushing this gets a little complex */
1966 /*-----------------------------------------------------------------*/
1968 genIpush (iCode * ic)
1970 int size, offset = 0;
1973 D (emitcode (";", "genIpush ");
1976 /* if this is not a parm push : ie. it is spill push
1977 and spill push is always done on the local stack */
1981 /* and the item is spilt then do nothing */
1982 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1985 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1986 size = AOP_SIZE (IC_LEFT (ic));
1987 /* push it on the stack */
1988 _startLazyDPSEvaluation ();
1991 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1997 emitcode ("push", "%s", l);
1999 _endLazyDPSEvaluation ();
2003 /* this is a paramter push: in this case we call
2004 the routine to find the call and save those
2005 registers that need to be saved */
2008 /* if use external stack then call the external
2009 stack pushing routine */
2010 if (options.useXstack)
2016 /* then do the push */
2017 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2019 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2020 size = AOP_SIZE (IC_LEFT (ic));
2022 _startLazyDPSEvaluation ();
2025 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2026 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2027 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2030 emitcode ("mov", "a,%s", l);
2031 emitcode ("push", "acc");
2034 emitcode ("push", "%s", l);
2036 _endLazyDPSEvaluation ();
2038 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2041 /*-----------------------------------------------------------------*/
2042 /* genIpop - recover the registers: can happen only for spilling */
2043 /*-----------------------------------------------------------------*/
2045 genIpop (iCode * ic)
2049 D (emitcode (";", "genIpop ");
2053 /* if the temp was not pushed then */
2054 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2057 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2058 size = AOP_SIZE (IC_LEFT (ic));
2059 offset = (size - 1);
2060 _startLazyDPSEvaluation ();
2063 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2064 FALSE, TRUE, TRUE));
2066 _endLazyDPSEvaluation ();
2068 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2071 /*-----------------------------------------------------------------*/
2072 /* unsaveRBank - restores the resgister bank from stack */
2073 /*-----------------------------------------------------------------*/
2075 unsaveRBank (int bank, iCode * ic, bool popPsw)
2081 if (options.useXstack)
2085 /* Assume r0 is available for use. */
2086 r = ds390_regWithIdx (R0_IDX);;
2091 r = getFreePtr (ic, &aop, FALSE);
2093 emitcode ("mov", "%s,_spx", r->name);
2098 if (options.useXstack)
2100 emitcode ("movx", "a,@%s", r->name);
2101 emitcode ("mov", "psw,a");
2102 emitcode ("dec", "%s", r->name);
2106 emitcode ("pop", "psw");
2110 for (i = (ds390_nRegs - 1); i >= 0; i--)
2112 if (options.useXstack)
2114 emitcode ("movx", "a,@%s", r->name);
2115 emitcode ("mov", "(%s+%d),a",
2116 regs390[i].base, 8 * bank + regs390[i].offset);
2117 emitcode ("dec", "%s", r->name);
2121 emitcode ("pop", "(%s+%d)",
2122 regs390[i].base, 8 * bank + regs390[i].offset);
2125 if (options.useXstack)
2127 emitcode ("mov", "_spx,%s", r->name);
2132 freeAsmop (NULL, aop, ic, TRUE);
2136 /*-----------------------------------------------------------------*/
2137 /* saveRBank - saves an entire register bank on the stack */
2138 /*-----------------------------------------------------------------*/
2140 saveRBank (int bank, iCode * ic, bool pushPsw)
2146 if (options.useXstack)
2150 /* Assume r0 is available for use. */
2151 r = ds390_regWithIdx (R0_IDX);;
2156 r = getFreePtr (ic, &aop, FALSE);
2158 emitcode ("mov", "%s,_spx", r->name);
2161 for (i = 0; i < ds390_nRegs; i++)
2163 if (options.useXstack)
2165 emitcode ("inc", "%s", r->name);
2166 emitcode ("mov", "a,(%s+%d)",
2167 regs390[i].base, 8 * bank + regs390[i].offset);
2168 emitcode ("movx", "@%s,a", r->name);
2171 emitcode ("push", "(%s+%d)",
2172 regs390[i].base, 8 * bank + regs390[i].offset);
2177 if (options.useXstack)
2179 emitcode ("mov", "a,psw");
2180 emitcode ("movx", "@%s,a", r->name);
2181 emitcode ("inc", "%s", r->name);
2182 emitcode ("mov", "_spx,%s", r->name);
2186 emitcode ("push", "psw");
2189 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2194 freeAsmop (NULL, aop, ic, TRUE);
2203 /*-----------------------------------------------------------------*/
2204 /* genCall - generates a call statement */
2205 /*-----------------------------------------------------------------*/
2207 genCall (iCode * ic)
2210 bool restoreBank = FALSE;
2211 bool swapBanks = FALSE;
2213 D (emitcode (";", "genCall "););
2215 /* if we are calling a not _naked function that is not using
2216 the same register bank then we need to save the
2217 destination registers on the stack */
2218 dtype = operandType (IC_LEFT (ic));
2219 if (dtype && !IFFUNC_ISNAKED(dtype) &&
2220 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2221 IFFUNC_ISISR (currFunc->type))
2225 /* This is unexpected; the bank should have been saved in
2228 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2234 /* if caller saves & we have not saved then */
2238 /* if send set is not empty the assign */
2239 /* We've saved all the registers we care about;
2240 * therefore, we may clobber any register not used
2241 * in the calling convention (i.e. anything not in
2248 for (sic = setFirstItem (_G.sendSet); sic;
2249 sic = setNextItem (_G.sendSet))
2251 int size, offset = 0;
2253 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2254 size = AOP_SIZE (IC_LEFT (sic));
2256 _startLazyDPSEvaluation ();
2259 char *l = aopGet (AOP(IC_LEFT(sic)), offset,
2260 FALSE, FALSE, TRUE);
2261 if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size)
2263 emitcode("mov", "%s,%s", regs390[offset].name, l);
2265 else if (strcmp (l, fReturn[offset]))
2267 emitcode ("mov", "%s,%s",
2273 _endLazyDPSEvaluation ();
2274 if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR)
2276 size = AOP_SIZE (IC_LEFT (sic));
2284 emitcode("mov", "%s,%s",
2285 fReturn[size], regs390[size].name);
2288 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2295 emitcode ("mov", "psw,#0x%02x",
2296 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2300 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2301 OP_SYMBOL (IC_LEFT (ic))->rname :
2302 OP_SYMBOL (IC_LEFT (ic))->name));
2306 emitcode ("mov", "psw,#0x%02x",
2307 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2310 /* if we need assign a result value */
2311 if ((IS_ITEMP (IC_RESULT (ic)) &&
2312 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2313 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2314 IS_TRUE_SYMOP (IC_RESULT (ic)))
2316 if (isOperandInFarSpace (IC_RESULT (ic))
2317 && getSize (operandType (IC_RESULT (ic))) <= 2)
2319 int size = getSize (operandType (IC_RESULT (ic)));
2321 /* Special case for 1 or 2 byte return in far space. */
2325 emitcode ("mov", "b,%s", fReturn[1]);
2328 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2329 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2333 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2335 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2340 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2343 assignResultValue (IC_RESULT (ic));
2345 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2349 /* adjust the stack for parameters if
2354 if (ic->parmBytes > 3)
2356 emitcode ("mov", "a,%s", spname);
2357 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2358 emitcode ("mov", "%s,a", spname);
2361 for (i = 0; i < ic->parmBytes; i++)
2362 emitcode ("dec", "%s", spname);
2365 /* if we hade saved some registers then unsave them */
2366 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2367 unsaveRegisters (ic);
2369 /* if register bank was saved then pop them */
2371 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2374 /*-----------------------------------------------------------------*/
2375 /* genPcall - generates a call by pointer statement */
2376 /*-----------------------------------------------------------------*/
2378 genPcall (iCode * ic)
2381 symbol *rlbl = newiTempLabel (NULL);
2382 bool restoreBank=FALSE;
2384 D (emitcode (";", "genPcall ");
2388 /* if caller saves & we have not saved then */
2392 /* if we are calling a function that is not using
2393 the same register bank then we need to save the
2394 destination registers on the stack */
2395 dtype = operandType (IC_LEFT (ic));
2396 if (dtype && !IFFUNC_ISNAKED(dtype) &&
2397 IFFUNC_ISISR (currFunc->type) &&
2398 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2399 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2403 /* push the return address on to the stack */
2404 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2405 emitcode ("push", "acc");
2406 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2407 emitcode ("push", "acc");
2409 if (options.model == MODEL_FLAT24)
2411 emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2412 emitcode ("push", "acc");
2415 /* now push the calling address */
2416 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2418 pushSide (IC_LEFT (ic), FPTRSIZE);
2420 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2422 /* if send set is not empty the assign */
2427 for (sic = setFirstItem (_G.sendSet); sic;
2428 sic = setNextItem (_G.sendSet))
2430 int size, offset = 0;
2432 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2433 size = AOP_SIZE (IC_LEFT (sic));
2434 _startLazyDPSEvaluation ();
2437 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2438 FALSE, FALSE, TRUE);
2439 if (strcmp (l, fReturn[offset]))
2441 emitcode ("mov", "%s,%s",
2447 _endLazyDPSEvaluation ();
2448 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2453 emitcode ("ret", "");
2454 emitcode ("", "%05d$:", (rlbl->key + 100));
2457 /* if we need assign a result value */
2458 if ((IS_ITEMP (IC_RESULT (ic)) &&
2459 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2460 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2461 IS_TRUE_SYMOP (IC_RESULT (ic)))
2465 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2468 assignResultValue (IC_RESULT (ic));
2470 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2473 /* adjust the stack for parameters if
2478 if (ic->parmBytes > 3)
2480 emitcode ("mov", "a,%s", spname);
2481 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2482 emitcode ("mov", "%s,a", spname);
2485 for (i = 0; i < ic->parmBytes; i++)
2486 emitcode ("dec", "%s", spname);
2490 /* if register bank was saved then unsave them */
2492 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2494 /* if we hade saved some registers then
2496 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2497 unsaveRegisters (ic);
2501 /*-----------------------------------------------------------------*/
2502 /* resultRemat - result is rematerializable */
2503 /*-----------------------------------------------------------------*/
2505 resultRemat (iCode * ic)
2507 if (SKIP_IC (ic) || ic->op == IFX)
2510 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2512 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2513 if (sym->remat && !POINTER_SET (ic))
2520 #if defined(__BORLANDC__) || defined(_MSC_VER)
2521 #define STRCASECMP stricmp
2523 #define STRCASECMP strcasecmp
2526 /*-----------------------------------------------------------------*/
2527 /* inExcludeList - return 1 if the string is in exclude Reg list */
2528 /*-----------------------------------------------------------------*/
2530 inExcludeList (char *s)
2534 if (options.excludeRegs[i] &&
2535 STRCASECMP (options.excludeRegs[i], "none") == 0)
2538 for (i = 0; options.excludeRegs[i]; i++)
2540 if (options.excludeRegs[i] &&
2541 STRCASECMP (s, options.excludeRegs[i]) == 0)
2547 /*-----------------------------------------------------------------*/
2548 /* genFunction - generated code for function entry */
2549 /*-----------------------------------------------------------------*/
2551 genFunction (iCode * ic)
2555 bool switchedPSW = FALSE;
2557 D (emitcode (";", "genFunction "););
2560 /* create the function header */
2561 emitcode (";", "-----------------------------------------");
2562 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2563 emitcode (";", "-----------------------------------------");
2565 emitcode ("", "%s:", sym->rname);
2566 ftype = operandType (IC_LEFT (ic));
2568 if (IFFUNC_ISNAKED(ftype))
2570 emitcode(";", "naked function: no prologue.");
2574 /* if critical function then turn interrupts off */
2575 if (IFFUNC_ISCRITICAL (ftype))
2576 emitcode ("clr", "ea");
2578 /* here we need to generate the equates for the
2579 register bank if required */
2580 if (FUNC_REGBANK (ftype) != rbank)
2584 rbank = FUNC_REGBANK (ftype);
2585 for (i = 0; i < ds390_nRegs; i++)
2587 if (strcmp (regs390[i].base, "0") == 0)
2588 emitcode ("", "%s = 0x%02x",
2590 8 * rbank + regs390[i].offset);
2592 emitcode ("", "%s = %s + 0x%02x",
2595 8 * rbank + regs390[i].offset);
2599 /* if this is an interrupt service routine then
2600 save acc, b, dpl, dph */
2601 if (IFFUNC_ISISR (sym->type))
2604 if (!inExcludeList ("acc"))
2605 emitcode ("push", "acc");
2606 if (!inExcludeList ("b"))
2607 emitcode ("push", "b");
2608 if (!inExcludeList ("dpl"))
2609 emitcode ("push", "dpl");
2610 if (!inExcludeList ("dph"))
2611 emitcode ("push", "dph");
2612 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2614 emitcode ("push", "dpx");
2615 /* Make sure we're using standard DPTR */
2616 emitcode ("push", "dps");
2617 emitcode ("mov", "dps, #0x00");
2618 if (options.stack10bit)
2620 /* This ISR could conceivably use DPTR2. Better save it. */
2621 emitcode ("push", "dpl1");
2622 emitcode ("push", "dph1");
2623 emitcode ("push", "dpx1");
2624 emitcode ("push", DP2_RESULT_REG);
2627 /* if this isr has no bank i.e. is going to
2628 run with bank 0 , then we need to save more
2630 if (!FUNC_REGBANK (sym->type))
2633 /* if this function does not call any other
2634 function then we can be economical and
2635 save only those registers that are used */
2636 if (!IFFUNC_HASFCALL(sym->type))
2640 /* if any registers used */
2643 /* save the registers used */
2644 for (i = 0; i < sym->regsUsed->size; i++)
2646 if (bitVectBitValue (sym->regsUsed, i) ||
2647 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2648 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2655 /* this function has a function call cannot
2656 determines register usage so we will have to push the
2658 saveRBank (0, ic, FALSE);
2663 /* This ISR uses a non-zero bank.
2665 * We assume that the bank is available for our
2668 * However, if this ISR calls a function which uses some
2669 * other bank, we must save that bank entirely.
2671 unsigned long banksToSave = 0;
2673 if (IFFUNC_HASFCALL(sym->type))
2676 #define MAX_REGISTER_BANKS 4
2681 for (i = ic; i; i = i->next)
2683 if (i->op == ENDFUNCTION)
2685 /* we got to the end OK. */
2693 dtype = operandType (IC_LEFT(i));
2695 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2697 /* Mark this bank for saving. */
2698 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2700 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2704 banksToSave |= (1 << FUNC_REGBANK(dtype));
2707 /* And note that we don't need to do it in
2715 /* This is a mess; we have no idea what
2716 * register bank the called function might
2719 * The only thing I can think of to do is
2720 * throw a warning and hope.
2722 werror(W_FUNCPTR_IN_USING_ISR);
2726 if (banksToSave && options.useXstack)
2728 /* Since we aren't passing it an ic,
2729 * saveRBank will assume r0 is available to abuse.
2731 * So switch to our (trashable) bank now, so
2732 * the caller's R0 isn't trashed.
2734 emitcode ("push", "psw");
2735 emitcode ("mov", "psw,#0x%02x",
2736 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2740 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2742 if (banksToSave & (1 << ix))
2744 saveRBank(ix, NULL, FALSE);
2748 // jwk: this needs a closer look
2749 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2754 /* if callee-save to be used for this function
2755 then save the registers being used in this function */
2756 if (IFFUNC_CALLEESAVES(sym->type))
2760 /* if any registers used */
2763 /* save the registers used */
2764 for (i = 0; i < sym->regsUsed->size; i++)
2766 if (bitVectBitValue (sym->regsUsed, i) ||
2767 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2769 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2777 /* set the register bank to the desired value */
2778 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2781 emitcode ("push", "psw");
2782 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2785 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2788 if (options.useXstack)
2790 emitcode ("mov", "r0,%s", spname);
2791 emitcode ("mov", "a,_bp");
2792 emitcode ("movx", "@r0,a");
2793 emitcode ("inc", "%s", spname);
2797 /* set up the stack */
2798 emitcode ("push", "_bp"); /* save the callers stack */
2800 emitcode ("mov", "_bp,%s", spname);
2803 /* adjust the stack for the function */
2809 werror (W_STACK_OVERFLOW, sym->name);
2811 if (i > 3 && sym->recvSize < 4)
2814 emitcode ("mov", "a,sp");
2815 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2816 emitcode ("mov", "sp,a");
2821 emitcode ("inc", "sp");
2827 emitcode ("mov", "a,_spx");
2828 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2829 emitcode ("mov", "_spx,a");
2834 /*-----------------------------------------------------------------*/
2835 /* genEndFunction - generates epilogue for functions */
2836 /*-----------------------------------------------------------------*/
2838 genEndFunction (iCode * ic)
2840 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2842 D (emitcode (";", "genEndFunction "););
2844 if (IFFUNC_ISNAKED(sym->type))
2846 emitcode(";", "naked function: no epilogue.");
2850 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2852 emitcode ("mov", "%s,_bp", spname);
2855 /* if use external stack but some variables were
2856 added to the local stack then decrement the
2858 if (options.useXstack && sym->stack)
2860 emitcode ("mov", "a,sp");
2861 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2862 emitcode ("mov", "sp,a");
2866 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2868 if (options.useXstack)
2870 emitcode ("mov", "r0,%s", spname);
2871 emitcode ("movx", "a,@r0");
2872 emitcode ("mov", "_bp,a");
2873 emitcode ("dec", "%s", spname);
2877 emitcode ("pop", "_bp");
2881 /* restore the register bank */
2882 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2884 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
2885 || !options.useXstack)
2887 /* Special case of ISR using non-zero bank with useXstack
2890 emitcode ("pop", "psw");
2894 if (IFFUNC_ISISR (sym->type))
2897 /* now we need to restore the registers */
2898 /* if this isr has no bank i.e. is going to
2899 run with bank 0 , then we need to save more
2901 if (!FUNC_REGBANK (sym->type))
2903 /* if this function does not call any other
2904 function then we can be economical and
2905 save only those registers that are used */
2906 if (!IFFUNC_HASFCALL(sym->type))
2910 /* if any registers used */
2913 /* save the registers used */
2914 for (i = sym->regsUsed->size; i >= 0; i--)
2916 if (bitVectBitValue (sym->regsUsed, i) ||
2917 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2918 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2925 /* this function has a function call cannot
2926 determines register usage so we will have to pop the
2928 unsaveRBank (0, ic, FALSE);
2933 /* This ISR uses a non-zero bank.
2935 * Restore any register banks saved by genFunction
2938 // jwk: this needs a closer look
2939 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2942 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2944 if (savedBanks & (1 << ix))
2946 unsaveRBank(ix, NULL, FALSE);
2950 if (options.useXstack)
2952 /* Restore bank AFTER calling unsaveRBank,
2953 * since it can trash r0.
2955 emitcode ("pop", "psw");
2959 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2961 if (options.stack10bit)
2963 emitcode ("pop", DP2_RESULT_REG);
2964 emitcode ("pop", "dpx1");
2965 emitcode ("pop", "dph1");
2966 emitcode ("pop", "dpl1");
2968 emitcode ("pop", "dps");
2969 emitcode ("pop", "dpx");
2971 if (!inExcludeList ("dph"))
2972 emitcode ("pop", "dph");
2973 if (!inExcludeList ("dpl"))
2974 emitcode ("pop", "dpl");
2975 if (!inExcludeList ("b"))
2976 emitcode ("pop", "b");
2977 if (!inExcludeList ("acc"))
2978 emitcode ("pop", "acc");
2980 if (IFFUNC_ISCRITICAL (sym->type))
2981 emitcode ("setb", "ea");
2983 /* if debug then send end of function */
2984 if (options.debug && currFunc) {
2986 emitcode ("", "C$%s$%d$%d$%d ==.",
2987 FileBaseName (ic->filename), currFunc->lastLine,
2988 ic->level, ic->block);
2989 if (IS_STATIC (currFunc->etype))
2990 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2992 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2996 emitcode ("reti", "");
3000 if (IFFUNC_ISCRITICAL (sym->type))
3001 emitcode ("setb", "ea");
3003 if (IFFUNC_CALLEESAVES(sym->type))
3007 /* if any registers used */
3010 /* save the registers used */
3011 for (i = sym->regsUsed->size; i >= 0; i--)
3013 if (bitVectBitValue (sym->regsUsed, i) ||
3014 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3015 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3021 /* if debug then send end of function */
3022 if (options.debug && currFunc)
3025 emitcode ("", "C$%s$%d$%d$%d ==.",
3026 FileBaseName (ic->filename), currFunc->lastLine,
3027 ic->level, ic->block);
3028 if (IS_STATIC (currFunc->etype))
3029 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3031 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3035 emitcode ("ret", "");
3040 /*-----------------------------------------------------------------*/
3041 /* genRet - generate code for return statement */
3042 /*-----------------------------------------------------------------*/
3046 int size, offset = 0, pushed = 0;
3048 D (emitcode (";", "genRet ");
3051 /* if we have no return value then
3052 just generate the "ret" */
3056 /* we have something to return then
3057 move the return value into place */
3058 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
3059 size = AOP_SIZE (IC_LEFT (ic));
3061 _startLazyDPSEvaluation ();
3065 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3067 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3068 FALSE, TRUE, FALSE);
3069 emitcode ("push", "%s", l);
3074 /* Since A is the last element of fReturn,
3075 * is is OK to clobber it in the aopGet.
3077 l = aopGet (AOP (IC_LEFT (ic)), offset,
3078 FALSE, FALSE, TRUE);
3079 if (strcmp (fReturn[offset], l))
3080 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3083 _endLazyDPSEvaluation ();
3090 if (strcmp (fReturn[pushed], "a"))
3091 emitcode ("pop", fReturn[pushed]);
3093 emitcode ("pop", "acc");
3096 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3099 /* generate a jump to the return label
3100 if the next is not the return statement */
3101 if (!(ic->next && ic->next->op == LABEL &&
3102 IC_LABEL (ic->next) == returnLabel))
3104 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3108 /*-----------------------------------------------------------------*/
3109 /* genLabel - generates a label */
3110 /*-----------------------------------------------------------------*/
3112 genLabel (iCode * ic)
3114 /* special case never generate */
3115 if (IC_LABEL (ic) == entryLabel)
3118 D (emitcode (";", "genLabel ");
3121 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3124 /*-----------------------------------------------------------------*/
3125 /* genGoto - generates a ljmp */
3126 /*-----------------------------------------------------------------*/
3128 genGoto (iCode * ic)
3130 D (emitcode (";", "genGoto ");
3132 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3135 /*-----------------------------------------------------------------*/
3136 /* findLabelBackwards: walks back through the iCode chain looking */
3137 /* for the given label. Returns number of iCode instructions */
3138 /* between that label and given ic. */
3139 /* Returns zero if label not found. */
3140 /*-----------------------------------------------------------------*/
3142 findLabelBackwards (iCode * ic, int key)
3151 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3153 /* printf("findLabelBackwards = %d\n", count); */
3161 /*-----------------------------------------------------------------*/
3162 /* genPlusIncr :- does addition with increment if possible */
3163 /*-----------------------------------------------------------------*/
3165 genPlusIncr (iCode * ic)
3167 unsigned int icount;
3168 unsigned int size = getDataSize (IC_RESULT (ic));
3170 /* will try to generate an increment */
3171 /* if the right side is not a literal
3173 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3176 /* if the literal value of the right hand side
3177 is greater than 4 then it is not worth it */
3178 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3181 /* if increment 16 bits in register */
3183 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3184 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3185 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3193 /* If the next instruction is a goto and the goto target
3194 * is <= 5 instructions previous to this, we can generate
3195 * jumps straight to that target.
3197 if (ic->next && ic->next->op == GOTO
3198 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3201 emitcode (";", "tail increment optimized (range %d)", labelRange);
3202 tlbl = IC_LABEL (ic->next);
3207 tlbl = newiTempLabel (NULL);
3210 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3211 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3212 IS_AOP_PREG (IC_RESULT (ic)))
3213 emitcode ("cjne", "%s,#0x00,%05d$"
3214 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3218 emitcode ("clr", "a");
3219 emitcode ("cjne", "a,%s,%05d$"
3220 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3224 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3227 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3228 IS_AOP_PREG (IC_RESULT (ic)))
3229 emitcode ("cjne", "%s,#0x00,%05d$"
3230 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3233 emitcode ("cjne", "a,%s,%05d$"
3234 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3237 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3241 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3242 IS_AOP_PREG (IC_RESULT (ic)))
3243 emitcode ("cjne", "%s,#0x00,%05d$"
3244 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3248 emitcode ("cjne", "a,%s,%05d$"
3249 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3252 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3257 emitcode ("", "%05d$:", tlbl->key + 100);
3262 /* if the sizes are greater than 1 then we cannot */
3263 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3264 AOP_SIZE (IC_LEFT (ic)) > 1)
3267 /* we can if the aops of the left & result match or
3268 if they are in registers and the registers are the
3271 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3272 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3273 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3278 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3279 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3280 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3285 _startLazyDPSEvaluation ();
3288 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3290 _endLazyDPSEvaluation ();
3299 /*-----------------------------------------------------------------*/
3300 /* outBitAcc - output a bit in acc */
3301 /*-----------------------------------------------------------------*/
3303 outBitAcc (operand * result)
3305 symbol *tlbl = newiTempLabel (NULL);
3306 /* if the result is a bit */
3307 if (AOP_TYPE (result) == AOP_CRY)
3309 aopPut (AOP (result), "a", 0);
3313 emitcode ("jz", "%05d$", tlbl->key + 100);
3314 emitcode ("mov", "a,%s", one);
3315 emitcode ("", "%05d$:", tlbl->key + 100);
3320 /*-----------------------------------------------------------------*/
3321 /* genPlusBits - generates code for addition of two bits */
3322 /*-----------------------------------------------------------------*/
3324 genPlusBits (iCode * ic)
3326 D (emitcode (";", "genPlusBits ");
3328 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3330 symbol *lbl = newiTempLabel (NULL);
3331 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3332 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3333 emitcode ("cpl", "c");
3334 emitcode ("", "%05d$:", (lbl->key + 100));
3335 outBitC (IC_RESULT (ic));
3339 emitcode ("clr", "a");
3340 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3341 emitcode ("rlc", "a");
3342 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3343 emitcode ("addc", "a,#0x00");
3344 outAcc (IC_RESULT (ic));
3349 adjustArithmeticResult (iCode * ic)
3351 if (opIsGptr (IC_RESULT (ic)) &&
3352 opIsGptr (IC_LEFT (ic)) &&
3353 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3355 aopPut (AOP (IC_RESULT (ic)),
3356 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3360 if (opIsGptr (IC_RESULT (ic)) &&
3361 opIsGptr (IC_RIGHT (ic)) &&
3362 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3364 aopPut (AOP (IC_RESULT (ic)),
3365 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3369 if (opIsGptr (IC_RESULT (ic)) &&
3370 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3371 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3372 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3373 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3376 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3377 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3381 #if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
3382 // Please don't bring it back without a really good reason.
3383 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3384 // (because all three operands are in far space).
3385 #define AOP_OP_3(ic) \
3386 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3387 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3388 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3389 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3390 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3391 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3393 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3395 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3399 // Macro to aopOp all three operands of an ic. If this cannot be done,
3400 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3401 // will be set TRUE. The caller must then handle the case specially, noting
3402 // that the IC_RESULT operand is not aopOp'd.
3403 #define AOP_OP_3_NOFATAL(ic, rc) \
3404 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3405 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3406 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3407 isOperandInFarSpace(IC_RESULT(ic))) \
3409 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3414 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3415 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3417 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3418 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3420 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3422 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3426 // aopOp the left & right operands of an ic.
3427 #define AOP_OP_2(ic) \
3428 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3429 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3431 // convienience macro.
3432 #define AOP_SET_LOCALS(ic) \
3433 left = IC_LEFT(ic); \
3434 right = IC_RIGHT(ic); \
3435 result = IC_RESULT(ic);
3438 // Given an integer value of pushedSize bytes on the stack,
3439 // adjust it to be resultSize bytes, either by discarding
3440 // the most significant bytes or by zero-padding.
3442 // On exit from this macro, pushedSize will have been adjusted to
3443 // equal resultSize, and ACC may be trashed.
3444 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3445 /* If the pushed data is bigger than the result, \
3446 * simply discard unused bytes. Icky, but works. \
3448 while (pushedSize > resultSize) \
3450 D (emitcode (";", "discarding unused result byte."););\
3451 emitcode ("pop", "acc"); \
3454 if (pushedSize < resultSize) \
3456 emitcode ("clr", "a"); \
3457 /* Conversly, we haven't pushed enough here. \
3458 * just zero-pad, and all is well. \
3460 while (pushedSize < resultSize) \
3462 emitcode("push", "acc"); \
3466 assert(pushedSize == resultSize);
3468 /*-----------------------------------------------------------------*/
3469 /* genPlus - generates code for addition */
3470 /*-----------------------------------------------------------------*/
3472 genPlus (iCode * ic)
3474 int size, offset = 0;
3475 bool pushResult = FALSE;
3478 D (emitcode (";", "genPlus "););
3480 /* special cases :- */
3482 AOP_OP_3_NOFATAL (ic, pushResult);
3485 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3490 /* if literal, literal on the right or
3491 if left requires ACC or right is already
3493 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3494 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3495 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3497 operand *t = IC_RIGHT (ic);
3498 IC_RIGHT (ic) = IC_LEFT (ic);
3500 emitcode (";", "Swapped plus args.");
3503 /* if both left & right are in bit
3505 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3506 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3512 /* if left in bit space & right literal */
3513 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3514 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3516 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3517 /* if result in bit space */
3518 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3520 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3521 emitcode ("cpl", "c");
3522 outBitC (IC_RESULT (ic));
3526 size = getDataSize (IC_RESULT (ic));
3527 _startLazyDPSEvaluation ();
3530 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3531 emitcode ("addc", "a,#00");
3532 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3534 _endLazyDPSEvaluation ();
3539 /* if I can do an increment instead
3540 of add then GOOD for ME */
3541 if (genPlusIncr (ic) == TRUE)
3543 emitcode (";", "did genPlusIncr");
3548 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3550 _startLazyDPSEvaluation ();
3553 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3555 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3557 emitcode ("add", "a,%s",
3558 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3560 emitcode ("addc", "a,%s",
3561 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3565 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3567 /* right is going to use ACC or we would have taken the
3570 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3572 D(emitcode(";", "+ AOP_ACC special case."););
3573 emitcode("xch", "a, %s", DP2_RESULT_REG);
3575 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3578 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3581 emitcode("add", "a, %s", DP2_RESULT_REG);
3585 emitcode ("add", "a,%s",
3586 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3591 emitcode ("addc", "a,%s",
3592 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3597 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3601 emitcode ("push", "acc");
3605 _endLazyDPSEvaluation ();
3609 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3611 size = getDataSize (IC_LEFT (ic));
3612 rSize = getDataSize (IC_RESULT (ic));
3614 ADJUST_PUSHED_RESULT(size, rSize);
3616 _startLazyDPSEvaluation ();
3619 emitcode ("pop", "acc");
3620 aopPut (AOP (IC_RESULT (ic)), "a", size);
3622 _endLazyDPSEvaluation ();
3625 adjustArithmeticResult (ic);
3628 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3629 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3630 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3633 /*-----------------------------------------------------------------*/
3634 /* genMinusDec :- does subtraction with deccrement if possible */
3635 /*-----------------------------------------------------------------*/
3637 genMinusDec (iCode * ic)
3639 unsigned int icount;
3640 unsigned int size = getDataSize (IC_RESULT (ic));
3642 /* will try to generate an increment */
3643 /* if the right side is not a literal
3645 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3648 /* if the literal value of the right hand side
3649 is greater than 4 then it is not worth it */
3650 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3653 /* if decrement 16 bits in register */
3654 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3655 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3656 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3664 /* If the next instruction is a goto and the goto target
3665 * is <= 5 instructions previous to this, we can generate
3666 * jumps straight to that target.
3668 if (ic->next && ic->next->op == GOTO
3669 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3672 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3673 tlbl = IC_LABEL (ic->next);
3678 tlbl = newiTempLabel (NULL);
3682 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3683 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3684 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3685 IS_AOP_PREG (IC_RESULT (ic)))
3686 emitcode ("cjne", "%s,#0xff,%05d$"
3687 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3691 emitcode ("mov", "a,#0xff");
3692 emitcode ("cjne", "a,%s,%05d$"
3693 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3696 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3699 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3700 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3701 IS_AOP_PREG (IC_RESULT (ic)))
3702 emitcode ("cjne", "%s,#0xff,%05d$"
3703 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3707 emitcode ("cjne", "a,%s,%05d$"
3708 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3711 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3715 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3716 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3717 IS_AOP_PREG (IC_RESULT (ic)))
3718 emitcode ("cjne", "%s,#0xff,%05d$"
3719 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3723 emitcode ("cjne", "a,%s,%05d$"
3724 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3727 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3731 emitcode ("", "%05d$:", tlbl->key + 100);
3736 /* if the sizes are greater than 1 then we cannot */
3737 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3738 AOP_SIZE (IC_LEFT (ic)) > 1)
3741 /* we can if the aops of the left & result match or
3742 if they are in registers and the registers are the
3745 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3746 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3747 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3750 _startLazyDPSEvaluation ();
3753 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3755 _endLazyDPSEvaluation ();
3763 /*-----------------------------------------------------------------*/
3764 /* addSign - complete with sign */
3765 /*-----------------------------------------------------------------*/
3767 addSign (operand * result, int offset, int sign)
3769 int size = (getDataSize (result) - offset);
3772 _startLazyDPSEvaluation();
3775 emitcode ("rlc", "a");
3776 emitcode ("subb", "a,acc");
3779 aopPut (AOP (result), "a", offset++);
3786 aopPut (AOP (result), zero, offset++);
3789 _endLazyDPSEvaluation();
3793 /*-----------------------------------------------------------------*/
3794 /* genMinusBits - generates code for subtraction of two bits */
3795 /*-----------------------------------------------------------------*/
3797 genMinusBits (iCode * ic)
3799 symbol *lbl = newiTempLabel (NULL);
3801 D (emitcode (";", "genMinusBits "););
3803 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3805 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3806 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3807 emitcode ("cpl", "c");
3808 emitcode ("", "%05d$:", (lbl->key + 100));
3809 outBitC (IC_RESULT (ic));
3813 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3814 emitcode ("subb", "a,acc");
3815 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3816 emitcode ("inc", "a");
3817 emitcode ("", "%05d$:", (lbl->key + 100));
3818 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3819 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3823 /*-----------------------------------------------------------------*/
3824 /* genMinus - generates code for subtraction */
3825 /*-----------------------------------------------------------------*/
3827 genMinus (iCode * ic)
3829 int size, offset = 0;
3831 unsigned long lit = 0L;
3832 bool pushResult = FALSE;
3834 D (emitcode (";", "genMinus "););
3836 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3837 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3838 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3839 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3845 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3847 /* special cases :- */
3848 /* if both left & right are in bit space */
3849 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3850 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3856 /* if I can do an decrement instead
3857 of subtract then GOOD for ME */
3858 if (genMinusDec (ic) == TRUE)
3863 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3865 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3871 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3876 /* if literal, add a,#-lit, else normal subb */
3877 _startLazyDPSEvaluation ();
3880 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3881 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3882 emitcode ("subb", "a,%s",
3883 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3886 /* first add without previous c */
3888 if (!size && lit==-1) {
3889 emitcode ("dec", "a");
3891 emitcode ("add", "a,#0x%02x",
3892 (unsigned int) (lit & 0x0FFL));
3895 emitcode ("addc", "a,#0x%02x",
3896 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3902 emitcode ("push", "acc");
3906 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3910 _endLazyDPSEvaluation ();
3914 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3916 size = getDataSize (IC_LEFT (ic));
3917 rSize = getDataSize (IC_RESULT (ic));
3919 ADJUST_PUSHED_RESULT(size, rSize);
3921 _startLazyDPSEvaluation ();
3924 emitcode ("pop", "acc");
3925 aopPut (AOP (IC_RESULT (ic)), "a", size);
3927 _endLazyDPSEvaluation ();
3930 adjustArithmeticResult (ic);
3933 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3934 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3935 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3939 /*-----------------------------------------------------------------*/
3940 /* genMultbits :- multiplication of bits */
3941 /*-----------------------------------------------------------------*/
3943 genMultbits (operand * left,
3948 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3949 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3950 aopOp(result, ic, TRUE, FALSE);
3955 /*-----------------------------------------------------------------*/
3956 /* genMultOneByte : 8*8=8/16 bit multiplication */
3957 /*-----------------------------------------------------------------*/
3959 genMultOneByte (operand * left,
3964 sym_link *opetype = operandType (result);
3968 /* (if two literals: the value is computed before) */
3969 /* if one literal, literal on the right */
3970 if (AOP_TYPE (left) == AOP_LIT)
3975 emitcode (";", "swapped left and right");
3978 if (SPEC_USIGN(opetype)
3979 // ignore the sign of left and right, what else can we do?
3980 || (SPEC_USIGN(operandType(left)) &&
3981 SPEC_USIGN(operandType(right)))) {
3982 // just an unsigned 8*8=8/16 multiply
3983 //emitcode (";","unsigned");
3984 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3985 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3986 emitcode ("mul", "ab");
3989 aopOp(result, ic, TRUE, FALSE);
3991 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
3993 // this should never happen
3994 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3995 AOP_SIZE(result), __FILE__, lineno);
3999 aopPut (AOP (result), "a", 0);
4001 if (AOP_SIZE(result)==2)
4003 aopPut (AOP (result), "b", 1);
4008 // we have to do a signed multiply
4010 emitcode (";", "signed");
4011 emitcode ("clr", "F0"); // reset sign flag
4012 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4014 lbl=newiTempLabel(NULL);
4015 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
4016 // left side is negative, 8-bit two's complement, this fails for -128
4017 emitcode ("setb", "F0"); // set sign flag
4018 emitcode ("cpl", "a");
4019 emitcode ("inc", "a");
4021 emitcode ("", "%05d$:", lbl->key+100);
4024 if (AOP_TYPE(right)==AOP_LIT) {
4025 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4026 /* AND literal negative */
4027 if ((int) val < 0) {
4028 emitcode ("cpl", "F0"); // complement sign flag
4029 emitcode ("mov", "b,#0x%02x", -val);
4031 emitcode ("mov", "b,#0x%02x", val);
4034 lbl=newiTempLabel(NULL);
4035 emitcode ("mov", "b,a");
4036 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4037 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
4038 // right side is negative, 8-bit two's complement
4039 emitcode ("cpl", "F0"); // complement sign flag
4040 emitcode ("cpl", "a");
4041 emitcode ("inc", "a");
4042 emitcode ("", "%05d$:", lbl->key+100);
4044 emitcode ("mul", "ab");
4047 aopOp(result, ic, TRUE, FALSE);
4049 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4051 // this should never happen
4052 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4053 AOP_SIZE(result), __FILE__, lineno);
4057 lbl=newiTempLabel(NULL);
4058 emitcode ("jnb", "F0,%05d$", lbl->key+100);
4059 // only ONE op was negative, we have to do a 8/16-bit two's complement
4060 emitcode ("cpl", "a"); // lsb
4061 if (AOP_SIZE(result)==1) {
4062 emitcode ("inc", "a");
4064 emitcode ("add", "a,#1");
4065 emitcode ("xch", "a,b");
4066 emitcode ("cpl", "a"); // msb
4067 emitcode ("addc", "a,#0");
4068 emitcode ("xch", "a,b");
4071 emitcode ("", "%05d$:", lbl->key+100);
4072 aopPut (AOP (result), "a", 0);
4074 if (AOP_SIZE(result)==2) {
4075 aopPut (AOP (result), "b", 1);
4079 /*-----------------------------------------------------------------*/
4080 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4081 /*-----------------------------------------------------------------*/
4082 static void genMultTwoByte (operand *left, operand *right,
4083 operand *result, iCode *ic)
4085 sym_link *retype = getSpec(operandType(right));
4086 sym_link *letype = getSpec(operandType(left));
4087 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4090 if (AOP_TYPE (left) == AOP_LIT) {
4095 /* load up MB with right */
4097 emitcode("clr","F0");
4098 if (AOP_TYPE(right) == AOP_LIT) {
4099 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4101 emitcode("setb","F0");
4104 emitcode ("mov","mb,#0x%02x",val & 0xff);
4105 emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4107 lbl = newiTempLabel(NULL);
4108 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4109 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4110 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4111 emitcode ("xch", "a,b");
4112 emitcode ("cpl","a");
4113 emitcode ("add", "a,#1");
4114 emitcode ("xch", "a,b");
4115 emitcode ("cpl", "a"); // msb
4116 emitcode ("addc", "a,#0");
4117 emitcode ("setb","F0");
4118 emitcode ("","%05d$:",lbl->key+100);
4119 emitcode ("mov","mb,b");
4120 emitcode ("mov","mb,a");
4123 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4124 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4126 /* load up MA with left */
4128 lbl = newiTempLabel(NULL);
4129 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4130 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4131 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4132 emitcode ("xch", "a,b");
4133 emitcode ("cpl","a");
4134 emitcode ("add", "a,#1");
4135 emitcode ("xch", "a,b");
4136 emitcode ("cpl", "a"); // msb
4137 emitcode ("addc","a,#0");
4138 emitcode ("jbc","F0,%05d$",lbl->key+100);
4139 emitcode ("setb","F0");
4140 emitcode ("","%05d$:",lbl->key+100);
4141 emitcode ("mov","ma,b");
4142 emitcode ("mov","ma,a");
4144 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4145 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4147 /* wait for multiplication to finish */
4148 lbl = newiTempLabel(NULL);
4149 emitcode("","%05d$:", lbl->key+100);
4150 emitcode("mov","a,mcnt1");
4151 emitcode("anl","a,#0x80");
4152 emitcode("jnz","%05d$",lbl->key+100);
4154 freeAsmop (left, NULL, ic, TRUE);
4155 freeAsmop (right, NULL, ic,TRUE);
4156 aopOp(result, ic, TRUE, FALSE);
4158 /* if unsigned then simple */
4160 emitcode ("mov","a,ma");
4161 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4162 emitcode ("mov","a,ma");
4163 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4164 aopPut(AOP(result),"ma",1);
4165 aopPut(AOP(result),"ma",0);
4167 emitcode("push","ma");
4168 emitcode("push","ma");
4169 emitcode("push","ma");
4171 /* negate result if needed */
4172 lbl = newiTempLabel(NULL);
4173 emitcode("jnb","F0,%05d$",lbl->key+100);
4174 emitcode("cpl","a");
4175 emitcode("add","a,#1");
4176 emitcode("","%05d$:", lbl->key+100);
4177 if (AOP_TYPE(result) == AOP_ACC)
4179 D(emitcode(";", "ACC special case."););
4180 /* We know result is the only live aop, and
4181 * it's obviously not a DPTR2, so AP is available.
4183 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4187 aopPut(AOP(result),"a",0);
4190 emitcode("pop","acc");
4191 lbl = newiTempLabel(NULL);
4192 emitcode("jnb","F0,%05d$",lbl->key+100);
4193 emitcode("cpl","a");
4194 emitcode("addc","a,#0");
4195 emitcode("","%05d$:", lbl->key+100);
4196 aopPut(AOP(result),"a",1);
4197 emitcode("pop","acc");
4198 if (AOP_SIZE(result) >= 3) {
4199 lbl = newiTempLabel(NULL);
4200 emitcode("jnb","F0,%05d$",lbl->key+100);
4201 emitcode("cpl","a");
4202 emitcode("addc","a,#0");
4203 emitcode("","%05d$:", lbl->key+100);
4204 aopPut(AOP(result),"a",2);
4206 emitcode("pop","acc");
4207 if (AOP_SIZE(result) >= 4) {
4208 lbl = newiTempLabel(NULL);
4209 emitcode("jnb","F0,%05d$",lbl->key+100);
4210 emitcode("cpl","a");
4211 emitcode("addc","a,#0");
4212 emitcode("","%05d$:", lbl->key+100);
4213 aopPut(AOP(result),"a",3);
4215 if (AOP_TYPE(result) == AOP_ACC)
4217 /* We stashed the result away above. */
4218 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4222 freeAsmop (result, NULL, ic, TRUE);
4226 /*-----------------------------------------------------------------*/
4227 /* genMult - generates code for multiplication */
4228 /*-----------------------------------------------------------------*/
4230 genMult (iCode * ic)
4232 operand *left = IC_LEFT (ic);
4233 operand *right = IC_RIGHT (ic);
4234 operand *result = IC_RESULT (ic);
4236 D (emitcode (";", "genMult "););
4238 /* assign the amsops */
4241 /* special cases first */
4243 if (AOP_TYPE (left) == AOP_CRY &&
4244 AOP_TYPE (right) == AOP_CRY)
4246 genMultbits (left, right, result, ic);
4250 /* if both are of size == 1 */
4251 if (AOP_SIZE (left) == 1 &&
4252 AOP_SIZE (right) == 1)
4254 genMultOneByte (left, right, result, ic);
4258 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4259 /* use the ds390 ARITHMETIC accel UNIT */
4260 genMultTwoByte (left, right, result, ic);
4263 /* should have been converted to function call */
4267 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4268 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4269 freeAsmop (result, NULL, ic, TRUE);
4272 /*-----------------------------------------------------------------*/
4273 /* genDivbits :- division of bits */
4274 /*-----------------------------------------------------------------*/
4276 genDivbits (operand * left,
4284 /* the result must be bit */
4285 LOAD_AB_FOR_DIV (left, right, l);
4286 emitcode ("div", "ab");
4287 emitcode ("rrc", "a");
4288 aopOp(result, ic, TRUE, FALSE);
4290 aopPut (AOP (result), "c", 0);
4293 /*-----------------------------------------------------------------*/
4294 /* genDivOneByte : 8 bit division */
4295 /*-----------------------------------------------------------------*/
4297 genDivOneByte (operand * left,
4302 sym_link *opetype = operandType (result);
4308 /* signed or unsigned */
4309 if (SPEC_USIGN (opetype))
4311 /* unsigned is easy */
4312 LOAD_AB_FOR_DIV (left, right, l);
4313 emitcode ("div", "ab");
4316 aopOp(result, ic, TRUE, FALSE);
4317 aopPut (AOP (result), "a", 0);
4320 size = AOP_SIZE (result) - 1;
4324 aopPut (AOP (result), zero, offset++);
4329 /* signed is a little bit more difficult */
4331 /* save the signs of the operands */
4332 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4334 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4335 emitcode ("push", "acc"); /* save it on the stack */
4337 /* now sign adjust for both left & right */
4338 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4340 lbl = newiTempLabel (NULL);
4341 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4342 emitcode ("cpl", "a");
4343 emitcode ("inc", "a");
4344 emitcode ("", "%05d$:", (lbl->key + 100));
4345 emitcode ("mov", "b,a");
4347 /* sign adjust left side */
4348 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4351 lbl = newiTempLabel (NULL);
4352 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4353 emitcode ("cpl", "a");
4354 emitcode ("inc", "a");
4355 emitcode ("", "%05d$:", (lbl->key + 100));
4357 /* now the division */
4358 emitcode ("nop", "; workaround for DS80C390 div bug.");
4359 emitcode ("div", "ab");
4360 /* we are interested in the lower order
4362 emitcode ("mov", "b,a");
4363 lbl = newiTempLabel (NULL);
4364 emitcode ("pop", "acc");
4365 /* if there was an over flow we don't
4366 adjust the sign of the result */
4367 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4368 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4370 emitcode ("clr", "a");
4371 emitcode ("subb", "a,b");
4372 emitcode ("mov", "b,a");
4373 emitcode ("", "%05d$:", (lbl->key + 100));
4375 /* now we are done */
4377 aopOp(result, ic, TRUE, FALSE);
4379 aopPut (AOP (result), "b", 0);
4381 size = AOP_SIZE (result) - 1;
4385 emitcode ("mov", "c,b.7");
4386 emitcode ("subb", "a,acc");
4390 aopPut (AOP (result), "a", offset++);
4396 /*-----------------------------------------------------------------*/
4397 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4398 /*-----------------------------------------------------------------*/
4399 static void genDivTwoByte (operand *left, operand *right,
4400 operand *result, iCode *ic)
4402 sym_link *retype = getSpec(operandType(right));
4403 sym_link *letype = getSpec(operandType(left));
4404 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4407 /* load up MA with left */
4409 emitcode("clr","F0");
4410 lbl = newiTempLabel(NULL);
4411 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4412 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4413 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4414 emitcode ("xch", "a,b");
4415 emitcode ("cpl","a");
4416 emitcode ("add", "a,#1");
4417 emitcode ("xch", "a,b");
4418 emitcode ("cpl", "a"); // msb
4419 emitcode ("addc","a,#0");
4420 emitcode ("setb","F0");
4421 emitcode ("","%05d$:",lbl->key+100);
4422 emitcode ("mov","ma,b");
4423 emitcode ("mov","ma,a");
4425 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4426 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4429 /* load up MB with right */
4431 if (AOP_TYPE(right) == AOP_LIT) {
4432 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4434 lbl = newiTempLabel(NULL);
4435 emitcode ("jbc","F0,%05d$",lbl->key+100);
4436 emitcode("setb","F0");
4437 emitcode ("","%05d$:",lbl->key+100);
4440 emitcode ("mov","mb,#0x%02x",val & 0xff);
4441 emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4443 lbl = newiTempLabel(NULL);
4444 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4445 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4446 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4447 emitcode ("xch", "a,b");
4448 emitcode ("cpl","a");
4449 emitcode ("add", "a,#1");
4450 emitcode ("xch", "a,b");
4451 emitcode ("cpl", "a"); // msb
4452 emitcode ("addc", "a,#0");
4453 emitcode ("jbc","F0,%05d$",lbl->key+100);
4454 emitcode ("setb","F0");
4455 emitcode ("","%05d$:",lbl->key+100);
4456 emitcode ("mov","mb,b");
4457 emitcode ("mov","mb,a");
4460 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4461 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4464 /* wait for multiplication to finish */
4465 lbl = newiTempLabel(NULL);
4466 emitcode("","%05d$:", lbl->key+100);
4467 emitcode("mov","a,mcnt1");
4468 emitcode("anl","a,#0x80");
4469 emitcode("jnz","%05d$",lbl->key+100);
4471 freeAsmop (left, NULL, ic, TRUE);
4472 freeAsmop (right, NULL, ic,TRUE);
4473 aopOp(result, ic, TRUE, FALSE);
4475 /* if unsigned then simple */
4477 aopPut(AOP(result),"ma",1);
4478 aopPut(AOP(result),"ma",0);
4480 emitcode("push","ma");
4482 /* negate result if needed */
4483 lbl = newiTempLabel(NULL);
4484 emitcode("jnb","F0,%05d$",lbl->key+100);
4485 emitcode("cpl","a");
4486 emitcode("add","a,#1");
4487 emitcode("","%05d$:", lbl->key+100);
4488 aopPut(AOP(result),"a",0);
4489 emitcode("pop","acc");
4490 lbl = newiTempLabel(NULL);
4491 emitcode("jnb","F0,%05d$",lbl->key+100);
4492 emitcode("cpl","a");
4493 emitcode("addc","a,#0");
4494 emitcode("","%05d$:", lbl->key+100);
4495 aopPut(AOP(result),"a",1);
4497 freeAsmop (result, NULL, ic, TRUE);
4501 /*-----------------------------------------------------------------*/
4502 /* genDiv - generates code for division */
4503 /*-----------------------------------------------------------------*/
4507 operand *left = IC_LEFT (ic);
4508 operand *right = IC_RIGHT (ic);
4509 operand *result = IC_RESULT (ic);
4511 D (emitcode (";", "genDiv "););
4513 /* assign the amsops */
4516 /* special cases first */
4518 if (AOP_TYPE (left) == AOP_CRY &&
4519 AOP_TYPE (right) == AOP_CRY)
4521 genDivbits (left, right, result, ic);
4525 /* if both are of size == 1 */
4526 if (AOP_SIZE (left) == 1 &&
4527 AOP_SIZE (right) == 1)
4529 genDivOneByte (left, right, result, ic);
4533 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4534 /* use the ds390 ARITHMETIC accel UNIT */
4535 genDivTwoByte (left, right, result, ic);
4538 /* should have been converted to function call */
4541 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4542 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4543 freeAsmop (result, NULL, ic, TRUE);
4546 /*-----------------------------------------------------------------*/
4547 /* genModbits :- modulus of bits */
4548 /*-----------------------------------------------------------------*/
4550 genModbits (operand * left,
4558 /* the result must be bit */
4559 LOAD_AB_FOR_DIV (left, right, l);
4560 emitcode ("div", "ab");
4561 emitcode ("mov", "a,b");
4562 emitcode ("rrc", "a");
4563 aopOp(result, ic, TRUE, FALSE);
4564 aopPut (AOP (result), "c", 0);
4567 /*-----------------------------------------------------------------*/
4568 /* genModOneByte : 8 bit modulus */
4569 /*-----------------------------------------------------------------*/
4571 genModOneByte (operand * left,
4576 sym_link *opetype = operandType (result);
4580 /* signed or unsigned */
4581 if (SPEC_USIGN (opetype))
4583 /* unsigned is easy */
4584 LOAD_AB_FOR_DIV (left, right, l);
4585 emitcode ("div", "ab");
4586 aopOp(result, ic, TRUE, FALSE);
4587 aopPut (AOP (result), "b", 0);
4591 /* signed is a little bit more difficult */
4593 /* save the signs of the operands */
4594 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4597 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4598 emitcode ("push", "acc"); /* save it on the stack */
4600 /* now sign adjust for both left & right */
4601 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4604 lbl = newiTempLabel (NULL);
4605 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4606 emitcode ("cpl", "a");
4607 emitcode ("inc", "a");
4608 emitcode ("", "%05d$:", (lbl->key + 100));
4609 emitcode ("mov", "b,a");
4611 /* sign adjust left side */
4612 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4615 lbl = newiTempLabel (NULL);
4616 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4617 emitcode ("cpl", "a");
4618 emitcode ("inc", "a");
4619 emitcode ("", "%05d$:", (lbl->key + 100));
4621 /* now the multiplication */
4622 emitcode ("nop", "; workaround for DS80C390 div bug.");
4623 emitcode ("div", "ab");
4624 /* we are interested in the lower order
4626 lbl = newiTempLabel (NULL);
4627 emitcode ("pop", "acc");
4628 /* if there was an over flow we don't
4629 adjust the sign of the result */
4630 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4631 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4633 emitcode ("clr", "a");
4634 emitcode ("subb", "a,b");
4635 emitcode ("mov", "b,a");
4636 emitcode ("", "%05d$:", (lbl->key + 100));
4638 /* now we are done */
4639 aopOp(result, ic, TRUE, FALSE);
4640 aopPut (AOP (result), "b", 0);
4644 /*-----------------------------------------------------------------*/
4645 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
4646 /*-----------------------------------------------------------------*/
4647 static void genModTwoByte (operand *left, operand *right,
4648 operand *result, iCode *ic)
4650 sym_link *retype = getSpec(operandType(right));
4651 sym_link *letype = getSpec(operandType(left));
4652 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4655 /* load up MA with left */
4657 lbl = newiTempLabel(NULL);
4658 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4659 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4660 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4661 emitcode ("xch", "a,b");
4662 emitcode ("cpl","a");
4663 emitcode ("add", "a,#1");
4664 emitcode ("xch", "a,b");
4665 emitcode ("cpl", "a"); // msb
4666 emitcode ("addc","a,#0");
4667 emitcode ("","%05d$:",lbl->key+100);
4668 emitcode ("mov","ma,b");
4669 emitcode ("mov","ma,a");
4671 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4672 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4675 /* load up MB with right */
4677 if (AOP_TYPE(right) == AOP_LIT) {
4678 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4682 emitcode ("mov","mb,#0x%02x",val & 0xff);
4683 emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4685 lbl = newiTempLabel(NULL);
4686 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4687 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4688 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4689 emitcode ("xch", "a,b");
4690 emitcode ("cpl","a");
4691 emitcode ("add", "a,#1");
4692 emitcode ("xch", "a,b");
4693 emitcode ("cpl", "a"); // msb
4694 emitcode ("addc", "a,#0");
4695 emitcode ("","%05d$:",lbl->key+100);
4696 emitcode ("mov","mb,b");
4697 emitcode ("mov","mb,a");
4700 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4701 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4704 /* wait for multiplication to finish */
4705 lbl = newiTempLabel(NULL);
4706 emitcode("","%05d$:", lbl->key+100);
4707 emitcode("mov","a,mcnt1");
4708 emitcode("anl","a,#0x80");
4709 emitcode("jnz","%05d$",lbl->key+100);
4711 freeAsmop (left, NULL, ic, TRUE);
4712 freeAsmop (right, NULL, ic,TRUE);
4713 aopOp(result, ic, TRUE, FALSE);
4715 aopPut(AOP(result),"mb",1);
4716 aopPut(AOP(result),"mb",0);
4717 freeAsmop (result, NULL, ic, TRUE);
4721 /*-----------------------------------------------------------------*/
4722 /* genMod - generates code for division */
4723 /*-----------------------------------------------------------------*/
4727 operand *left = IC_LEFT (ic);
4728 operand *right = IC_RIGHT (ic);
4729 operand *result = IC_RESULT (ic);
4731 D (emitcode (";", "genMod "); );
4733 /* assign the amsops */
4736 /* special cases first */
4738 if (AOP_TYPE (left) == AOP_CRY &&
4739 AOP_TYPE (right) == AOP_CRY)
4741 genModbits (left, right, result, ic);
4745 /* if both are of size == 1 */
4746 if (AOP_SIZE (left) == 1 &&
4747 AOP_SIZE (right) == 1)
4749 genModOneByte (left, right, result, ic);
4753 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4754 /* use the ds390 ARITHMETIC accel UNIT */
4755 genModTwoByte (left, right, result, ic);
4759 /* should have been converted to function call */
4763 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4764 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4765 freeAsmop (result, NULL, ic, TRUE);
4768 /*-----------------------------------------------------------------*/
4769 /* genIfxJump :- will create a jump depending on the ifx */
4770 /*-----------------------------------------------------------------*/
4772 genIfxJump (iCode * ic, char *jval)
4775 symbol *tlbl = newiTempLabel (NULL);
4778 D (emitcode (";", "genIfxJump ");
4781 /* if true label then we jump if condition
4785 jlbl = IC_TRUE (ic);
4786 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4787 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4791 /* false label is present */
4792 jlbl = IC_FALSE (ic);
4793 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4794 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4796 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4797 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4799 emitcode (inst, "%05d$", tlbl->key + 100);
4800 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4801 emitcode ("", "%05d$:", tlbl->key + 100);
4803 /* mark the icode as generated */
4807 /*-----------------------------------------------------------------*/
4808 /* genCmp :- greater or less than comparison */
4809 /*-----------------------------------------------------------------*/
4811 genCmp (operand * left, operand * right,
4812 iCode * ic, iCode * ifx, int sign)
4814 int size, offset = 0;
4815 unsigned long lit = 0L;
4818 D (emitcode (";", "genCmp");
4821 result = IC_RESULT (ic);
4823 /* if left & right are bit variables */
4824 if (AOP_TYPE (left) == AOP_CRY &&
4825 AOP_TYPE (right) == AOP_CRY)
4827 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4828 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4832 /* subtract right from left if at the
4833 end the carry flag is set then we know that
4834 left is greater than right */
4835 size = max (AOP_SIZE (left), AOP_SIZE (right));
4837 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4838 if ((size == 1) && !sign &&
4839 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4841 symbol *lbl = newiTempLabel (NULL);
4842 emitcode ("cjne", "%s,%s,%05d$",
4843 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4844 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4846 emitcode ("", "%05d$:", lbl->key + 100);
4850 if (AOP_TYPE (right) == AOP_LIT)
4852 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4853 /* optimize if(x < 0) or if(x >= 0) */
4862 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4864 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4865 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4867 aopOp (result, ic, FALSE, FALSE);
4869 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4871 freeAsmop (result, NULL, ic, TRUE);
4872 genIfxJump (ifx, "acc.7");
4877 emitcode ("rlc", "a");
4879 goto release_freedLR;
4887 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4888 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4889 emitcode (";", "genCmp #2");
4890 if (sign && (size == 0))
4892 emitcode (";", "genCmp #3");
4893 emitcode ("xrl", "a,#0x80");
4894 if (AOP_TYPE (right) == AOP_LIT)
4896 unsigned long lit = (unsigned long)
4897 floatFromVal (AOP (right)->aopu.aop_lit);
4898 emitcode (";", "genCmp #3.1");
4899 emitcode ("subb", "a,#0x%02x",
4900 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4904 emitcode (";", "genCmp #3.2");
4905 if (AOP_NEEDSACC (right))
4907 emitcode ("push", "acc");
4909 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4910 FALSE, FALSE, FALSE));
4911 emitcode ("xrl", "b,#0x80");
4912 if (AOP_NEEDSACC (right))
4914 emitcode ("pop", "acc");
4916 emitcode ("subb", "a,b");
4923 emitcode (";", "genCmp #4");
4924 if (AOP_NEEDSACC (right))
4927 emitcode (";", "genCmp #4.1");
4928 emitcode ("xch", "a, b");
4929 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4930 emitcode ("xch", "a, b");
4935 emitcode (";", "genCmp #4.2");
4936 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4939 emitcode ("subb", "a,%s", s);
4946 /* Don't need the left & right operands any more; do need the result. */
4947 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4948 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4950 aopOp (result, ic, FALSE, FALSE);
4954 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4960 /* if the result is used in the next
4961 ifx conditional branch then generate
4962 code a little differently */
4965 genIfxJump (ifx, "c");
4971 /* leave the result in acc */
4973 freeAsmop (result, NULL, ic, TRUE);
4976 /*-----------------------------------------------------------------*/
4977 /* genCmpGt :- greater than comparison */
4978 /*-----------------------------------------------------------------*/
4980 genCmpGt (iCode * ic, iCode * ifx)
4982 operand *left, *right;
4983 sym_link *letype, *retype;
4986 D (emitcode (";", "genCmpGt ");
4989 left = IC_LEFT (ic);
4990 right = IC_RIGHT (ic);
4992 letype = getSpec (operandType (left));
4993 retype = getSpec (operandType (right));
4994 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4996 /* assign the left & right amsops */
4999 genCmp (right, left, ic, ifx, sign);
5002 /*-----------------------------------------------------------------*/
5003 /* genCmpLt - less than comparisons */
5004 /*-----------------------------------------------------------------*/
5006 genCmpLt (iCode * ic, iCode * ifx)
5008 operand *left, *right;
5009 sym_link *letype, *retype;
5012 D (emitcode (";", "genCmpLt "););
5014 left = IC_LEFT (ic);
5015 right = IC_RIGHT (ic);
5017 letype = getSpec (operandType (left));
5018 retype = getSpec (operandType (right));
5019 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5021 /* assign the left & right amsops */
5024 genCmp (left, right, ic, ifx, sign);
5027 /*-----------------------------------------------------------------*/
5028 /* gencjneshort - compare and jump if not equal */
5029 /*-----------------------------------------------------------------*/
5031 gencjneshort (operand * left, operand * right, symbol * lbl)
5033 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5035 unsigned long lit = 0L;
5037 D (emitcode (";", "gencjneshort");
5040 /* if the left side is a literal or
5041 if the right is in a pointer register and left
5043 if ((AOP_TYPE (left) == AOP_LIT) ||
5044 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5051 if (AOP_TYPE (right) == AOP_LIT)
5052 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5054 if (opIsGptr (left) || opIsGptr (right))
5056 /* We are comparing a generic pointer to something.
5057 * Exclude the generic type byte from the comparison.
5060 D (emitcode (";", "cjneshort: generic ptr special case.");
5065 /* if the right side is a literal then anything goes */
5066 if (AOP_TYPE (right) == AOP_LIT &&
5067 AOP_TYPE (left) != AOP_DIR)
5071 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5073 emitcode ("cjne", "a,%s,%05d$",
5074 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5080 /* if the right side is in a register or in direct space or
5081 if the left is a pointer register & right is not */
5082 else if (AOP_TYPE (right) == AOP_REG ||
5083 AOP_TYPE (right) == AOP_DIR ||
5084 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5085 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5089 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5090 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5091 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5092 emitcode ("jnz", "%05d$", lbl->key + 100);
5094 emitcode ("cjne", "a,%s,%05d$",
5095 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5102 /* right is a pointer reg need both a & b */
5105 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5106 if (strcmp (l, "b"))
5107 emitcode ("mov", "b,%s", l);
5108 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5109 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5115 /*-----------------------------------------------------------------*/
5116 /* gencjne - compare and jump if not equal */
5117 /*-----------------------------------------------------------------*/
5119 gencjne (operand * left, operand * right, symbol * lbl)
5121 symbol *tlbl = newiTempLabel (NULL);
5123 D (emitcode (";", "gencjne");
5126 gencjneshort (left, right, lbl);
5128 emitcode ("mov", "a,%s", one);
5129 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5130 emitcode ("", "%05d$:", lbl->key + 100);
5131 emitcode ("clr", "a");
5132 emitcode ("", "%05d$:", tlbl->key + 100);
5135 /*-----------------------------------------------------------------*/
5136 /* genCmpEq - generates code for equal to */
5137 /*-----------------------------------------------------------------*/
5139 genCmpEq (iCode * ic, iCode * ifx)
5141 operand *left, *right, *result;
5143 D (emitcode (";", "genCmpEq ");
5147 AOP_SET_LOCALS (ic);
5149 /* if literal, literal on the right or
5150 if the right is in a pointer register and left
5152 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5153 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5155 operand *t = IC_RIGHT (ic);
5156 IC_RIGHT (ic) = IC_LEFT (ic);
5160 if (ifx && /* !AOP_SIZE(result) */
5161 OP_SYMBOL (result) &&
5162 OP_SYMBOL (result)->regType == REG_CND)
5165 /* if they are both bit variables */
5166 if (AOP_TYPE (left) == AOP_CRY &&
5167 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5169 if (AOP_TYPE (right) == AOP_LIT)
5171 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5174 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5175 emitcode ("cpl", "c");
5179 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5183 emitcode ("clr", "c");
5185 /* AOP_TYPE(right) == AOP_CRY */
5189 symbol *lbl = newiTempLabel (NULL);
5190 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5191 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5192 emitcode ("cpl", "c");
5193 emitcode ("", "%05d$:", (lbl->key + 100));
5195 /* if true label then we jump if condition
5197 tlbl = newiTempLabel (NULL);
5200 emitcode ("jnc", "%05d$", tlbl->key + 100);
5201 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5205 emitcode ("jc", "%05d$", tlbl->key + 100);
5206 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5208 emitcode ("", "%05d$:", tlbl->key + 100);
5212 tlbl = newiTempLabel (NULL);
5213 gencjneshort (left, right, tlbl);
5216 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5217 emitcode ("", "%05d$:", tlbl->key + 100);
5221 symbol *lbl = newiTempLabel (NULL);
5222 emitcode ("sjmp", "%05d$", lbl->key + 100);
5223 emitcode ("", "%05d$:", tlbl->key + 100);
5224 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5225 emitcode ("", "%05d$:", lbl->key + 100);
5228 /* mark the icode as generated */
5231 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5232 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5236 /* if they are both bit variables */
5237 if (AOP_TYPE (left) == AOP_CRY &&
5238 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5240 if (AOP_TYPE (right) == AOP_LIT)
5242 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5245 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5246 emitcode ("cpl", "c");
5250 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5254 emitcode ("clr", "c");
5256 /* AOP_TYPE(right) == AOP_CRY */
5260 symbol *lbl = newiTempLabel (NULL);
5261 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5262 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5263 emitcode ("cpl", "c");
5264 emitcode ("", "%05d$:", (lbl->key + 100));
5267 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5268 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5270 aopOp (result, ic, TRUE, FALSE);
5273 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5280 genIfxJump (ifx, "c");
5283 /* if the result is used in an arithmetic operation
5284 then put the result in place */
5289 gencjne (left, right, newiTempLabel (NULL));
5291 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5292 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5294 aopOp (result, ic, TRUE, FALSE);
5296 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5298 aopPut (AOP (result), "a", 0);
5303 genIfxJump (ifx, "a");
5306 /* if the result is used in an arithmetic operation
5307 then put the result in place */
5308 if (AOP_TYPE (result) != AOP_CRY)
5310 /* leave the result in acc */
5314 freeAsmop (result, NULL, ic, TRUE);
5317 /*-----------------------------------------------------------------*/
5318 /* ifxForOp - returns the icode containing the ifx for operand */
5319 /*-----------------------------------------------------------------*/
5321 ifxForOp (operand * op, iCode * ic)
5323 /* if true symbol then needs to be assigned */
5324 if (IS_TRUE_SYMOP (op))
5327 /* if this has register type condition and
5328 the next instruction is ifx with the same operand
5329 and live to of the operand is upto the ifx only then */
5331 ic->next->op == IFX &&
5332 IC_COND (ic->next)->key == op->key &&
5333 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5338 /*-----------------------------------------------------------------*/
5339 /* genAndOp - for && operation */
5340 /*-----------------------------------------------------------------*/
5342 genAndOp (iCode * ic)
5344 operand *left, *right, *result;
5347 D (emitcode (";", "genAndOp "););
5349 /* note here that && operations that are in an
5350 if statement are taken away by backPatchLabels
5351 only those used in arthmetic operations remain */
5353 AOP_SET_LOCALS (ic);
5355 /* if both are bit variables */
5356 if (AOP_TYPE (left) == AOP_CRY &&
5357 AOP_TYPE (right) == AOP_CRY)
5359 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5360 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5361 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5362 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5364 aopOp (result,ic,FALSE, FALSE);
5369 tlbl = newiTempLabel (NULL);
5371 emitcode ("jz", "%05d$", tlbl->key + 100);
5373 emitcode ("", "%05d$:", tlbl->key + 100);
5374 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5375 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5377 aopOp (result,ic,FALSE, FALSE);
5380 freeAsmop (result, NULL, ic, TRUE);
5384 /*-----------------------------------------------------------------*/
5385 /* genOrOp - for || operation */
5386 /*-----------------------------------------------------------------*/
5388 genOrOp (iCode * ic)
5390 operand *left, *right, *result;
5393 D (emitcode (";", "genOrOp "););
5395 /* note here that || operations that are in an
5396 if statement are taken away by backPatchLabels
5397 only those used in arthmetic operations remain */
5399 AOP_SET_LOCALS (ic);
5401 /* if both are bit variables */
5402 if (AOP_TYPE (left) == AOP_CRY &&
5403 AOP_TYPE (right) == AOP_CRY)
5405 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5406 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5407 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5408 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5410 aopOp (result,ic,FALSE, FALSE);
5416 tlbl = newiTempLabel (NULL);
5418 emitcode ("jnz", "%05d$", tlbl->key + 100);
5420 emitcode ("", "%05d$:", tlbl->key + 100);
5421 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5422 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5424 aopOp (result,ic,FALSE, FALSE);
5429 freeAsmop (result, NULL, ic, TRUE);
5432 /*-----------------------------------------------------------------*/
5433 /* isLiteralBit - test if lit == 2^n */
5434 /*-----------------------------------------------------------------*/
5436 isLiteralBit (unsigned long lit)
5438 unsigned long pw[32] =
5439 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5440 0x100L, 0x200L, 0x400L, 0x800L,
5441 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5442 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5443 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5444 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5445 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5448 for (idx = 0; idx < 32; idx++)
5454 /*-----------------------------------------------------------------*/
5455 /* continueIfTrue - */
5456 /*-----------------------------------------------------------------*/
5458 continueIfTrue (iCode * ic)
5461 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5465 /*-----------------------------------------------------------------*/
5467 /*-----------------------------------------------------------------*/
5469 jumpIfTrue (iCode * ic)
5472 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5476 /*-----------------------------------------------------------------*/
5477 /* jmpTrueOrFalse - */
5478 /*-----------------------------------------------------------------*/
5480 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5482 // ugly but optimized by peephole
5485 symbol *nlbl = newiTempLabel (NULL);
5486 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5487 emitcode ("", "%05d$:", tlbl->key + 100);
5488 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5489 emitcode ("", "%05d$:", nlbl->key + 100);
5493 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5494 emitcode ("", "%05d$:", tlbl->key + 100);
5499 // Generate code to perform a bit-wise logic operation
5500 // on two operands in far space (assumed to already have been
5501 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5502 // in far space. This requires pushing the result on the stack
5503 // then popping it into the result.
5505 genFarFarLogicOp(iCode *ic, char *logicOp)
5507 int size, resultSize, compSize;
5511 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5512 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5513 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5515 _startLazyDPSEvaluation();
5516 for (size = compSize; (size--); offset++)
5518 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5519 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5520 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5522 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5523 emitcode ("push", "acc");
5525 _endLazyDPSEvaluation();
5527 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5528 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5529 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5531 resultSize = AOP_SIZE(IC_RESULT(ic));
5533 ADJUST_PUSHED_RESULT(compSize, resultSize);
5535 _startLazyDPSEvaluation();
5538 emitcode ("pop", "acc");
5539 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5541 _endLazyDPSEvaluation();
5542 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5546 /*-----------------------------------------------------------------*/
5547 /* genAnd - code for and */
5548 /*-----------------------------------------------------------------*/
5550 genAnd (iCode * ic, iCode * ifx)
5552 operand *left, *right, *result;
5553 int size, offset = 0;
5554 unsigned long lit = 0L;
5559 D (emitcode (";", "genAnd "););
5561 AOP_OP_3_NOFATAL (ic, pushResult);
5562 AOP_SET_LOCALS (ic);
5566 genFarFarLogicOp(ic, "anl");
5571 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5573 AOP_TYPE (left), AOP_TYPE (right));
5574 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5576 AOP_SIZE (left), AOP_SIZE (right));
5579 /* if left is a literal & right is not then exchange them */
5580 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5581 #ifdef LOGIC_OPS_BROKEN
5582 || AOP_NEEDSACC (left)
5586 operand *tmp = right;
5591 /* if result = right then exchange them */
5592 if (sameRegs (AOP (result), AOP (right)))
5594 operand *tmp = right;
5599 /* if right is bit then exchange them */
5600 if (AOP_TYPE (right) == AOP_CRY &&
5601 AOP_TYPE (left) != AOP_CRY)
5603 operand *tmp = right;
5607 if (AOP_TYPE (right) == AOP_LIT)
5608 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5610 size = AOP_SIZE (result);
5613 // result = bit & yy;
5614 if (AOP_TYPE (left) == AOP_CRY)
5616 // c = bit & literal;
5617 if (AOP_TYPE (right) == AOP_LIT)
5621 if (size && sameRegs (AOP (result), AOP (left)))
5624 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5629 if (size && (AOP_TYPE (result) == AOP_CRY))
5631 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5634 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5639 emitcode ("clr", "c");
5644 if (AOP_TYPE (right) == AOP_CRY)
5647 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5648 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5653 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5655 emitcode ("rrc", "a");
5656 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5664 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5665 genIfxJump (ifx, "c");
5669 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5670 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5671 if ((AOP_TYPE (right) == AOP_LIT) &&
5672 (AOP_TYPE (result) == AOP_CRY) &&
5673 (AOP_TYPE (left) != AOP_CRY))
5675 int posbit = isLiteralBit (lit);
5680 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5683 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5689 sprintf (buffer, "acc.%d", posbit & 0x07);
5690 genIfxJump (ifx, buffer);
5697 symbol *tlbl = newiTempLabel (NULL);
5698 int sizel = AOP_SIZE (left);
5700 emitcode ("setb", "c");
5703 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5705 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5707 if ((posbit = isLiteralBit (bytelit)) != 0)
5708 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5711 if (bytelit != 0x0FFL)
5712 emitcode ("anl", "a,%s",
5713 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5714 emitcode ("jnz", "%05d$", tlbl->key + 100);
5719 // bit = left & literal
5722 emitcode ("clr", "c");
5723 emitcode ("", "%05d$:", tlbl->key + 100);
5725 // if(left & literal)
5729 jmpTrueOrFalse (ifx, tlbl);
5737 /* if left is same as result */
5738 if (sameRegs (AOP (result), AOP (left)))
5740 for (; size--; offset++)
5742 if (AOP_TYPE (right) == AOP_LIT)
5744 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5746 else if (bytelit == 0)
5747 aopPut (AOP (result), zero, offset);
5748 else if (IS_AOP_PREG (result))
5750 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5751 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5752 aopPut (AOP (result), "a", offset);
5755 emitcode ("anl", "%s,%s",
5756 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5757 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5761 if (AOP_TYPE (left) == AOP_ACC)
5762 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5765 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5766 if (IS_AOP_PREG (result))
5768 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5769 aopPut (AOP (result), "a", offset);
5773 emitcode ("anl", "%s,a",
5774 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5781 // left & result in different registers
5782 if (AOP_TYPE (result) == AOP_CRY)
5785 // if(size), result in bit
5786 // if(!size && ifx), conditional oper: if(left & right)
5787 symbol *tlbl = newiTempLabel (NULL);
5788 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5790 emitcode ("setb", "c");
5793 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5794 emitcode ("anl", "a,%s",
5795 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5797 if (AOP_TYPE(left)==AOP_ACC) {
5798 emitcode("mov", "b,a");
5799 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5800 emitcode("anl", "a,b");
5802 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5803 emitcode ("anl", "a,%s",
5804 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5807 emitcode ("jnz", "%05d$", tlbl->key + 100);
5813 emitcode ("", "%05d$:", tlbl->key + 100);
5817 jmpTrueOrFalse (ifx, tlbl);
5821 for (; (size--); offset++)
5824 // result = left & right
5825 if (AOP_TYPE (right) == AOP_LIT)
5827 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5829 aopPut (AOP (result),
5830 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5834 else if (bytelit == 0)
5836 aopPut (AOP (result), zero, offset);
5839 D (emitcode (";", "better literal AND."););
5840 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5841 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5842 FALSE, FALSE, FALSE));
5847 // faster than result <- left, anl result,right
5848 // and better if result is SFR
5849 if (AOP_TYPE (left) == AOP_ACC)
5851 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5852 FALSE, FALSE, FALSE));
5856 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
5857 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
5859 emitcode("mov", "b,a");
5863 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5864 emitcode ("anl", "a,%s", rOp);
5867 aopPut (AOP (result), "a", offset);
5873 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5874 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5875 freeAsmop (result, NULL, ic, TRUE);
5879 /*-----------------------------------------------------------------*/
5880 /* genOr - code for or */
5881 /*-----------------------------------------------------------------*/
5883 genOr (iCode * ic, iCode * ifx)
5885 operand *left, *right, *result;
5886 int size, offset = 0;
5887 unsigned long lit = 0L;
5890 D (emitcode (";", "genOr "););
5892 AOP_OP_3_NOFATAL (ic, pushResult);
5893 AOP_SET_LOCALS (ic);
5897 genFarFarLogicOp(ic, "orl");
5903 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5905 AOP_TYPE (left), AOP_TYPE (right));
5906 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5908 AOP_SIZE (left), AOP_SIZE (right));
5911 /* if left is a literal & right is not then exchange them */
5912 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5913 #ifdef LOGIC_OPS_BROKEN
5914 || AOP_NEEDSACC (left) // I think this is a net loss now.
5918 operand *tmp = right;
5923 /* if result = right then exchange them */
5924 if (sameRegs (AOP (result), AOP (right)))
5926 operand *tmp = right;
5931 /* if right is bit then exchange them */
5932 if (AOP_TYPE (right) == AOP_CRY &&
5933 AOP_TYPE (left) != AOP_CRY)
5935 operand *tmp = right;
5939 if (AOP_TYPE (right) == AOP_LIT)
5940 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5942 size = AOP_SIZE (result);
5946 if (AOP_TYPE (left) == AOP_CRY)
5948 if (AOP_TYPE (right) == AOP_LIT)
5950 // c = bit & literal;
5953 // lit != 0 => result = 1
5954 if (AOP_TYPE (result) == AOP_CRY)
5957 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5959 continueIfTrue (ifx);
5962 emitcode ("setb", "c");
5966 // lit == 0 => result = left
5967 if (size && sameRegs (AOP (result), AOP (left)))
5969 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5974 if (AOP_TYPE (right) == AOP_CRY)
5977 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5978 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5983 symbol *tlbl = newiTempLabel (NULL);
5984 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5985 emitcode ("setb", "c");
5986 emitcode ("jb", "%s,%05d$",
5987 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5989 emitcode ("jnz", "%05d$", tlbl->key + 100);
5990 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5992 jmpTrueOrFalse (ifx, tlbl);
5998 emitcode ("", "%05d$:", tlbl->key + 100);
6007 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6008 genIfxJump (ifx, "c");
6012 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6013 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6014 if ((AOP_TYPE (right) == AOP_LIT) &&
6015 (AOP_TYPE (result) == AOP_CRY) &&
6016 (AOP_TYPE (left) != AOP_CRY))
6022 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6024 continueIfTrue (ifx);
6029 // lit = 0, result = boolean(left)
6031 emitcode ("setb", "c");
6035 symbol *tlbl = newiTempLabel (NULL);
6036 emitcode ("jnz", "%05d$", tlbl->key + 100);
6038 emitcode ("", "%05d$:", tlbl->key + 100);
6042 genIfxJump (ifx, "a");
6050 /* if left is same as result */
6051 if (sameRegs (AOP (result), AOP (left)))
6053 for (; size--; offset++)
6055 if (AOP_TYPE (right) == AOP_LIT)
6057 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6063 if (IS_AOP_PREG (left))
6065 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6066 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6067 aopPut (AOP (result), "a", offset);
6071 emitcode ("orl", "%s,%s",
6072 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6073 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6079 if (AOP_TYPE (left) == AOP_ACC)
6081 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6085 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6086 if (IS_AOP_PREG (left))
6088 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6089 aopPut (AOP (result), "a", offset);
6093 emitcode ("orl", "%s,a",
6094 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6102 // left & result in different registers
6103 if (AOP_TYPE (result) == AOP_CRY)
6106 // if(size), result in bit
6107 // if(!size && ifx), conditional oper: if(left | right)
6108 symbol *tlbl = newiTempLabel (NULL);
6109 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6111 emitcode ("setb", "c");
6114 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6115 emitcode ("orl", "a,%s",
6116 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6118 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6119 emitcode ("orl", "a,%s",
6120 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6122 emitcode ("jnz", "%05d$", tlbl->key + 100);
6128 emitcode ("", "%05d$:", tlbl->key + 100);
6132 jmpTrueOrFalse (ifx, tlbl);
6136 _startLazyDPSEvaluation();
6137 for (; (size--); offset++)
6140 // result = left & right
6141 if (AOP_TYPE (right) == AOP_LIT)
6143 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6145 aopPut (AOP (result),
6146 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6150 D (emitcode (";", "better literal OR."););
6151 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6152 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6153 FALSE, FALSE, FALSE));
6158 // faster than result <- left, anl result,right
6159 // and better if result is SFR
6160 if (AOP_TYPE (left) == AOP_ACC)
6162 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6163 FALSE, FALSE, FALSE));
6167 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6169 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6171 emitcode("mov", "b,a");
6175 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6176 emitcode ("orl", "a,%s", rOp);
6179 aopPut (AOP (result), "a", offset);
6181 _endLazyDPSEvaluation();
6186 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6187 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6188 freeAsmop (result, NULL, ic, TRUE);
6191 /*-----------------------------------------------------------------*/
6192 /* genXor - code for xclusive or */
6193 /*-----------------------------------------------------------------*/
6195 genXor (iCode * ic, iCode * ifx)
6197 operand *left, *right, *result;
6198 int size, offset = 0;
6199 unsigned long lit = 0L;
6202 D (emitcode (";", "genXor "););
6204 AOP_OP_3_NOFATAL (ic, pushResult);
6205 AOP_SET_LOCALS (ic);
6209 genFarFarLogicOp(ic, "xrl");
6214 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6216 AOP_TYPE (left), AOP_TYPE (right));
6217 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6219 AOP_SIZE (left), AOP_SIZE (right));
6222 /* if left is a literal & right is not ||
6223 if left needs acc & right does not */
6224 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6225 #ifdef LOGIC_OPS_BROKEN
6226 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6230 operand *tmp = right;
6235 /* if result = right then exchange them */
6236 if (sameRegs (AOP (result), AOP (right)))
6238 operand *tmp = right;
6243 /* if right is bit then exchange them */
6244 if (AOP_TYPE (right) == AOP_CRY &&
6245 AOP_TYPE (left) != AOP_CRY)
6247 operand *tmp = right;
6251 if (AOP_TYPE (right) == AOP_LIT)
6252 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6254 size = AOP_SIZE (result);
6258 if (AOP_TYPE (left) == AOP_CRY)
6260 if (AOP_TYPE (right) == AOP_LIT)
6262 // c = bit & literal;
6265 // lit>>1 != 0 => result = 1
6266 if (AOP_TYPE (result) == AOP_CRY)
6269 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6271 continueIfTrue (ifx);
6274 emitcode ("setb", "c");
6281 // lit == 0, result = left
6282 if (size && sameRegs (AOP (result), AOP (left)))
6284 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6288 // lit == 1, result = not(left)
6289 if (size && sameRegs (AOP (result), AOP (left)))
6291 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6296 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6297 emitcode ("cpl", "c");
6306 symbol *tlbl = newiTempLabel (NULL);
6307 if (AOP_TYPE (right) == AOP_CRY)
6310 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6314 int sizer = AOP_SIZE (right);
6316 // if val>>1 != 0, result = 1
6317 emitcode ("setb", "c");
6320 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6322 // test the msb of the lsb
6323 emitcode ("anl", "a,#0xfe");
6324 emitcode ("jnz", "%05d$", tlbl->key + 100);
6328 emitcode ("rrc", "a");
6330 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6331 emitcode ("cpl", "c");
6332 emitcode ("", "%05d$:", (tlbl->key + 100));
6339 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6340 genIfxJump (ifx, "c");
6344 if (sameRegs (AOP (result), AOP (left)))
6346 /* if left is same as result */
6347 for (; size--; offset++)
6349 if (AOP_TYPE (right) == AOP_LIT)
6351 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6353 else if (IS_AOP_PREG (left))
6355 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6356 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6357 aopPut (AOP (result), "a", offset);
6360 emitcode ("xrl", "%s,%s",
6361 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6362 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6366 if (AOP_TYPE (left) == AOP_ACC)
6367 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6370 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6371 if (IS_AOP_PREG (left))
6373 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6374 aopPut (AOP (result), "a", offset);
6377 emitcode ("xrl", "%s,a",
6378 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6385 // left & result in different registers
6386 if (AOP_TYPE (result) == AOP_CRY)
6389 // if(size), result in bit
6390 // if(!size && ifx), conditional oper: if(left ^ right)
6391 symbol *tlbl = newiTempLabel (NULL);
6392 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6394 emitcode ("setb", "c");
6397 if ((AOP_TYPE (right) == AOP_LIT) &&
6398 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6400 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6404 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6405 emitcode ("xrl", "a,%s",
6406 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6408 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6409 emitcode ("xrl", "a,%s",
6410 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6413 emitcode ("jnz", "%05d$", tlbl->key + 100);
6419 emitcode ("", "%05d$:", tlbl->key + 100);
6423 jmpTrueOrFalse (ifx, tlbl);
6426 for (; (size--); offset++)
6429 // result = left & right
6430 if (AOP_TYPE (right) == AOP_LIT)
6432 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6434 aopPut (AOP (result),
6435 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6439 D (emitcode (";", "better literal XOR.");
6441 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6442 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6443 FALSE, FALSE, FALSE));
6447 // faster than result <- left, anl result,right
6448 // and better if result is SFR
6449 if (AOP_TYPE (left) == AOP_ACC)
6451 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6452 FALSE, FALSE, FALSE));
6456 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6457 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6459 emitcode("mov", "b,a");
6463 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6464 emitcode ("xrl", "a,%s", rOp);
6467 aopPut (AOP (result), "a", offset);
6472 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6473 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6474 freeAsmop (result, NULL, ic, TRUE);
6477 /*-----------------------------------------------------------------*/
6478 /* genInline - write the inline code out */
6479 /*-----------------------------------------------------------------*/
6481 genInline (iCode * ic)
6483 char *buffer, *bp, *bp1;
6485 D (emitcode (";", "genInline ");
6488 _G.inLine += (!options.asmpeep);
6490 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6491 strcpy (buffer, IC_INLINE (ic));
6493 /* emit each line as a code */
6518 /* emitcode("",buffer); */
6519 _G.inLine -= (!options.asmpeep);
6522 /*-----------------------------------------------------------------*/
6523 /* genRRC - rotate right with carry */
6524 /*-----------------------------------------------------------------*/
6528 operand *left, *result;
6529 int size, offset = 0;
6532 D (emitcode (";", "genRRC ");
6535 /* rotate right with carry */
6536 left = IC_LEFT (ic);
6537 result = IC_RESULT (ic);
6538 aopOp (left, ic, FALSE, FALSE);
6539 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6541 /* move it to the result */
6542 size = AOP_SIZE (result);
6546 _startLazyDPSEvaluation ();
6549 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6551 emitcode ("rrc", "a");
6552 if (AOP_SIZE (result) > 1)
6553 aopPut (AOP (result), "a", offset--);
6555 _endLazyDPSEvaluation ();
6557 /* now we need to put the carry into the
6558 highest order byte of the result */
6559 if (AOP_SIZE (result) > 1)
6561 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6564 emitcode ("mov", "acc.7,c");
6565 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6566 freeAsmop (left, NULL, ic, TRUE);
6567 freeAsmop (result, NULL, ic, TRUE);
6570 /*-----------------------------------------------------------------*/
6571 /* genRLC - generate code for rotate left with carry */
6572 /*-----------------------------------------------------------------*/
6576 operand *left, *result;
6577 int size, offset = 0;
6580 D (emitcode (";", "genRLC ");
6583 /* rotate right with carry */
6584 left = IC_LEFT (ic);
6585 result = IC_RESULT (ic);
6586 aopOp (left, ic, FALSE, FALSE);
6587 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6589 /* move it to the result */
6590 size = AOP_SIZE (result);
6594 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6596 emitcode ("add", "a,acc");
6597 if (AOP_SIZE (result) > 1)
6599 aopPut (AOP (result), "a", offset++);
6602 _startLazyDPSEvaluation ();
6605 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6607 emitcode ("rlc", "a");
6608 if (AOP_SIZE (result) > 1)
6609 aopPut (AOP (result), "a", offset++);
6611 _endLazyDPSEvaluation ();
6613 /* now we need to put the carry into the
6614 highest order byte of the result */
6615 if (AOP_SIZE (result) > 1)
6617 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6620 emitcode ("mov", "acc.0,c");
6621 aopPut (AOP (result), "a", 0);
6622 freeAsmop (left, NULL, ic, TRUE);
6623 freeAsmop (result, NULL, ic, TRUE);
6626 /*-----------------------------------------------------------------*/
6627 /* genGetHbit - generates code get highest order bit */
6628 /*-----------------------------------------------------------------*/
6630 genGetHbit (iCode * ic)
6632 operand *left, *result;
6633 left = IC_LEFT (ic);
6634 result = IC_RESULT (ic);
6635 aopOp (left, ic, FALSE, FALSE);
6636 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6638 D (emitcode (";", "genGetHbit ");
6641 /* get the highest order byte into a */
6642 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6643 if (AOP_TYPE (result) == AOP_CRY)
6645 emitcode ("rlc", "a");
6650 emitcode ("rl", "a");
6651 emitcode ("anl", "a,#0x01");
6656 freeAsmop (left, NULL, ic, TRUE);
6657 freeAsmop (result, NULL, ic, TRUE);
6660 /*-----------------------------------------------------------------*/
6661 /* AccRol - rotate left accumulator by known count */
6662 /*-----------------------------------------------------------------*/
6664 AccRol (int shCount)
6666 shCount &= 0x0007; // shCount : 0..7
6673 emitcode ("rl", "a");
6676 emitcode ("rl", "a");
6677 emitcode ("rl", "a");
6680 emitcode ("swap", "a");
6681 emitcode ("rr", "a");
6684 emitcode ("swap", "a");
6687 emitcode ("swap", "a");
6688 emitcode ("rl", "a");
6691 emitcode ("rr", "a");
6692 emitcode ("rr", "a");
6695 emitcode ("rr", "a");
6700 /*-----------------------------------------------------------------*/
6701 /* AccLsh - left shift accumulator by known count */
6702 /*-----------------------------------------------------------------*/
6704 AccLsh (int shCount)
6709 emitcode ("add", "a,acc");
6710 else if (shCount == 2)
6712 emitcode ("add", "a,acc");
6713 emitcode ("add", "a,acc");
6717 /* rotate left accumulator */
6719 /* and kill the lower order bits */
6720 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6725 /*-----------------------------------------------------------------*/
6726 /* AccRsh - right shift accumulator by known count */
6727 /*-----------------------------------------------------------------*/
6729 AccRsh (int shCount)
6736 emitcode ("rrc", "a");
6740 /* rotate right accumulator */
6741 AccRol (8 - shCount);
6742 /* and kill the higher order bits */
6743 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6748 #ifdef BETTER_LITERAL_SHIFT
6749 /*-----------------------------------------------------------------*/
6750 /* AccSRsh - signed right shift accumulator by known count */
6751 /*-----------------------------------------------------------------*/
6753 AccSRsh (int shCount)
6760 emitcode ("mov", "c,acc.7");
6761 emitcode ("rrc", "a");
6763 else if (shCount == 2)
6765 emitcode ("mov", "c,acc.7");
6766 emitcode ("rrc", "a");
6767 emitcode ("mov", "c,acc.7");
6768 emitcode ("rrc", "a");
6772 tlbl = newiTempLabel (NULL);
6773 /* rotate right accumulator */
6774 AccRol (8 - shCount);
6775 /* and kill the higher order bits */
6776 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6777 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6778 emitcode ("orl", "a,#0x%02x",
6779 (unsigned char) ~SRMask[shCount]);
6780 emitcode ("", "%05d$:", tlbl->key + 100);
6786 #ifdef BETTER_LITERAL_SHIFT
6787 /*-----------------------------------------------------------------*/
6788 /* shiftR1Left2Result - shift right one byte from left to result */
6789 /*-----------------------------------------------------------------*/
6791 shiftR1Left2Result (operand * left, int offl,
6792 operand * result, int offr,
6793 int shCount, int sign)
6795 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6796 /* shift right accumulator */
6801 aopPut (AOP (result), "a", offr);
6805 #ifdef BETTER_LITERAL_SHIFT
6806 /*-----------------------------------------------------------------*/
6807 /* shiftL1Left2Result - shift left one byte from left to result */
6808 /*-----------------------------------------------------------------*/
6810 shiftL1Left2Result (operand * left, int offl,
6811 operand * result, int offr, int shCount)
6813 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6814 /* shift left accumulator */
6816 aopPut (AOP (result), "a", offr);
6820 #ifdef BETTER_LITERAL_SHIFT
6821 /*-----------------------------------------------------------------*/
6822 /* movLeft2Result - move byte from left to result */
6823 /*-----------------------------------------------------------------*/
6825 movLeft2Result (operand * left, int offl,
6826 operand * result, int offr, int sign)
6829 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6831 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6833 if (*l == '@' && (IS_AOP_PREG (result)))
6835 emitcode ("mov", "a,%s", l);
6836 aopPut (AOP (result), "a", offr);
6842 aopPut (AOP (result), l, offr);
6846 /* MSB sign in acc.7 ! */
6847 if (getDataSize (left) == offl + 1)
6849 emitcode ("mov", "a,%s", l);
6850 aopPut (AOP (result), "a", offr);
6858 #ifdef BETTER_LITERAL_SHIFT
6859 /*-----------------------------------------------------------------*/
6860 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6861 /*-----------------------------------------------------------------*/
6865 emitcode ("rrc", "a");
6866 emitcode ("xch", "a,%s", x);
6867 emitcode ("rrc", "a");
6868 emitcode ("xch", "a,%s", x);
6872 #ifdef BETTER_LITERAL_SHIFT
6874 /*-----------------------------------------------------------------*/
6875 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6876 /*-----------------------------------------------------------------*/
6880 emitcode ("xch", "a,%s", x);
6881 emitcode ("rlc", "a");
6882 emitcode ("xch", "a,%s", x);
6883 emitcode ("rlc", "a");
6887 #ifdef BETTER_LITERAL_SHIFT
6888 /*-----------------------------------------------------------------*/
6889 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6890 /*-----------------------------------------------------------------*/
6894 emitcode ("xch", "a,%s", x);
6895 emitcode ("add", "a,acc");
6896 emitcode ("xch", "a,%s", x);
6897 emitcode ("rlc", "a");
6901 #ifdef BETTER_LITERAL_SHIFT
6902 /*-----------------------------------------------------------------*/
6903 /* AccAXLsh - left shift a:x by known count (0..7) */
6904 /*-----------------------------------------------------------------*/
6906 AccAXLsh (char *x, int shCount)
6921 case 5: // AAAAABBB:CCCCCDDD
6923 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6925 emitcode ("anl", "a,#0x%02x",
6926 SLMask[shCount]); // BBB00000:CCCCCDDD
6928 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6930 AccRol (shCount); // DDDCCCCC:BBB00000
6932 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6934 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6936 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6938 emitcode ("anl", "a,#0x%02x",
6939 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6941 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6943 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6946 case 6: // AAAAAABB:CCCCCCDD
6947 emitcode ("anl", "a,#0x%02x",
6948 SRMask[shCount]); // 000000BB:CCCCCCDD
6949 emitcode ("mov", "c,acc.0"); // c = B
6950 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6952 AccAXRrl1 (x); // BCCCCCCD:D000000B
6953 AccAXRrl1 (x); // BBCCCCCC:DD000000
6955 emitcode("rrc","a");
6956 emitcode("xch","a,%s", x);
6957 emitcode("rrc","a");
6958 emitcode("mov","c,acc.0"); //<< get correct bit
6959 emitcode("xch","a,%s", x);
6961 emitcode("rrc","a");
6962 emitcode("xch","a,%s", x);
6963 emitcode("rrc","a");
6964 emitcode("xch","a,%s", x);
6967 case 7: // a:x <<= 7
6969 emitcode ("anl", "a,#0x%02x",
6970 SRMask[shCount]); // 0000000B:CCCCCCCD
6972 emitcode ("mov", "c,acc.0"); // c = B
6974 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6976 AccAXRrl1 (x); // BCCCCCCC:D0000000
6985 #ifdef BETTER_LITERAL_SHIFT
6987 /*-----------------------------------------------------------------*/
6988 /* AccAXRsh - right shift a:x known count (0..7) */
6989 /*-----------------------------------------------------------------*/
6991 AccAXRsh (char *x, int shCount)
6999 AccAXRrl1 (x); // 0->a:x
7004 AccAXRrl1 (x); // 0->a:x
7007 AccAXRrl1 (x); // 0->a:x
7012 case 5: // AAAAABBB:CCCCCDDD = a:x
7014 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7016 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7018 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7020 emitcode ("anl", "a,#0x%02x",
7021 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7023 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7025 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7027 emitcode ("anl", "a,#0x%02x",
7028 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7030 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7032 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7034 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7037 case 6: // AABBBBBB:CCDDDDDD
7039 emitcode ("mov", "c,acc.7");
7040 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7042 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7044 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7046 emitcode ("anl", "a,#0x%02x",
7047 SRMask[shCount]); // 000000AA:BBBBBBCC
7050 case 7: // ABBBBBBB:CDDDDDDD
7052 emitcode ("mov", "c,acc.7"); // c = A
7054 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7056 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7058 emitcode ("anl", "a,#0x%02x",
7059 SRMask[shCount]); // 0000000A:BBBBBBBC
7068 #ifdef BETTER_LITERAL_SHIFT
7069 /*-----------------------------------------------------------------*/
7070 /* AccAXRshS - right shift signed a:x known count (0..7) */
7071 /*-----------------------------------------------------------------*/
7073 AccAXRshS (char *x, int shCount)
7081 emitcode ("mov", "c,acc.7");
7082 AccAXRrl1 (x); // s->a:x
7086 emitcode ("mov", "c,acc.7");
7087 AccAXRrl1 (x); // s->a:x
7089 emitcode ("mov", "c,acc.7");
7090 AccAXRrl1 (x); // s->a:x
7095 case 5: // AAAAABBB:CCCCCDDD = a:x
7097 tlbl = newiTempLabel (NULL);
7098 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7100 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7102 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7104 emitcode ("anl", "a,#0x%02x",
7105 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7107 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7109 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7111 emitcode ("anl", "a,#0x%02x",
7112 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7114 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7116 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7118 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7120 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7121 emitcode ("orl", "a,#0x%02x",
7122 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7124 emitcode ("", "%05d$:", tlbl->key + 100);
7125 break; // SSSSAAAA:BBBCCCCC
7127 case 6: // AABBBBBB:CCDDDDDD
7129 tlbl = newiTempLabel (NULL);
7130 emitcode ("mov", "c,acc.7");
7131 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7133 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7135 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7137 emitcode ("anl", "a,#0x%02x",
7138 SRMask[shCount]); // 000000AA:BBBBBBCC
7140 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7141 emitcode ("orl", "a,#0x%02x",
7142 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7144 emitcode ("", "%05d$:", tlbl->key + 100);
7146 case 7: // ABBBBBBB:CDDDDDDD
7148 tlbl = newiTempLabel (NULL);
7149 emitcode ("mov", "c,acc.7"); // c = A
7151 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7153 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7155 emitcode ("anl", "a,#0x%02x",
7156 SRMask[shCount]); // 0000000A:BBBBBBBC
7158 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7159 emitcode ("orl", "a,#0x%02x",
7160 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7162 emitcode ("", "%05d$:", tlbl->key + 100);
7170 #ifdef BETTER_LITERAL_SHIFT
7172 _loadLeftIntoAx(char **lsb,
7178 // Get the initial value from left into a pair of registers.
7179 // MSB must be in A, LSB can be any register.
7181 // If the result is held in registers, it is an optimization
7182 // if the LSB can be held in the register which will hold the,
7183 // result LSB since this saves us from having to copy it into
7184 // the result following AccAXLsh.
7186 // If the result is addressed indirectly, this is not a gain.
7187 if (AOP_NEEDSACC(result))
7191 _startLazyDPSEvaluation();
7192 if (AOP_TYPE(left) == AOP_DPTR2)
7195 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7196 // get LSB in DP2_RESULT_REG.
7197 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7198 assert(!strcmp(leftByte, DP2_RESULT_REG));
7202 // get LSB into DP2_RESULT_REG
7203 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7204 if (strcmp(leftByte, DP2_RESULT_REG))
7207 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7210 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7211 assert(strcmp(leftByte, DP2_RESULT_REG));
7214 _endLazyDPSEvaluation();
7215 *lsb = DP2_RESULT_REG;
7219 if (sameRegs (AOP (result), AOP (left)) &&
7220 ((offl + MSB16) == offr))
7222 /* don't crash result[offr] */
7223 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7224 emitcode ("xch", "a,%s",
7225 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7229 movLeft2Result (left, offl, result, offr, 0);
7230 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7232 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7233 assert(strcmp(*lsb,"a"));
7238 _storeAxResults(char *lsb,
7242 _startLazyDPSEvaluation();
7243 if (AOP_NEEDSACC(result))
7245 /* We have to explicitly update the result LSB.
7247 emitcode("xch","a,%s", lsb);
7248 aopPut(AOP(result), "a", offr);
7249 emitcode("mov","a,%s", lsb);
7251 if (getDataSize (result) > 1)
7253 aopPut (AOP (result), "a", offr + MSB16);
7255 _endLazyDPSEvaluation();
7258 /*-----------------------------------------------------------------*/
7259 /* shiftL2Left2Result - shift left two bytes from left to result */
7260 /*-----------------------------------------------------------------*/
7262 shiftL2Left2Result (operand * left, int offl,
7263 operand * result, int offr, int shCount)
7267 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7269 AccAXLsh (lsb, shCount);
7271 _storeAxResults(lsb, result, offr);
7275 #ifdef BETTER_LITERAL_SHIFT
7276 /*-----------------------------------------------------------------*/
7277 /* shiftR2Left2Result - shift right two bytes from left to result */
7278 /*-----------------------------------------------------------------*/
7280 shiftR2Left2Result (operand * left, int offl,
7281 operand * result, int offr,
7282 int shCount, int sign)
7286 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7288 /* a:x >> shCount (x = lsb(result)) */
7291 AccAXRshS(lsb, shCount);
7295 AccAXRsh(lsb, shCount);
7298 _storeAxResults(lsb, result, offr);
7304 /*-----------------------------------------------------------------*/
7305 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7306 /*-----------------------------------------------------------------*/
7308 shiftLLeftOrResult (operand * left, int offl,
7309 operand * result, int offr, int shCount)
7311 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7312 /* shift left accumulator */
7314 /* or with result */
7315 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7316 /* back to result */
7317 aopPut (AOP (result), "a", offr);
7323 /*-----------------------------------------------------------------*/
7324 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7325 /*-----------------------------------------------------------------*/
7327 shiftRLeftOrResult (operand * left, int offl,
7328 operand * result, int offr, int shCount)
7330 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7331 /* shift right accumulator */
7333 /* or with result */
7334 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7335 /* back to result */
7336 aopPut (AOP (result), "a", offr);
7340 #ifdef BETTER_LITERAL_SHIFT
7341 /*-----------------------------------------------------------------*/
7342 /* genlshOne - left shift a one byte quantity by known count */
7343 /*-----------------------------------------------------------------*/
7345 genlshOne (operand * result, operand * left, int shCount)
7347 D (emitcode (";", "genlshOne "););
7348 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7352 #ifdef BETTER_LITERAL_SHIFT
7353 /*-----------------------------------------------------------------*/
7354 /* genlshTwo - left shift two bytes by known amount != 0 */
7355 /*-----------------------------------------------------------------*/
7357 genlshTwo (operand * result, operand * left, int shCount)
7361 D (emitcode (";", "genlshTwo "););
7363 size = getDataSize (result);
7365 /* if shCount >= 8 */
7370 _startLazyDPSEvaluation();
7376 _endLazyDPSEvaluation();
7377 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7378 aopPut (AOP (result), zero, LSB);
7382 movLeft2Result (left, LSB, result, MSB16, 0);
7383 aopPut (AOP (result), zero, LSB);
7384 _endLazyDPSEvaluation();
7389 aopPut (AOP (result), zero, LSB);
7390 _endLazyDPSEvaluation();
7394 /* 1 <= shCount <= 7 */
7399 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7403 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7411 /*-----------------------------------------------------------------*/
7412 /* shiftLLong - shift left one long from left to result */
7413 /* offl = LSB or MSB16 */
7414 /*-----------------------------------------------------------------*/
7416 shiftLLong (operand * left, operand * result, int offr)
7419 int size = AOP_SIZE (result);
7421 if (size >= LSB + offr)
7423 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7425 emitcode ("add", "a,acc");
7426 if (sameRegs (AOP (left), AOP (result)) &&
7427 size >= MSB16 + offr && offr != LSB)
7428 emitcode ("xch", "a,%s",
7429 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7431 aopPut (AOP (result), "a", LSB + offr);
7434 if (size >= MSB16 + offr)
7436 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7438 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7441 emitcode ("rlc", "a");
7442 if (sameRegs (AOP (left), AOP (result)) &&
7443 size >= MSB24 + offr && offr != LSB)
7444 emitcode ("xch", "a,%s",
7445 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7447 aopPut (AOP (result), "a", MSB16 + offr);
7450 if (size >= MSB24 + offr)
7452 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7454 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7457 emitcode ("rlc", "a");
7458 if (sameRegs (AOP (left), AOP (result)) &&
7459 size >= MSB32 + offr && offr != LSB)
7460 emitcode ("xch", "a,%s",
7461 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7463 aopPut (AOP (result), "a", MSB24 + offr);
7466 if (size > MSB32 + offr)
7468 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7470 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7473 emitcode ("rlc", "a");
7474 aopPut (AOP (result), "a", MSB32 + offr);
7477 aopPut (AOP (result), zero, LSB);
7483 /*-----------------------------------------------------------------*/
7484 /* genlshFour - shift four byte by a known amount != 0 */
7485 /*-----------------------------------------------------------------*/
7487 genlshFour (operand * result, operand * left, int shCount)
7491 D (emitcode (";", "genlshFour ");
7494 size = AOP_SIZE (result);
7496 /* if shifting more that 3 bytes */
7501 /* lowest order of left goes to the highest
7502 order of the destination */
7503 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7505 movLeft2Result (left, LSB, result, MSB32, 0);
7506 aopPut (AOP (result), zero, LSB);
7507 aopPut (AOP (result), zero, MSB16);
7508 aopPut (AOP (result), zero, MSB24);
7512 /* more than two bytes */
7513 else if (shCount >= 16)
7515 /* lower order two bytes goes to higher order two bytes */
7517 /* if some more remaining */
7519 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7522 movLeft2Result (left, MSB16, result, MSB32, 0);
7523 movLeft2Result (left, LSB, result, MSB24, 0);
7525 aopPut (AOP (result), zero, MSB16);
7526 aopPut (AOP (result), zero, LSB);
7530 /* if more than 1 byte */
7531 else if (shCount >= 8)
7533 /* lower order three bytes goes to higher order three bytes */
7538 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7540 movLeft2Result (left, LSB, result, MSB16, 0);
7546 movLeft2Result (left, MSB24, result, MSB32, 0);
7547 movLeft2Result (left, MSB16, result, MSB24, 0);
7548 movLeft2Result (left, LSB, result, MSB16, 0);
7549 aopPut (AOP (result), zero, LSB);
7551 else if (shCount == 1)
7552 shiftLLong (left, result, MSB16);
7555 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7556 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7557 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7558 aopPut (AOP (result), zero, LSB);
7563 /* 1 <= shCount <= 7 */
7564 else if (shCount <= 2)
7566 shiftLLong (left, result, LSB);
7568 shiftLLong (result, result, LSB);
7570 /* 3 <= shCount <= 7, optimize */
7573 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7574 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7575 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7580 #ifdef BETTER_LITERAL_SHIFT
7581 /*-----------------------------------------------------------------*/
7582 /* genLeftShiftLiteral - left shifting by known count */
7583 /*-----------------------------------------------------------------*/
7585 genLeftShiftLiteral (operand * left,
7590 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7593 size = getSize (operandType (result));
7595 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7597 /* We only handle certain easy cases so far. */
7599 && (shCount < (size * 8))
7603 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7607 freeAsmop (right, NULL, ic, TRUE);
7609 aopOp(left, ic, FALSE, FALSE);
7610 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7613 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7615 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7616 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7618 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7621 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7623 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7624 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7626 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7632 emitcode ("; shift left ", "result %d, left %d", size,
7636 /* I suppose that the left size >= result size */
7639 _startLazyDPSEvaluation();
7642 movLeft2Result (left, size, result, size, 0);
7644 _endLazyDPSEvaluation();
7646 else if (shCount >= (size * 8))
7648 _startLazyDPSEvaluation();
7651 aopPut (AOP (result), zero, size);
7653 _endLazyDPSEvaluation();
7660 genlshOne (result, left, shCount);
7664 genlshTwo (result, left, shCount);
7668 genlshFour (result, left, shCount);
7672 fprintf(stderr, "*** ack! mystery literal shift!\n");
7676 freeAsmop (left, NULL, ic, TRUE);
7677 freeAsmop (result, NULL, ic, TRUE);
7682 /*-----------------------------------------------------------------*/
7683 /* genLeftShift - generates code for left shifting */
7684 /*-----------------------------------------------------------------*/
7686 genLeftShift (iCode * ic)
7688 operand *left, *right, *result;
7691 symbol *tlbl, *tlbl1;
7693 D (emitcode (";", "genLeftShift "););
7695 right = IC_RIGHT (ic);
7696 left = IC_LEFT (ic);
7697 result = IC_RESULT (ic);
7699 aopOp (right, ic, FALSE, FALSE);
7702 #ifdef BETTER_LITERAL_SHIFT
7703 /* if the shift count is known then do it
7704 as efficiently as possible */
7705 if (AOP_TYPE (right) == AOP_LIT)
7707 if (genLeftShiftLiteral (left, right, result, ic))
7714 /* shift count is unknown then we have to form
7715 a loop get the loop count in B : Note: we take
7716 only the lower order byte since shifting
7717 more that 32 bits make no sense anyway, ( the
7718 largest size of an object can be only 32 bits ) */
7720 if (AOP_TYPE (right) == AOP_LIT)
7722 /* Really should be handled by genLeftShiftLiteral,
7723 * but since I'm too lazy to fix that today, at least we can make
7724 * some small improvement.
7726 emitcode("mov", "b,#0x%02x",
7727 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7731 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7732 emitcode ("inc", "b");
7734 freeAsmop (right, NULL, ic, TRUE);
7735 aopOp (left, ic, FALSE, FALSE);
7736 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7738 /* now move the left to the result if they are not the
7740 if (!sameRegs (AOP (left), AOP (result)) &&
7741 AOP_SIZE (result) > 1)
7744 size = AOP_SIZE (result);
7746 _startLazyDPSEvaluation ();
7749 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7750 if (*l == '@' && (IS_AOP_PREG (result)))
7753 emitcode ("mov", "a,%s", l);
7754 aopPut (AOP (result), "a", offset);
7757 aopPut (AOP (result), l, offset);
7760 _endLazyDPSEvaluation ();
7763 tlbl = newiTempLabel (NULL);
7764 size = AOP_SIZE (result);
7766 tlbl1 = newiTempLabel (NULL);
7768 /* if it is only one byte then */
7771 symbol *tlbl1 = newiTempLabel (NULL);
7773 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7775 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7776 emitcode ("", "%05d$:", tlbl->key + 100);
7777 emitcode ("add", "a,acc");
7778 emitcode ("", "%05d$:", tlbl1->key + 100);
7779 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7780 aopPut (AOP (result), "a", 0);
7784 reAdjustPreg (AOP (result));
7786 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7787 emitcode ("", "%05d$:", tlbl->key + 100);
7788 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7790 emitcode ("add", "a,acc");
7791 aopPut (AOP (result), "a", offset++);
7792 _startLazyDPSEvaluation ();
7795 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7797 emitcode ("rlc", "a");
7798 aopPut (AOP (result), "a", offset++);
7800 _endLazyDPSEvaluation ();
7801 reAdjustPreg (AOP (result));
7803 emitcode ("", "%05d$:", tlbl1->key + 100);
7804 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7806 freeAsmop (left, NULL, ic, TRUE);
7807 freeAsmop (result, NULL, ic, TRUE);
7810 #ifdef BETTER_LITERAL_SHIFT
7811 /*-----------------------------------------------------------------*/
7812 /* genrshOne - right shift a one byte quantity by known count */
7813 /*-----------------------------------------------------------------*/
7815 genrshOne (operand * result, operand * left,
7816 int shCount, int sign)
7818 D (emitcode (";", "genrshOne"););
7819 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7823 #ifdef BETTER_LITERAL_SHIFT
7824 /*-----------------------------------------------------------------*/
7825 /* genrshTwo - right shift two bytes by known amount != 0 */
7826 /*-----------------------------------------------------------------*/
7828 genrshTwo (operand * result, operand * left,
7829 int shCount, int sign)
7831 D (emitcode (";", "genrshTwo"););
7833 /* if shCount >= 8 */
7837 _startLazyDPSEvaluation();
7840 shiftR1Left2Result (left, MSB16, result, LSB,
7845 movLeft2Result (left, MSB16, result, LSB, sign);
7847 addSign (result, MSB16, sign);
7848 _endLazyDPSEvaluation();
7851 /* 1 <= shCount <= 7 */
7854 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7861 /*-----------------------------------------------------------------*/
7862 /* shiftRLong - shift right one long from left to result */
7863 /* offl = LSB or MSB16 */
7864 /*-----------------------------------------------------------------*/
7866 shiftRLong (operand * left, int offl,
7867 operand * result, int sign)
7869 int isSameRegs=sameRegs(AOP(left),AOP(result));
7871 if (isSameRegs && offl>1) {
7872 // we are in big trouble, but this shouldn't happen
7873 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7876 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7881 emitcode ("rlc", "a");
7882 emitcode ("subb", "a,acc");
7883 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7885 aopPut (AOP(result), zero, MSB32);
7890 emitcode ("clr", "c");
7892 emitcode ("mov", "c,acc.7");
7895 emitcode ("rrc", "a");
7897 if (isSameRegs && offl==MSB16) {
7898 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7900 aopPut (AOP (result), "a", MSB32);
7901 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7904 emitcode ("rrc", "a");
7905 if (isSameRegs && offl==1) {
7906 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7908 aopPut (AOP (result), "a", MSB24);
7909 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7911 emitcode ("rrc", "a");
7912 aopPut (AOP (result), "a", MSB16 - offl);
7916 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7917 emitcode ("rrc", "a");
7918 aopPut (AOP (result), "a", LSB);
7925 /*-----------------------------------------------------------------*/
7926 /* genrshFour - shift four byte by a known amount != 0 */
7927 /*-----------------------------------------------------------------*/
7929 genrshFour (operand * result, operand * left,
7930 int shCount, int sign)
7932 D (emitcode (";", "genrshFour");
7935 /* if shifting more that 3 bytes */
7940 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7942 movLeft2Result (left, MSB32, result, LSB, sign);
7943 addSign (result, MSB16, sign);
7945 else if (shCount >= 16)
7949 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7952 movLeft2Result (left, MSB24, result, LSB, 0);
7953 movLeft2Result (left, MSB32, result, MSB16, sign);
7955 addSign (result, MSB24, sign);
7957 else if (shCount >= 8)
7961 shiftRLong (left, MSB16, result, sign);
7962 else if (shCount == 0)
7964 movLeft2Result (left, MSB16, result, LSB, 0);
7965 movLeft2Result (left, MSB24, result, MSB16, 0);
7966 movLeft2Result (left, MSB32, result, MSB24, sign);
7967 addSign (result, MSB32, sign);
7971 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7972 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7973 /* the last shift is signed */
7974 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7975 addSign (result, MSB32, sign);
7979 { /* 1 <= shCount <= 7 */
7982 shiftRLong (left, LSB, result, sign);
7984 shiftRLong (result, LSB, result, sign);
7988 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7989 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7990 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7996 #ifdef BETTER_LITERAL_SHIFT
7997 /*-----------------------------------------------------------------*/
7998 /* genRightShiftLiteral - right shifting by known count */
7999 /*-----------------------------------------------------------------*/
8001 genRightShiftLiteral (operand * left,
8007 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8010 size = getSize (operandType (result));
8012 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8014 /* We only handle certain easy cases so far. */
8016 && (shCount < (size * 8))
8020 D(emitcode (";", "genRightShiftLiteral wimping out"););
8024 freeAsmop (right, NULL, ic, TRUE);
8026 aopOp (left, ic, FALSE, FALSE);
8027 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8030 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8034 /* test the LEFT size !!! */
8036 /* I suppose that the left size >= result size */
8039 size = getDataSize (result);
8040 _startLazyDPSEvaluation();
8043 movLeft2Result (left, size, result, size, 0);
8045 _endLazyDPSEvaluation();
8047 else if (shCount >= (size * 8))
8051 /* get sign in acc.7 */
8052 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8054 addSign (result, LSB, sign);
8061 genrshOne (result, left, shCount, sign);
8065 genrshTwo (result, left, shCount, sign);
8069 genrshFour (result, left, shCount, sign);
8076 freeAsmop (left, NULL, ic, TRUE);
8077 freeAsmop (result, NULL, ic, TRUE);
8083 /*-----------------------------------------------------------------*/
8084 /* genSignedRightShift - right shift of signed number */
8085 /*-----------------------------------------------------------------*/
8087 genSignedRightShift (iCode * ic)
8089 operand *right, *left, *result;
8092 symbol *tlbl, *tlbl1;
8094 D (emitcode (";", "genSignedRightShift "););
8096 /* we do it the hard way put the shift count in b
8097 and loop thru preserving the sign */
8099 right = IC_RIGHT (ic);
8100 left = IC_LEFT (ic);
8101 result = IC_RESULT (ic);
8103 aopOp (right, ic, FALSE, FALSE);
8105 #ifdef BETTER_LITERAL_SHIFT
8106 if (AOP_TYPE (right) == AOP_LIT)
8108 if (genRightShiftLiteral (left, right, result, ic, 1))
8114 /* shift count is unknown then we have to form
8115 a loop get the loop count in B : Note: we take
8116 only the lower order byte since shifting
8117 more that 32 bits make no sense anyway, ( the
8118 largest size of an object can be only 32 bits ) */
8120 if (AOP_TYPE (right) == AOP_LIT)
8122 /* Really should be handled by genRightShiftLiteral,
8123 * but since I'm too lazy to fix that today, at least we can make
8124 * some small improvement.
8126 emitcode("mov", "b,#0x%02x",
8127 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8131 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8132 emitcode ("inc", "b");
8134 freeAsmop (right, NULL, ic, TRUE);
8135 aopOp (left, ic, FALSE, FALSE);
8136 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8138 /* now move the left to the result if they are not the
8140 if (!sameRegs (AOP (left), AOP (result)) &&
8141 AOP_SIZE (result) > 1)
8144 size = AOP_SIZE (result);
8146 _startLazyDPSEvaluation ();
8149 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8150 if (*l == '@' && IS_AOP_PREG (result))
8153 emitcode ("mov", "a,%s", l);
8154 aopPut (AOP (result), "a", offset);
8157 aopPut (AOP (result), l, offset);
8160 _endLazyDPSEvaluation ();
8163 /* mov the highest order bit to OVR */
8164 tlbl = newiTempLabel (NULL);
8165 tlbl1 = newiTempLabel (NULL);
8167 size = AOP_SIZE (result);
8169 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8170 emitcode ("rlc", "a");
8171 emitcode ("mov", "ov,c");
8172 /* if it is only one byte then */
8175 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8177 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8178 emitcode ("", "%05d$:", tlbl->key + 100);
8179 emitcode ("mov", "c,ov");
8180 emitcode ("rrc", "a");
8181 emitcode ("", "%05d$:", tlbl1->key + 100);
8182 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8183 aopPut (AOP (result), "a", 0);
8187 reAdjustPreg (AOP (result));
8188 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8189 emitcode ("", "%05d$:", tlbl->key + 100);
8190 emitcode ("mov", "c,ov");
8191 _startLazyDPSEvaluation ();
8194 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8196 emitcode ("rrc", "a");
8197 aopPut (AOP (result), "a", offset--);
8199 _endLazyDPSEvaluation ();
8200 reAdjustPreg (AOP (result));
8201 emitcode ("", "%05d$:", tlbl1->key + 100);
8202 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8205 freeAsmop (left, NULL, ic, TRUE);
8206 freeAsmop (result, NULL, ic, TRUE);
8209 /*-----------------------------------------------------------------*/
8210 /* genRightShift - generate code for right shifting */
8211 /*-----------------------------------------------------------------*/
8213 genRightShift (iCode * ic)
8215 operand *right, *left, *result;
8219 symbol *tlbl, *tlbl1;
8221 D (emitcode (";", "genRightShift "););
8223 /* if signed then we do it the hard way preserve the
8224 sign bit moving it inwards */
8225 retype = getSpec (operandType (IC_RESULT (ic)));
8227 if (!SPEC_USIGN (retype))
8229 genSignedRightShift (ic);
8233 /* signed & unsigned types are treated the same : i.e. the
8234 signed is NOT propagated inwards : quoting from the
8235 ANSI - standard : "for E1 >> E2, is equivalent to division
8236 by 2**E2 if unsigned or if it has a non-negative value,
8237 otherwise the result is implementation defined ", MY definition
8238 is that the sign does not get propagated */
8240 right = IC_RIGHT (ic);
8241 left = IC_LEFT (ic);
8242 result = IC_RESULT (ic);
8244 aopOp (right, ic, FALSE, FALSE);
8246 #ifdef BETTER_LITERAL_SHIFT
8247 /* if the shift count is known then do it
8248 as efficiently as possible */
8249 if (AOP_TYPE (right) == AOP_LIT)
8251 if (genRightShiftLiteral (left, right, result, ic, 0))
8258 /* shift count is unknown then we have to form
8259 a loop get the loop count in B : Note: we take
8260 only the lower order byte since shifting
8261 more that 32 bits make no sense anyway, ( the
8262 largest size of an object can be only 32 bits ) */
8264 if (AOP_TYPE (right) == AOP_LIT)
8266 /* Really should be handled by genRightShiftLiteral,
8267 * but since I'm too lazy to fix that today, at least we can make
8268 * some small improvement.
8270 emitcode("mov", "b,#0x%02x",
8271 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8275 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8276 emitcode ("inc", "b");
8278 freeAsmop (right, NULL, ic, TRUE);
8279 aopOp (left, ic, FALSE, FALSE);
8280 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8282 /* now move the left to the result if they are not the
8284 if (!sameRegs (AOP (left), AOP (result)) &&
8285 AOP_SIZE (result) > 1)
8288 size = AOP_SIZE (result);
8290 _startLazyDPSEvaluation ();
8293 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8294 if (*l == '@' && IS_AOP_PREG (result))
8297 emitcode ("mov", "a,%s", l);
8298 aopPut (AOP (result), "a", offset);
8301 aopPut (AOP (result), l, offset);
8304 _endLazyDPSEvaluation ();
8307 tlbl = newiTempLabel (NULL);
8308 tlbl1 = newiTempLabel (NULL);
8309 size = AOP_SIZE (result);
8312 /* if it is only one byte then */
8315 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8317 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8318 emitcode ("", "%05d$:", tlbl->key + 100);
8320 emitcode ("rrc", "a");
8321 emitcode ("", "%05d$:", tlbl1->key + 100);
8322 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8323 aopPut (AOP (result), "a", 0);
8327 reAdjustPreg (AOP (result));
8328 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8329 emitcode ("", "%05d$:", tlbl->key + 100);
8331 _startLazyDPSEvaluation ();
8334 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8336 emitcode ("rrc", "a");
8337 aopPut (AOP (result), "a", offset--);
8339 _endLazyDPSEvaluation ();
8340 reAdjustPreg (AOP (result));
8342 emitcode ("", "%05d$:", tlbl1->key + 100);
8343 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8346 freeAsmop (left, NULL, ic, TRUE);
8347 freeAsmop (result, NULL, ic, TRUE);
8350 /*-----------------------------------------------------------------*/
8351 /* genUnpackBits - generates code for unpacking bits */
8352 /*-----------------------------------------------------------------*/
8354 genUnpackBits (operand * result, char *rname, int ptype)
8361 D (emitcode (";", "genUnpackBits ");
8364 etype = getSpec (operandType (result));
8366 /* read the first byte */
8372 emitcode ("mov", "a,@%s", rname);
8376 emitcode ("movx", "a,@%s", rname);
8380 emitcode ("movx", "a,@dptr");
8384 emitcode ("clr", "a");
8385 emitcode ("movc", "a,@a+dptr");
8389 emitcode ("lcall", "__gptrget");
8393 /* if we have bitdisplacement then it fits */
8394 /* into this byte completely or if length is */
8395 /* less than a byte */
8396 if ((shCnt = SPEC_BSTR (etype)) ||
8397 (SPEC_BLEN (etype) <= 8))
8400 /* shift right acc */
8403 emitcode ("anl", "a,#0x%02x",
8404 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8405 aopPut (AOP (result), "a", offset);
8409 /* bit field did not fit in a byte */
8410 rlen = SPEC_BLEN (etype) - 8;
8411 aopPut (AOP (result), "a", offset++);
8420 emitcode ("inc", "%s", rname);
8421 emitcode ("mov", "a,@%s", rname);
8425 emitcode ("inc", "%s", rname);
8426 emitcode ("movx", "a,@%s", rname);
8430 emitcode ("inc", "dptr");
8431 emitcode ("movx", "a,@dptr");
8435 emitcode ("clr", "a");
8436 emitcode ("inc", "dptr");
8437 emitcode ("movc", "a,@a+dptr");
8441 emitcode ("inc", "dptr");
8442 emitcode ("lcall", "__gptrget");
8447 /* if we are done */
8451 aopPut (AOP (result), "a", offset++);
8457 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
8458 aopPut (AOP (result), "a", offset);
8465 /*-----------------------------------------------------------------*/
8466 /* genDataPointerGet - generates code when ptr offset is known */
8467 /*-----------------------------------------------------------------*/
8469 genDataPointerGet (operand * left,
8475 int size, offset = 0;
8476 aopOp (result, ic, TRUE, FALSE);
8478 /* get the string representation of the name */
8479 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8480 size = AOP_SIZE (result);
8481 _startLazyDPSEvaluation ();
8485 sprintf (buffer, "(%s + %d)", l + 1, offset);
8487 sprintf (buffer, "%s", l + 1);
8488 aopPut (AOP (result), buffer, offset++);
8490 _endLazyDPSEvaluation ();
8492 freeAsmop (left, NULL, ic, TRUE);
8493 freeAsmop (result, NULL, ic, TRUE);
8496 /*-----------------------------------------------------------------*/
8497 /* genNearPointerGet - emitcode for near pointer fetch */
8498 /*-----------------------------------------------------------------*/
8500 genNearPointerGet (operand * left,
8507 sym_link *rtype, *retype, *letype;
8508 sym_link *ltype = operandType (left);
8511 rtype = operandType (result);
8512 retype = getSpec (rtype);
8513 letype = getSpec (ltype);
8515 aopOp (left, ic, FALSE, FALSE);
8517 /* if left is rematerialisable and
8518 result is not bit variable type and
8519 the left is pointer to data space i.e
8520 lower 128 bytes of space */
8521 if (AOP_TYPE (left) == AOP_IMMD &&
8522 !IS_BITVAR (retype) &&
8523 !IS_BITVAR (letype) &&
8524 DCL_TYPE (ltype) == POINTER)
8526 genDataPointerGet (left, result, ic);
8530 /* if the value is already in a pointer register
8531 then don't need anything more */
8532 if (!AOP_INPREG (AOP (left)))
8534 /* otherwise get a free pointer register */
8536 preg = getFreePtr (ic, &aop, FALSE);
8537 emitcode ("mov", "%s,%s",
8539 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8543 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8545 freeAsmop (left, NULL, ic, TRUE);
8546 aopOp (result, ic, FALSE, FALSE);
8548 /* if bitfield then unpack the bits */
8549 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8550 genUnpackBits (result, rname, POINTER);
8553 /* we have can just get the values */
8554 int size = AOP_SIZE (result);
8559 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8562 emitcode ("mov", "a,@%s", rname);
8563 aopPut (AOP (result), "a", offset);
8567 sprintf (buffer, "@%s", rname);
8568 aopPut (AOP (result), buffer, offset);
8572 emitcode ("inc", "%s", rname);
8576 /* now some housekeeping stuff */
8579 /* we had to allocate for this iCode */
8580 freeAsmop (NULL, aop, ic, TRUE);
8584 /* we did not allocate which means left
8585 already in a pointer register, then
8586 if size > 0 && this could be used again
8587 we have to point it back to where it
8589 if (AOP_SIZE (result) > 1 &&
8590 !OP_SYMBOL (left)->remat &&
8591 (OP_SYMBOL (left)->liveTo > ic->seq ||
8594 int size = AOP_SIZE (result) - 1;
8596 emitcode ("dec", "%s", rname);
8601 freeAsmop (result, NULL, ic, TRUE);
8605 /*-----------------------------------------------------------------*/
8606 /* genPagedPointerGet - emitcode for paged pointer fetch */
8607 /*-----------------------------------------------------------------*/
8609 genPagedPointerGet (operand * left,
8616 sym_link *rtype, *retype, *letype;
8618 rtype = operandType (result);
8619 retype = getSpec (rtype);
8620 letype = getSpec (operandType (left));
8621 aopOp (left, ic, FALSE, FALSE);
8623 /* if the value is already in a pointer register
8624 then don't need anything more */
8625 if (!AOP_INPREG (AOP (left)))
8627 /* otherwise get a free pointer register */
8629 preg = getFreePtr (ic, &aop, FALSE);
8630 emitcode ("mov", "%s,%s",
8632 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8636 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8638 freeAsmop (left, NULL, ic, TRUE);
8639 aopOp (result, ic, FALSE, FALSE);
8641 /* if bitfield then unpack the bits */
8642 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8643 genUnpackBits (result, rname, PPOINTER);
8646 /* we have can just get the values */
8647 int size = AOP_SIZE (result);
8653 emitcode ("movx", "a,@%s", rname);
8654 aopPut (AOP (result), "a", offset);
8659 emitcode ("inc", "%s", rname);
8663 /* now some housekeeping stuff */
8666 /* we had to allocate for this iCode */
8667 freeAsmop (NULL, aop, ic, TRUE);
8671 /* we did not allocate which means left
8672 already in a pointer register, then
8673 if size > 0 && this could be used again
8674 we have to point it back to where it
8676 if (AOP_SIZE (result) > 1 &&
8677 !OP_SYMBOL (left)->remat &&
8678 (OP_SYMBOL (left)->liveTo > ic->seq ||
8681 int size = AOP_SIZE (result) - 1;
8683 emitcode ("dec", "%s", rname);
8688 freeAsmop (result, NULL, ic, TRUE);
8693 /*-----------------------------------------------------------------*/
8694 /* genFarPointerGet - gget value from far space */
8695 /*-----------------------------------------------------------------*/
8697 genFarPointerGet (operand * left,
8698 operand * result, iCode * ic)
8701 sym_link *retype = getSpec (operandType (result));
8702 sym_link *letype = getSpec (operandType (left));
8703 D (emitcode (";", "genFarPointerGet");
8706 aopOp (left, ic, FALSE, FALSE);
8708 /* if the operand is already in dptr
8709 then we do nothing else we move the value to dptr */
8710 if (AOP_TYPE (left) != AOP_STR)
8712 /* if this is remateriazable */
8713 if (AOP_TYPE (left) == AOP_IMMD)
8715 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8719 /* we need to get it byte by byte */
8720 _startLazyDPSEvaluation ();
8721 if (AOP_TYPE (left) != AOP_DPTR)
8723 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8724 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8725 if (options.model == MODEL_FLAT24)
8726 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8730 /* We need to generate a load to DPTR indirect through DPTR. */
8731 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8733 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8734 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8735 if (options.model == MODEL_FLAT24)
8736 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8737 emitcode ("pop", "dph");
8738 emitcode ("pop", "dpl");
8740 _endLazyDPSEvaluation ();
8743 /* so dptr know contains the address */
8744 freeAsmop (left, NULL, ic, TRUE);
8745 aopOp (result, ic, FALSE, TRUE);
8747 /* if bit then unpack */
8748 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8749 genUnpackBits (result, "dptr", FPOINTER);
8752 size = AOP_SIZE (result);
8755 _startLazyDPSEvaluation ();
8762 emitcode ("movx", "a,@dptr");
8764 emitcode ("inc", "dptr");
8766 aopPut (AOP (result), "a", offset++);
8768 _endLazyDPSEvaluation ();
8771 freeAsmop (result, NULL, ic, TRUE);
8774 /*-----------------------------------------------------------------*/
8775 /* emitcodePointerGet - gget value from code space */
8776 /*-----------------------------------------------------------------*/
8778 emitcodePointerGet (operand * left,
8779 operand * result, iCode * ic)
8782 sym_link *retype = getSpec (operandType (result));
8784 aopOp (left, ic, FALSE, FALSE);
8786 /* if the operand is already in dptr
8787 then we do nothing else we move the value to dptr */
8788 if (AOP_TYPE (left) != AOP_STR)
8790 /* if this is remateriazable */
8791 if (AOP_TYPE (left) == AOP_IMMD)
8793 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8796 { /* we need to get it byte by byte */
8797 _startLazyDPSEvaluation ();
8798 if (AOP_TYPE (left) != AOP_DPTR)
8800 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8801 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8802 if (options.model == MODEL_FLAT24)
8803 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8807 /* We need to generate a load to DPTR indirect through DPTR. */
8808 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8810 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8811 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8812 if (options.model == MODEL_FLAT24)
8813 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8814 emitcode ("pop", "dph");
8815 emitcode ("pop", "dpl");
8817 _endLazyDPSEvaluation ();
8820 /* so dptr know contains the address */
8821 freeAsmop (left, NULL, ic, TRUE);
8822 aopOp (result, ic, FALSE, TRUE);
8824 /* if bit then unpack */
8825 if (IS_BITVAR (retype))
8826 genUnpackBits (result, "dptr", CPOINTER);
8829 size = AOP_SIZE (result);
8832 _startLazyDPSEvaluation ();
8838 emitcode ("clr", "a");
8839 emitcode ("movc", "a,@a+dptr");
8841 emitcode ("inc", "dptr");
8842 aopPut (AOP (result), "a", offset++);
8844 _endLazyDPSEvaluation ();
8847 freeAsmop (result, NULL, ic, TRUE);
8850 /*-----------------------------------------------------------------*/
8851 /* genGenPointerGet - gget value from generic pointer space */
8852 /*-----------------------------------------------------------------*/
8854 genGenPointerGet (operand * left,
8855 operand * result, iCode * ic)
8858 sym_link *retype = getSpec (operandType (result));
8859 sym_link *letype = getSpec (operandType (left));
8861 D (emitcode (";", "genGenPointerGet "); );
8863 aopOp (left, ic, FALSE, TRUE);
8865 /* if the operand is already in dptr
8866 then we do nothing else we move the value to dptr */
8867 if (AOP_TYPE (left) != AOP_STR)
8869 /* if this is remateriazable */
8870 if (AOP_TYPE (left) == AOP_IMMD)
8872 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8873 if (AOP(left)->aopu.aop_immd.from_cast_remat)
8874 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
8876 emitcode ("mov", "b,#%d", pointerCode (retype));
8879 { /* we need to get it byte by byte */
8880 _startLazyDPSEvaluation ();
8881 if (AOP(left)->type==AOP_DPTR2) {
8883 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8886 emitcode ("mov", "dpl,%s", l);
8887 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8890 emitcode ("mov", "dph,%s", l);
8891 if (options.model == MODEL_FLAT24) {
8892 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8895 emitcode ("mov", "dpx,%s", l);
8896 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8898 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8901 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8902 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8903 if (options.model == MODEL_FLAT24) {
8904 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8905 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8907 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8910 _endLazyDPSEvaluation ();
8913 /* so dptr know contains the address */
8914 freeAsmop (left, NULL, ic, TRUE);
8915 aopOp (result, ic, FALSE, TRUE);
8917 /* if bit then unpack */
8918 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8919 genUnpackBits (result, "dptr", GPOINTER);
8922 size = AOP_SIZE (result);
8927 emitcode ("lcall", "__gptrget");
8928 aopPut (AOP (result), "a", offset++);
8930 emitcode ("inc", "dptr");
8934 freeAsmop (result, NULL, ic, TRUE);
8937 /*-----------------------------------------------------------------*/
8938 /* genPointerGet - generate code for pointer get */
8939 /*-----------------------------------------------------------------*/
8941 genPointerGet (iCode * ic)
8943 operand *left, *result;
8944 sym_link *type, *etype;
8947 D (emitcode (";", "genPointerGet ");
8950 left = IC_LEFT (ic);
8951 result = IC_RESULT (ic);
8953 /* depending on the type of pointer we need to
8954 move it to the correct pointer register */
8955 type = operandType (left);
8956 etype = getSpec (type);
8957 /* if left is of type of pointer then it is simple */
8958 if (IS_PTR (type) && !IS_FUNC (type->next))
8959 p_type = DCL_TYPE (type);
8962 /* we have to go by the storage class */
8963 p_type = PTR_TYPE (SPEC_OCLS (etype));
8965 /* special case when cast remat */
8966 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
8967 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
8968 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
8969 type = type = operandType (left);
8970 p_type = DCL_TYPE (type);
8972 /* now that we have the pointer type we assign
8973 the pointer values */
8979 genNearPointerGet (left, result, ic);
8983 genPagedPointerGet (left, result, ic);
8987 genFarPointerGet (left, result, ic);
8991 emitcodePointerGet (left, result, ic);
8995 genGenPointerGet (left, result, ic);
9001 /*-----------------------------------------------------------------*/
9002 /* genPackBits - generates code for packed bit storage */
9003 /*-----------------------------------------------------------------*/
9005 genPackBits (sym_link * etype,
9007 char *rname, int p_type)
9015 blen = SPEC_BLEN (etype);
9016 bstr = SPEC_BSTR (etype);
9018 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9021 /* if the bit lenth is less than or */
9022 /* it exactly fits a byte then */
9023 if (SPEC_BLEN (etype) <= 8)
9025 shCount = SPEC_BSTR (etype);
9027 /* shift left acc */
9030 if (SPEC_BLEN (etype) < 8)
9031 { /* if smaller than a byte */
9037 emitcode ("mov", "b,a");
9038 emitcode ("mov", "a,@%s", rname);
9042 emitcode ("mov", "b,a");
9043 emitcode ("movx", "a,@dptr");
9047 emitcode ("push", "b");
9048 emitcode ("push", "acc");
9049 emitcode ("lcall", "__gptrget");
9050 emitcode ("pop", "b");
9054 emitcode ("anl", "a,#0x%02x", (unsigned char)
9055 ((unsigned char) (0xFF << (blen + bstr)) |
9056 (unsigned char) (0xFF >> (8 - bstr))));
9057 emitcode ("orl", "a,b");
9058 if (p_type == GPOINTER)
9059 emitcode ("pop", "b");
9066 emitcode ("mov", "@%s,a", rname);
9070 emitcode ("movx", "@dptr,a");
9074 emitcode ("lcall", "__gptrput");
9079 if (SPEC_BLEN (etype) <= 8)
9082 emitcode ("inc", "%s", rname);
9083 rLen = SPEC_BLEN (etype);
9085 /* now generate for lengths greater than one byte */
9089 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9101 emitcode ("mov", "@%s,a", rname);
9104 emitcode ("mov", "@%s,%s", rname, l);
9109 emitcode ("movx", "@dptr,a");
9114 emitcode ("lcall", "__gptrput");
9117 emitcode ("inc", "%s", rname);
9122 /* last last was not complete */
9125 /* save the byte & read byte */
9129 emitcode ("mov", "b,a");
9130 emitcode ("mov", "a,@%s", rname);
9134 emitcode ("mov", "b,a");
9135 emitcode ("movx", "a,@dptr");
9139 emitcode ("push", "b");
9140 emitcode ("push", "acc");
9141 emitcode ("lcall", "__gptrget");
9142 emitcode ("pop", "b");
9146 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
9147 emitcode ("orl", "a,b");
9150 if (p_type == GPOINTER)
9151 emitcode ("pop", "b");
9157 emitcode ("mov", "@%s,a", rname);
9161 emitcode ("movx", "@dptr,a");
9165 emitcode ("lcall", "__gptrput");
9169 /*-----------------------------------------------------------------*/
9170 /* genDataPointerSet - remat pointer to data space */
9171 /*-----------------------------------------------------------------*/
9173 genDataPointerSet (operand * right,
9177 int size, offset = 0;
9178 char *l, buffer[256];
9180 aopOp (right, ic, FALSE, FALSE);
9182 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9183 size = AOP_SIZE (right);
9187 sprintf (buffer, "(%s + %d)", l + 1, offset);
9189 sprintf (buffer, "%s", l + 1);
9190 emitcode ("mov", "%s,%s", buffer,
9191 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9194 freeAsmop (right, NULL, ic, TRUE);
9195 freeAsmop (result, NULL, ic, TRUE);
9198 /*-----------------------------------------------------------------*/
9199 /* genNearPointerSet - emitcode for near pointer put */
9200 /*-----------------------------------------------------------------*/
9202 genNearPointerSet (operand * right,
9209 sym_link *retype, *letype;
9210 sym_link *ptype = operandType (result);
9212 retype = getSpec (operandType (right));
9213 letype = getSpec (ptype);
9215 aopOp (result, ic, FALSE, FALSE);
9217 /* if the result is rematerializable &
9218 in data space & not a bit variable */
9219 if (AOP_TYPE (result) == AOP_IMMD &&
9220 DCL_TYPE (ptype) == POINTER &&
9221 !IS_BITVAR (retype) &&
9222 !IS_BITVAR (letype))
9224 genDataPointerSet (right, result, ic);
9228 /* if the value is already in a pointer register
9229 then don't need anything more */
9230 if (!AOP_INPREG (AOP (result)))
9232 /* otherwise get a free pointer register */
9234 preg = getFreePtr (ic, &aop, FALSE);
9235 emitcode ("mov", "%s,%s",
9237 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9241 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9243 freeAsmop (result, NULL, ic, TRUE);
9244 aopOp (right, ic, FALSE, FALSE);
9246 /* if bitfield then unpack the bits */
9247 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9248 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9251 /* we have can just get the values */
9252 int size = AOP_SIZE (right);
9257 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9261 emitcode ("mov", "@%s,a", rname);
9264 emitcode ("mov", "@%s,%s", rname, l);
9266 emitcode ("inc", "%s", rname);
9271 /* now some housekeeping stuff */
9274 /* we had to allocate for this iCode */
9275 freeAsmop (NULL, aop, ic, TRUE);
9279 /* we did not allocate which means left
9280 already in a pointer register, then
9281 if size > 0 && this could be used again
9282 we have to point it back to where it
9284 if (AOP_SIZE (right) > 1 &&
9285 !OP_SYMBOL (result)->remat &&
9286 (OP_SYMBOL (result)->liveTo > ic->seq ||
9289 int size = AOP_SIZE (right) - 1;
9291 emitcode ("dec", "%s", rname);
9296 freeAsmop (right, NULL, ic, TRUE);
9301 /*-----------------------------------------------------------------*/
9302 /* genPagedPointerSet - emitcode for Paged pointer put */
9303 /*-----------------------------------------------------------------*/
9305 genPagedPointerSet (operand * right,
9312 sym_link *retype, *letype;
9314 retype = getSpec (operandType (right));
9315 letype = getSpec (operandType (result));
9317 aopOp (result, ic, FALSE, FALSE);
9319 /* if the value is already in a pointer register
9320 then don't need anything more */
9321 if (!AOP_INPREG (AOP (result)))
9323 /* otherwise get a free pointer register */
9325 preg = getFreePtr (ic, &aop, FALSE);
9326 emitcode ("mov", "%s,%s",
9328 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9332 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9334 freeAsmop (result, NULL, ic, TRUE);
9335 aopOp (right, ic, FALSE, FALSE);
9337 /* if bitfield then unpack the bits */
9338 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9339 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9342 /* we have can just get the values */
9343 int size = AOP_SIZE (right);
9348 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9351 emitcode ("movx", "@%s,a", rname);
9354 emitcode ("inc", "%s", rname);
9360 /* now some housekeeping stuff */
9363 /* we had to allocate for this iCode */
9364 freeAsmop (NULL, aop, ic, TRUE);
9368 /* we did not allocate which means left
9369 already in a pointer register, then
9370 if size > 0 && this could be used again
9371 we have to point it back to where it
9373 if (AOP_SIZE (right) > 1 &&
9374 !OP_SYMBOL (result)->remat &&
9375 (OP_SYMBOL (result)->liveTo > ic->seq ||
9378 int size = AOP_SIZE (right) - 1;
9380 emitcode ("dec", "%s", rname);
9385 freeAsmop (right, NULL, ic, TRUE);
9390 /*-----------------------------------------------------------------*/
9391 /* genFarPointerSet - set value from far space */
9392 /*-----------------------------------------------------------------*/
9394 genFarPointerSet (operand * right,
9395 operand * result, iCode * ic)
9398 sym_link *retype = getSpec (operandType (right));
9399 sym_link *letype = getSpec (operandType (result));
9401 aopOp (result, ic, FALSE, FALSE);
9403 /* if the operand is already in dptr
9404 then we do nothing else we move the value to dptr */
9405 if (AOP_TYPE (result) != AOP_STR)
9407 /* if this is remateriazable */
9408 if (AOP_TYPE (result) == AOP_IMMD)
9409 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9412 /* we need to get it byte by byte */
9413 _startLazyDPSEvaluation ();
9414 if (AOP_TYPE (result) != AOP_DPTR)
9416 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9417 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9418 if (options.model == MODEL_FLAT24)
9419 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9423 /* We need to generate a load to DPTR indirect through DPTR. */
9424 D (emitcode (";", "genFarPointerSet -- indirection special case.");
9426 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9427 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9428 if (options.model == MODEL_FLAT24)
9429 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9430 emitcode ("pop", "dph");
9431 emitcode ("pop", "dpl");
9433 _endLazyDPSEvaluation ();
9436 /* so dptr know contains the address */
9437 freeAsmop (result, NULL, ic, TRUE);
9438 aopOp (right, ic, FALSE, TRUE);
9440 /* if bit then unpack */
9441 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9442 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9445 size = AOP_SIZE (right);
9448 _startLazyDPSEvaluation ();
9451 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9457 emitcode ("movx", "@dptr,a");
9459 emitcode ("inc", "dptr");
9461 _endLazyDPSEvaluation ();
9464 freeAsmop (right, NULL, ic, TRUE);
9467 /*-----------------------------------------------------------------*/
9468 /* genGenPointerSet - set value from generic pointer space */
9469 /*-----------------------------------------------------------------*/
9471 genGenPointerSet (operand * right,
9472 operand * result, iCode * ic)
9475 sym_link *retype = getSpec (operandType (right));
9476 sym_link *letype = getSpec (operandType (result));
9478 aopOp (result, ic, FALSE, TRUE);
9480 /* if the operand is already in dptr
9481 then we do nothing else we move the value to dptr */
9482 if (AOP_TYPE (result) != AOP_STR)
9484 _startLazyDPSEvaluation ();
9485 /* if this is remateriazable */
9486 if (AOP_TYPE (result) == AOP_IMMD)
9488 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9489 if (AOP(result)->aopu.aop_immd.from_cast_remat)
9490 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
9492 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9495 { /* we need to get it byte by byte */
9496 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9497 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9498 if (options.model == MODEL_FLAT24) {
9499 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9500 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9502 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9505 _endLazyDPSEvaluation ();
9507 /* so dptr know contains the address */
9508 freeAsmop (result, NULL, ic, TRUE);
9509 aopOp (right, ic, FALSE, TRUE);
9511 /* if bit then unpack */
9512 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9513 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9516 size = AOP_SIZE (right);
9519 _startLazyDPSEvaluation ();
9522 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9528 emitcode ("lcall", "__gptrput");
9530 emitcode ("inc", "dptr");
9532 _endLazyDPSEvaluation ();
9535 freeAsmop (right, NULL, ic, TRUE);
9538 /*-----------------------------------------------------------------*/
9539 /* genPointerSet - stores the value into a pointer location */
9540 /*-----------------------------------------------------------------*/
9542 genPointerSet (iCode * ic)
9544 operand *right, *result;
9545 sym_link *type, *etype;
9548 D (emitcode (";", "genPointerSet ");
9551 right = IC_RIGHT (ic);
9552 result = IC_RESULT (ic);
9554 /* depending on the type of pointer we need to
9555 move it to the correct pointer register */
9556 type = operandType (result);
9557 etype = getSpec (type);
9558 /* if left is of type of pointer then it is simple */
9559 if (IS_PTR (type) && !IS_FUNC (type->next))
9561 p_type = DCL_TYPE (type);
9565 /* we have to go by the storage class */
9566 p_type = PTR_TYPE (SPEC_OCLS (etype));
9568 /* special case when cast remat */
9569 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9570 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9571 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9572 type = type = operandType (result);
9573 p_type = DCL_TYPE (type);
9576 /* now that we have the pointer type we assign
9577 the pointer values */
9583 genNearPointerSet (right, result, ic);
9587 genPagedPointerSet (right, result, ic);
9591 genFarPointerSet (right, result, ic);
9595 genGenPointerSet (right, result, ic);
9601 /*-----------------------------------------------------------------*/
9602 /* genIfx - generate code for Ifx statement */
9603 /*-----------------------------------------------------------------*/
9605 genIfx (iCode * ic, iCode * popIc)
9607 operand *cond = IC_COND (ic);
9610 D (emitcode (";", "genIfx "););
9612 aopOp (cond, ic, FALSE, FALSE);
9614 /* get the value into acc */
9615 if (AOP_TYPE (cond) != AOP_CRY)
9619 /* the result is now in the accumulator */
9620 freeAsmop (cond, NULL, ic, TRUE);
9622 /* if there was something to be popped then do it */
9626 /* if the condition is a bit variable */
9627 if (isbit && IS_ITEMP (cond) &&
9629 genIfxJump (ic, SPIL_LOC (cond)->rname);
9630 else if (isbit && !IS_ITEMP (cond))
9631 genIfxJump (ic, OP_SYMBOL (cond)->rname);
9633 genIfxJump (ic, "a");
9638 /*-----------------------------------------------------------------*/
9639 /* genAddrOf - generates code for address of */
9640 /*-----------------------------------------------------------------*/
9642 genAddrOf (iCode * ic)
9644 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9647 D (emitcode (";", "genAddrOf ");
9650 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9652 /* if the operand is on the stack then we
9653 need to get the stack offset of this
9657 /* if it has an offset then we need to compute
9661 emitcode ("mov", "a,_bp");
9662 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9663 aopPut (AOP (IC_RESULT (ic)), "a", 0);
9667 /* we can just move _bp */
9668 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9670 /* fill the result with zero */
9671 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9674 if (options.stack10bit && size < (FPTRSIZE - 1))
9677 "*** warning: pointer to stack var truncated.\n");
9684 if (options.stack10bit && offset == 2)
9686 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
9690 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9697 /* object not on stack then we need the name */
9698 size = AOP_SIZE (IC_RESULT (ic));
9703 char s[SDCC_NAME_MAX];
9705 sprintf (s, "#(%s >> %d)",
9709 sprintf (s, "#%s", sym->rname);
9710 aopPut (AOP (IC_RESULT (ic)), s, offset++);
9714 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9718 /*-----------------------------------------------------------------*/
9719 /* genArrayInit - generates code for address of */
9720 /*-----------------------------------------------------------------*/
9722 genArrayInit (iCode * ic)
9726 int elementSize = 0, eIndex;
9727 unsigned val, lastVal;
9729 operand *left=IC_LEFT(ic);
9731 D (emitcode (";", "genArrayInit "););
9733 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
9735 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
9737 // Load immediate value into DPTR.
9738 emitcode("mov", "dptr, %s",
9739 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
9741 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
9744 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9745 "Unexpected operand to genArrayInit.\n");
9748 // a regression because of SDCCcse.c:1.52
9749 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9750 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9751 if (options.model == MODEL_FLAT24)
9752 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9756 type = operandType(IC_LEFT(ic));
9758 if (type && type->next)
9760 elementSize = getSize(type->next);
9764 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9765 "can't determine element size in genArrayInit.\n");
9769 iLoop = IC_ARRAYILIST(ic);
9774 bool firstpass = TRUE;
9776 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
9777 iLoop->count, (int)iLoop->literalValue, elementSize);
9783 symbol *tlbl = NULL;
9785 count = ix > 256 ? 256 : ix;
9789 tlbl = newiTempLabel (NULL);
9790 if (firstpass || (count & 0xff))
9792 emitcode("mov", "b, #0x%x", count & 0xff);
9795 emitcode ("", "%05d$:", tlbl->key + 100);
9800 for (eIndex = 0; eIndex < elementSize; eIndex++)
9802 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
9805 emitcode("mov", "a, #0x%x", val);
9809 emitcode("movx", "@dptr, a");
9810 emitcode("inc", "dptr");
9815 emitcode("djnz", "b, %05d$", tlbl->key + 100);
9821 iLoop = iLoop->next;
9824 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
9827 /*-----------------------------------------------------------------*/
9828 /* genFarFarAssign - assignment when both are in far space */
9829 /*-----------------------------------------------------------------*/
9831 genFarFarAssign (operand * result, operand * right, iCode * ic)
9833 int size = AOP_SIZE (right);
9835 symbol *rSym = NULL;
9839 /* quick & easy case. */
9840 D(emitcode(";","genFarFarAssign (1 byte case)"););
9841 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9842 freeAsmop (right, NULL, ic, FALSE);
9843 /* now assign DPTR to result */
9845 aopOp(result, ic, FALSE, FALSE);
9847 aopPut(AOP(result), "a", 0);
9848 freeAsmop(result, NULL, ic, FALSE);
9852 /* See if we've got an underlying symbol to abuse. */
9853 if (IS_SYMOP(result) && OP_SYMBOL(result))
9855 if (IS_TRUE_SYMOP(result))
9857 rSym = OP_SYMBOL(result);
9859 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9861 rSym = OP_SYMBOL(result)->usl.spillLoc;
9865 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9867 /* We can use the '390 auto-toggle feature to good effect here. */
9869 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
9870 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
9871 emitcode ("mov", "dptr,#%s", rSym->rname);
9872 /* DP2 = result, DP1 = right, DP1 is current. */
9875 emitcode("movx", "a,@dptr");
9876 emitcode("movx", "@dptr,a");
9879 emitcode("inc", "dptr");
9880 emitcode("inc", "dptr");
9883 emitcode("mov", "dps, #0");
9884 freeAsmop (right, NULL, ic, FALSE);
9886 some alternative code for processors without auto-toggle
9887 no time to test now, so later well put in...kpb
9888 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
9889 emitcode("mov", "dps, #0x01"); /* Select DPTR2. */
9890 emitcode ("mov", "dptr,#%s", rSym->rname);
9891 /* DP2 = result, DP1 = right, DP1 is current. */
9895 emitcode("movx", "a,@dptr");
9897 emitcode("inc", "dptr");
9898 emitcode("inc", "dps");
9899 emitcode("movx", "@dptr,a");
9901 emitcode("inc", "dptr");
9902 emitcode("inc", "dps");
9904 emitcode("mov", "dps, #0");
9905 freeAsmop (right, NULL, ic, FALSE);
9910 D (emitcode (";", "genFarFarAssign"););
9911 aopOp (result, ic, TRUE, TRUE);
9913 _startLazyDPSEvaluation ();
9917 aopPut (AOP (result),
9918 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9921 _endLazyDPSEvaluation ();
9922 freeAsmop (result, NULL, ic, FALSE);
9923 freeAsmop (right, NULL, ic, FALSE);
9927 /*-----------------------------------------------------------------*/
9928 /* genAssign - generate code for assignment */
9929 /*-----------------------------------------------------------------*/
9931 genAssign (iCode * ic)
9933 operand *result, *right;
9935 unsigned long lit = 0L;
9937 D (emitcode (";", "genAssign ");
9940 result = IC_RESULT (ic);
9941 right = IC_RIGHT (ic);
9943 /* if they are the same */
9944 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9947 aopOp (right, ic, FALSE, FALSE);
9949 emitcode (";", "genAssign: resultIsFar = %s",
9950 isOperandInFarSpace (result) ?
9953 /* special case both in far space */
9954 if ((AOP_TYPE (right) == AOP_DPTR ||
9955 AOP_TYPE (right) == AOP_DPTR2) &&
9956 /* IS_TRUE_SYMOP(result) && */
9957 isOperandInFarSpace (result))
9959 genFarFarAssign (result, right, ic);
9963 aopOp (result, ic, TRUE, FALSE);
9965 /* if they are the same registers */
9966 if (sameRegs (AOP (right), AOP (result)))
9969 /* if the result is a bit */
9970 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
9972 /* if the right size is a literal then
9973 we know what the value is */
9974 if (AOP_TYPE (right) == AOP_LIT)
9976 if (((int) operandLitValue (right)))
9977 aopPut (AOP (result), one, 0);
9979 aopPut (AOP (result), zero, 0);
9983 /* the right is also a bit variable */
9984 if (AOP_TYPE (right) == AOP_CRY)
9986 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9987 aopPut (AOP (result), "c", 0);
9993 aopPut (AOP (result), "a", 0);
9997 /* bit variables done */
9999 size = AOP_SIZE (result);
10001 if (AOP_TYPE (right) == AOP_LIT)
10002 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10005 (AOP_TYPE (result) != AOP_REG) &&
10006 (AOP_TYPE (right) == AOP_LIT) &&
10007 !IS_FLOAT (operandType (right)))
10009 _startLazyDPSEvaluation ();
10010 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10012 aopPut (AOP (result),
10013 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10018 /* And now fill the rest with zeros. */
10021 emitcode ("clr", "a");
10025 aopPut (AOP (result), "a", offset++);
10027 _endLazyDPSEvaluation ();
10031 _startLazyDPSEvaluation ();
10034 aopPut (AOP (result),
10035 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10039 _endLazyDPSEvaluation ();
10043 freeAsmop (right, NULL, ic, FALSE);
10044 freeAsmop (result, NULL, ic, TRUE);
10047 /*-----------------------------------------------------------------*/
10048 /* genJumpTab - generates code for jump table */
10049 /*-----------------------------------------------------------------*/
10051 genJumpTab (iCode * ic)
10056 D (emitcode (";", "genJumpTab ");
10059 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10060 /* get the condition into accumulator */
10061 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10063 /* multiply by four! */
10064 emitcode ("add", "a,acc");
10065 emitcode ("add", "a,acc");
10066 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10068 jtab = newiTempLabel (NULL);
10069 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10070 emitcode ("jmp", "@a+dptr");
10071 emitcode ("", "%05d$:", jtab->key + 100);
10072 /* now generate the jump labels */
10073 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10074 jtab = setNextItem (IC_JTLABELS (ic)))
10075 emitcode ("ljmp", "%05d$", jtab->key + 100);
10079 /*-----------------------------------------------------------------*/
10080 /* genCast - gen code for casting */
10081 /*-----------------------------------------------------------------*/
10083 genCast (iCode * ic)
10085 operand *result = IC_RESULT (ic);
10086 sym_link *ctype = operandType (IC_LEFT (ic));
10087 sym_link *rtype = operandType (IC_RIGHT (ic));
10088 operand *right = IC_RIGHT (ic);
10091 D (emitcode (";", "genCast ");
10094 /* if they are equivalent then do nothing */
10095 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10098 aopOp (right, ic, FALSE, FALSE);
10099 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10101 /* if the result is a bit */
10102 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10103 if (IS_BITVAR(OP_SYMBOL(result)->type))
10105 /* if the right size is a literal then
10106 we know what the value is */
10107 if (AOP_TYPE (right) == AOP_LIT)
10109 if (((int) operandLitValue (right)))
10110 aopPut (AOP (result), one, 0);
10112 aopPut (AOP (result), zero, 0);
10117 /* the right is also a bit variable */
10118 if (AOP_TYPE (right) == AOP_CRY)
10120 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10121 aopPut (AOP (result), "c", 0);
10125 /* we need to or */
10127 aopPut (AOP (result), "a", 0);
10131 /* if they are the same size : or less */
10132 if (AOP_SIZE (result) <= AOP_SIZE (right))
10135 /* if they are in the same place */
10136 if (sameRegs (AOP (right), AOP (result)))
10139 /* if they in different places then copy */
10140 size = AOP_SIZE (result);
10142 _startLazyDPSEvaluation ();
10145 aopPut (AOP (result),
10146 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10150 _endLazyDPSEvaluation ();
10155 /* if the result is of type pointer */
10156 if (IS_PTR (ctype))
10160 sym_link *type = operandType (right);
10162 /* pointer to generic pointer */
10163 if (IS_GENPTR (ctype))
10169 p_type = DCL_TYPE (type);
10173 #if OLD_CAST_BEHAVIOR
10174 /* KV: we are converting a non-pointer type to
10175 * a generic pointer. This (ifdef'd out) code
10176 * says that the resulting generic pointer
10177 * should have the same class as the storage
10178 * location of the non-pointer variable.
10180 * For example, converting an int (which happens
10181 * to be stored in DATA space) to a pointer results
10182 * in a DATA generic pointer; if the original int
10183 * in XDATA space, so will be the resulting pointer.
10185 * I don't like that behavior, and thus this change:
10186 * all such conversions will be forced to XDATA and
10187 * throw a warning. If you want some non-XDATA
10188 * type, or you want to suppress the warning, you
10189 * must go through an intermediate cast, like so:
10191 * char _generic *gp = (char _xdata *)(intVar);
10193 sym_link *etype = getSpec (type);
10195 /* we have to go by the storage class */
10196 if (SPEC_OCLS (etype) != generic)
10198 p_type = PTR_TYPE (SPEC_OCLS (etype));
10203 /* Converting unknown class (i.e. register variable)
10204 * to generic pointer. This is not good, but
10205 * we'll make a guess (and throw a warning).
10208 werror (W_INT_TO_GEN_PTR_CAST);
10212 /* the first two bytes are known */
10213 size = GPTRSIZE - 1;
10215 _startLazyDPSEvaluation ();
10218 aopPut (AOP (result),
10219 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10223 _endLazyDPSEvaluation ();
10225 /* the last byte depending on type */
10243 /* this should never happen */
10244 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10245 "got unknown pointer type");
10248 aopPut (AOP (result), l, GPTRSIZE - 1);
10252 /* just copy the pointers */
10253 size = AOP_SIZE (result);
10255 _startLazyDPSEvaluation ();
10258 aopPut (AOP (result),
10259 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10263 _endLazyDPSEvaluation ();
10267 /* so we now know that the size of destination is greater
10268 than the size of the source */
10269 /* we move to result for the size of source */
10270 size = AOP_SIZE (right);
10272 _startLazyDPSEvaluation ();
10275 aopPut (AOP (result),
10276 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10280 _endLazyDPSEvaluation ();
10282 /* now depending on the sign of the source && destination */
10283 size = AOP_SIZE (result) - AOP_SIZE (right);
10284 /* if unsigned or not an integral type */
10285 /* also, if the source is a bit, we don't need to sign extend, because
10286 * it can't possibly have set the sign bit.
10288 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10292 aopPut (AOP (result), zero, offset++);
10297 /* we need to extend the sign :{ */
10298 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10299 FALSE, FALSE, TRUE);
10301 emitcode ("rlc", "a");
10302 emitcode ("subb", "a,acc");
10304 aopPut (AOP (result), "a", offset++);
10307 /* we are done hurray !!!! */
10310 freeAsmop (right, NULL, ic, TRUE);
10311 freeAsmop (result, NULL, ic, TRUE);
10315 /*-----------------------------------------------------------------*/
10316 /* genDjnz - generate decrement & jump if not zero instrucion */
10317 /*-----------------------------------------------------------------*/
10319 genDjnz (iCode * ic, iCode * ifx)
10321 symbol *lbl, *lbl1;
10325 /* if the if condition has a false label
10326 then we cannot save */
10327 if (IC_FALSE (ifx))
10330 /* if the minus is not of the form
10332 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10333 !IS_OP_LITERAL (IC_RIGHT (ic)))
10336 if (operandLitValue (IC_RIGHT (ic)) != 1)
10339 /* if the size of this greater than one then no
10341 if (getSize (operandType (IC_RESULT (ic))) > 1)
10344 /* otherwise we can save BIG */
10345 D(emitcode(";", "genDjnz"););
10347 lbl = newiTempLabel (NULL);
10348 lbl1 = newiTempLabel (NULL);
10350 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10352 if (AOP_NEEDSACC(IC_RESULT(ic)))
10354 /* If the result is accessed indirectly via
10355 * the accumulator, we must explicitly write
10356 * it back after the decrement.
10358 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10360 if (strcmp(rByte, "a"))
10362 /* Something is hopelessly wrong */
10363 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10364 __FILE__, __LINE__);
10365 /* We can just give up; the generated code will be inefficient,
10366 * but what the hey.
10368 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10371 emitcode ("dec", "%s", rByte);
10372 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10373 emitcode ("jnz", "%05d$", lbl->key + 100);
10375 else if (IS_AOP_PREG (IC_RESULT (ic)))
10377 emitcode ("dec", "%s",
10378 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10379 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10380 emitcode ("jnz", "%05d$", lbl->key + 100);
10384 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10387 emitcode ("sjmp", "%05d$", lbl1->key + 100);
10388 emitcode ("", "%05d$:", lbl->key + 100);
10389 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10390 emitcode ("", "%05d$:", lbl1->key + 100);
10392 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10393 ifx->generated = 1;
10397 /*-----------------------------------------------------------------*/
10398 /* genReceive - generate code for a receive iCode */
10399 /*-----------------------------------------------------------------*/
10401 genReceive (iCode * ic)
10404 D (emitcode (";", "genReceive ");
10407 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10408 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10409 IS_TRUE_SYMOP (IC_RESULT (ic))))
10411 int size = getSize (operandType (IC_RESULT (ic)));
10412 int offset = fReturnSizeDS390 - size;
10415 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10416 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10419 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10420 size = AOP_SIZE (IC_RESULT (ic));
10424 emitcode ("pop", "acc");
10425 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10432 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10434 assignResultValue (IC_RESULT (ic));
10437 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10440 /*-----------------------------------------------------------------*/
10441 /* gen390Code - generate code for Dallas 390 based controllers */
10442 /*-----------------------------------------------------------------*/
10444 gen390Code (iCode * lic)
10449 lineHead = lineCurr = NULL;
10451 if (options.model == MODEL_FLAT24) {
10452 fReturnSizeDS390 = 5;
10453 fReturn = fReturn24;
10455 fReturnSizeDS390 = 4;
10456 fReturn = fReturn16;
10457 options.stack10bit=0;
10461 /* print the allocation information */
10463 printAllocInfo (currFunc, codeOutFile);
10465 /* if debug information required */
10466 if (options.debug && currFunc)
10468 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
10470 if (IS_STATIC (currFunc->etype))
10471 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
10473 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
10476 /* stack pointer name */
10477 if (options.useXstack)
10483 for (ic = lic; ic; ic = ic->next)
10486 if (cln != ic->lineno)
10491 emitcode ("", "C$%s$%d$%d$%d ==.",
10492 FileBaseName (ic->filename), ic->lineno,
10493 ic->level, ic->block);
10496 emitcode (";", "%s %d", ic->filename, ic->lineno);
10499 /* if the result is marked as
10500 spilt and rematerializable or code for
10501 this has already been generated then
10503 if (resultRemat (ic) || ic->generated)
10506 /* depending on the operation */
10526 /* IPOP happens only when trying to restore a
10527 spilt live range, if there is an ifx statement
10528 following this pop then the if statement might
10529 be using some of the registers being popped which
10530 would destory the contents of the register so
10531 we need to check for this condition and handle it */
10533 ic->next->op == IFX &&
10534 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10535 genIfx (ic->next, ic);
10553 genEndFunction (ic);
10573 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10590 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10594 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10601 /* note these two are xlated by algebraic equivalence
10602 during parsing SDCC.y */
10603 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10604 "got '>=' or '<=' shouldn't have come here");
10608 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10620 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10624 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10628 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10652 genRightShift (ic);
10655 case GET_VALUE_AT_ADDRESS:
10656 genPointerGet (ic);
10660 if (POINTER_SET (ic))
10661 genPointerSet (ic);
10687 addSet (&_G.sendSet, ic);
10700 /* now we are ready to call the
10701 peep hole optimizer */
10702 if (!options.nopeep)
10703 peepHole (&lineHead);
10705 /* now do the actual printing */
10706 printLine (lineHead, codeOutFile);