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! for operand %s\n",sym->name);
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))->accuse ||
2314 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2315 IS_TRUE_SYMOP (IC_RESULT (ic)))
2317 if (isOperandInFarSpace (IC_RESULT (ic))
2318 && getSize (operandType (IC_RESULT (ic))) <= 2)
2320 int size = getSize (operandType (IC_RESULT (ic)));
2322 /* Special case for 1 or 2 byte return in far space. */
2326 emitcode ("mov", "b,%s", fReturn[1]);
2329 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2330 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2334 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2336 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2341 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2344 assignResultValue (IC_RESULT (ic));
2346 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2350 /* adjust the stack for parameters if
2355 if (ic->parmBytes > 3)
2357 emitcode ("mov", "a,%s", spname);
2358 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2359 emitcode ("mov", "%s,a", spname);
2362 for (i = 0; i < ic->parmBytes; i++)
2363 emitcode ("dec", "%s", spname);
2366 /* if we hade saved some registers then unsave them */
2367 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2368 unsaveRegisters (ic);
2370 /* if register bank was saved then pop them */
2372 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2375 /*-----------------------------------------------------------------*/
2376 /* genPcall - generates a call by pointer statement */
2377 /*-----------------------------------------------------------------*/
2379 genPcall (iCode * ic)
2382 symbol *rlbl = newiTempLabel (NULL);
2383 bool restoreBank=FALSE;
2385 D (emitcode (";", "genPcall ");
2389 /* if caller saves & we have not saved then */
2393 /* if we are calling a function that is not using
2394 the same register bank then we need to save the
2395 destination registers on the stack */
2396 dtype = operandType (IC_LEFT (ic));
2397 if (dtype && !IFFUNC_ISNAKED(dtype) &&
2398 IFFUNC_ISISR (currFunc->type) &&
2399 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2400 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2404 /* push the return address on to the stack */
2405 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2406 emitcode ("push", "acc");
2407 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2408 emitcode ("push", "acc");
2410 if (options.model == MODEL_FLAT24)
2412 emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2413 emitcode ("push", "acc");
2416 /* now push the calling address */
2417 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2419 pushSide (IC_LEFT (ic), FPTRSIZE);
2421 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2423 /* if send set is not empty the assign */
2428 for (sic = setFirstItem (_G.sendSet); sic;
2429 sic = setNextItem (_G.sendSet))
2431 int size, offset = 0;
2433 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2434 size = AOP_SIZE (IC_LEFT (sic));
2435 _startLazyDPSEvaluation ();
2438 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2439 FALSE, FALSE, TRUE);
2440 if (strcmp (l, fReturn[offset]))
2442 emitcode ("mov", "%s,%s",
2448 _endLazyDPSEvaluation ();
2449 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2454 emitcode ("ret", "");
2455 emitcode ("", "%05d$:", (rlbl->key + 100));
2458 /* if we need assign a result value */
2459 if ((IS_ITEMP (IC_RESULT (ic)) &&
2460 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2461 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2462 IS_TRUE_SYMOP (IC_RESULT (ic)))
2466 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2469 assignResultValue (IC_RESULT (ic));
2471 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2474 /* adjust the stack for parameters if
2479 if (ic->parmBytes > 3)
2481 emitcode ("mov", "a,%s", spname);
2482 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2483 emitcode ("mov", "%s,a", spname);
2486 for (i = 0; i < ic->parmBytes; i++)
2487 emitcode ("dec", "%s", spname);
2491 /* if register bank was saved then unsave them */
2493 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2495 /* if we hade saved some registers then
2497 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2498 unsaveRegisters (ic);
2502 /*-----------------------------------------------------------------*/
2503 /* resultRemat - result is rematerializable */
2504 /*-----------------------------------------------------------------*/
2506 resultRemat (iCode * ic)
2508 if (SKIP_IC (ic) || ic->op == IFX)
2511 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2513 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2514 if (sym->remat && !POINTER_SET (ic))
2521 #if defined(__BORLANDC__) || defined(_MSC_VER)
2522 #define STRCASECMP stricmp
2524 #define STRCASECMP strcasecmp
2527 /*-----------------------------------------------------------------*/
2528 /* inExcludeList - return 1 if the string is in exclude Reg list */
2529 /*-----------------------------------------------------------------*/
2531 inExcludeList (char *s)
2535 if (options.excludeRegs[i] &&
2536 STRCASECMP (options.excludeRegs[i], "none") == 0)
2539 for (i = 0; options.excludeRegs[i]; i++)
2541 if (options.excludeRegs[i] &&
2542 STRCASECMP (s, options.excludeRegs[i]) == 0)
2548 /*-----------------------------------------------------------------*/
2549 /* genFunction - generated code for function entry */
2550 /*-----------------------------------------------------------------*/
2552 genFunction (iCode * ic)
2556 bool switchedPSW = FALSE;
2558 D (emitcode (";", "genFunction "););
2561 /* create the function header */
2562 emitcode (";", "-----------------------------------------");
2563 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2564 emitcode (";", "-----------------------------------------");
2566 emitcode ("", "%s:", sym->rname);
2567 ftype = operandType (IC_LEFT (ic));
2569 if (IFFUNC_ISNAKED(ftype))
2571 emitcode(";", "naked function: no prologue.");
2575 /* if critical function then turn interrupts off */
2576 if (IFFUNC_ISCRITICAL (ftype))
2577 emitcode ("clr", "ea");
2579 /* here we need to generate the equates for the
2580 register bank if required */
2581 if (FUNC_REGBANK (ftype) != rbank)
2585 rbank = FUNC_REGBANK (ftype);
2586 for (i = 0; i < ds390_nRegs; i++)
2588 if (regs390[i].print) {
2589 if (strcmp (regs390[i].base, "0") == 0)
2590 emitcode ("", "%s = 0x%02x",
2592 8 * rbank + regs390[i].offset);
2594 emitcode ("", "%s = %s + 0x%02x",
2597 8 * rbank + regs390[i].offset);
2602 /* if this is an interrupt service routine then
2603 save acc, b, dpl, dph */
2604 if (IFFUNC_ISISR (sym->type))
2607 if (!inExcludeList ("acc"))
2608 emitcode ("push", "acc");
2609 if (!inExcludeList ("b"))
2610 emitcode ("push", "b");
2611 if (!inExcludeList ("dpl"))
2612 emitcode ("push", "dpl");
2613 if (!inExcludeList ("dph"))
2614 emitcode ("push", "dph");
2615 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2617 emitcode ("push", "dpx");
2618 /* Make sure we're using standard DPTR */
2619 emitcode ("push", "dps");
2620 emitcode ("mov", "dps, #0x00");
2621 if (options.stack10bit)
2623 /* This ISR could conceivably use DPTR2. Better save it. */
2624 emitcode ("push", "dpl1");
2625 emitcode ("push", "dph1");
2626 emitcode ("push", "dpx1");
2627 emitcode ("push", DP2_RESULT_REG);
2630 /* if this isr has no bank i.e. is going to
2631 run with bank 0 , then we need to save more
2633 if (!FUNC_REGBANK (sym->type))
2636 /* if this function does not call any other
2637 function then we can be economical and
2638 save only those registers that are used */
2639 if (!IFFUNC_HASFCALL(sym->type))
2643 /* if any registers used */
2646 /* save the registers used */
2647 for (i = 0; i < sym->regsUsed->size; i++)
2649 if (bitVectBitValue (sym->regsUsed, i) ||
2650 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2651 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2658 /* this function has a function call cannot
2659 determines register usage so we will have to push the
2661 saveRBank (0, ic, FALSE);
2666 /* This ISR uses a non-zero bank.
2668 * We assume that the bank is available for our
2671 * However, if this ISR calls a function which uses some
2672 * other bank, we must save that bank entirely.
2674 unsigned long banksToSave = 0;
2676 if (IFFUNC_HASFCALL(sym->type))
2679 #define MAX_REGISTER_BANKS 4
2684 for (i = ic; i; i = i->next)
2686 if (i->op == ENDFUNCTION)
2688 /* we got to the end OK. */
2696 dtype = operandType (IC_LEFT(i));
2698 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2700 /* Mark this bank for saving. */
2701 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2703 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2707 banksToSave |= (1 << FUNC_REGBANK(dtype));
2710 /* And note that we don't need to do it in
2718 /* This is a mess; we have no idea what
2719 * register bank the called function might
2722 * The only thing I can think of to do is
2723 * throw a warning and hope.
2725 werror(W_FUNCPTR_IN_USING_ISR);
2729 if (banksToSave && options.useXstack)
2731 /* Since we aren't passing it an ic,
2732 * saveRBank will assume r0 is available to abuse.
2734 * So switch to our (trashable) bank now, so
2735 * the caller's R0 isn't trashed.
2737 emitcode ("push", "psw");
2738 emitcode ("mov", "psw,#0x%02x",
2739 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2743 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2745 if (banksToSave & (1 << ix))
2747 saveRBank(ix, NULL, FALSE);
2751 // jwk: this needs a closer look
2752 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2757 /* if callee-save to be used for this function
2758 then save the registers being used in this function */
2759 if (IFFUNC_CALLEESAVES(sym->type))
2763 /* if any registers used */
2766 /* save the registers used */
2767 for (i = 0; i < sym->regsUsed->size; i++)
2769 if (bitVectBitValue (sym->regsUsed, i) ||
2770 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2772 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2780 /* set the register bank to the desired value */
2781 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2784 emitcode ("push", "psw");
2785 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2788 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2791 if (options.useXstack)
2793 emitcode ("mov", "r0,%s", spname);
2794 emitcode ("mov", "a,_bp");
2795 emitcode ("movx", "@r0,a");
2796 emitcode ("inc", "%s", spname);
2800 /* set up the stack */
2801 emitcode ("push", "_bp"); /* save the callers stack */
2803 emitcode ("mov", "_bp,%s", spname);
2806 /* adjust the stack for the function */
2812 werror (W_STACK_OVERFLOW, sym->name);
2814 if (i > 3 && sym->recvSize < 4)
2817 emitcode ("mov", "a,sp");
2818 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2819 emitcode ("mov", "sp,a");
2824 emitcode ("inc", "sp");
2830 emitcode ("mov", "a,_spx");
2831 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2832 emitcode ("mov", "_spx,a");
2837 /*-----------------------------------------------------------------*/
2838 /* genEndFunction - generates epilogue for functions */
2839 /*-----------------------------------------------------------------*/
2841 genEndFunction (iCode * ic)
2843 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2845 D (emitcode (";", "genEndFunction "););
2847 if (IFFUNC_ISNAKED(sym->type))
2849 emitcode(";", "naked function: no epilogue.");
2853 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2855 emitcode ("mov", "%s,_bp", spname);
2858 /* if use external stack but some variables were
2859 added to the local stack then decrement the
2861 if (options.useXstack && sym->stack)
2863 emitcode ("mov", "a,sp");
2864 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2865 emitcode ("mov", "sp,a");
2869 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2871 if (options.useXstack)
2873 emitcode ("mov", "r0,%s", spname);
2874 emitcode ("movx", "a,@r0");
2875 emitcode ("mov", "_bp,a");
2876 emitcode ("dec", "%s", spname);
2880 emitcode ("pop", "_bp");
2884 /* restore the register bank */
2885 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2887 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
2888 || !options.useXstack)
2890 /* Special case of ISR using non-zero bank with useXstack
2893 emitcode ("pop", "psw");
2897 if (IFFUNC_ISISR (sym->type))
2900 /* now we need to restore the registers */
2901 /* if this isr has no bank i.e. is going to
2902 run with bank 0 , then we need to save more
2904 if (!FUNC_REGBANK (sym->type))
2906 /* if this function does not call any other
2907 function then we can be economical and
2908 save only those registers that are used */
2909 if (!IFFUNC_HASFCALL(sym->type))
2913 /* if any registers used */
2916 /* save the registers used */
2917 for (i = sym->regsUsed->size; i >= 0; i--)
2919 if (bitVectBitValue (sym->regsUsed, i) ||
2920 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2921 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2928 /* this function has a function call cannot
2929 determines register usage so we will have to pop the
2931 unsaveRBank (0, ic, FALSE);
2936 /* This ISR uses a non-zero bank.
2938 * Restore any register banks saved by genFunction
2941 // jwk: this needs a closer look
2942 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2945 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2947 if (savedBanks & (1 << ix))
2949 unsaveRBank(ix, NULL, FALSE);
2953 if (options.useXstack)
2955 /* Restore bank AFTER calling unsaveRBank,
2956 * since it can trash r0.
2958 emitcode ("pop", "psw");
2962 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2964 if (options.stack10bit)
2966 emitcode ("pop", DP2_RESULT_REG);
2967 emitcode ("pop", "dpx1");
2968 emitcode ("pop", "dph1");
2969 emitcode ("pop", "dpl1");
2971 emitcode ("pop", "dps");
2972 emitcode ("pop", "dpx");
2974 if (!inExcludeList ("dph"))
2975 emitcode ("pop", "dph");
2976 if (!inExcludeList ("dpl"))
2977 emitcode ("pop", "dpl");
2978 if (!inExcludeList ("b"))
2979 emitcode ("pop", "b");
2980 if (!inExcludeList ("acc"))
2981 emitcode ("pop", "acc");
2983 if (IFFUNC_ISCRITICAL (sym->type))
2984 emitcode ("setb", "ea");
2986 /* if debug then send end of function */
2987 if (options.debug && currFunc) {
2989 emitcode ("", "C$%s$%d$%d$%d ==.",
2990 FileBaseName (ic->filename), currFunc->lastLine,
2991 ic->level, ic->block);
2992 if (IS_STATIC (currFunc->etype))
2993 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2995 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2999 emitcode ("reti", "");
3003 if (IFFUNC_ISCRITICAL (sym->type))
3004 emitcode ("setb", "ea");
3006 if (IFFUNC_CALLEESAVES(sym->type))
3010 /* if any registers used */
3013 /* save the registers used */
3014 for (i = sym->regsUsed->size; i >= 0; i--)
3016 if (bitVectBitValue (sym->regsUsed, i) ||
3017 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3018 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3024 /* if debug then send end of function */
3025 if (options.debug && currFunc)
3028 emitcode ("", "C$%s$%d$%d$%d ==.",
3029 FileBaseName (ic->filename), currFunc->lastLine,
3030 ic->level, ic->block);
3031 if (IS_STATIC (currFunc->etype))
3032 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3034 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3038 emitcode ("ret", "");
3043 /*-----------------------------------------------------------------*/
3044 /* genRet - generate code for return statement */
3045 /*-----------------------------------------------------------------*/
3049 int size, offset = 0, pushed = 0;
3051 D (emitcode (";", "genRet ");
3054 /* if we have no return value then
3055 just generate the "ret" */
3059 /* we have something to return then
3060 move the return value into place */
3061 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
3062 size = AOP_SIZE (IC_LEFT (ic));
3064 _startLazyDPSEvaluation ();
3068 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3070 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3071 FALSE, TRUE, FALSE);
3072 emitcode ("push", "%s", l);
3077 /* Since A is the last element of fReturn,
3078 * is is OK to clobber it in the aopGet.
3080 l = aopGet (AOP (IC_LEFT (ic)), offset,
3081 FALSE, FALSE, TRUE);
3082 if (strcmp (fReturn[offset], l))
3083 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3086 _endLazyDPSEvaluation ();
3093 if (strcmp (fReturn[pushed], "a"))
3094 emitcode ("pop", fReturn[pushed]);
3096 emitcode ("pop", "acc");
3099 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3102 /* generate a jump to the return label
3103 if the next is not the return statement */
3104 if (!(ic->next && ic->next->op == LABEL &&
3105 IC_LABEL (ic->next) == returnLabel))
3107 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3111 /*-----------------------------------------------------------------*/
3112 /* genLabel - generates a label */
3113 /*-----------------------------------------------------------------*/
3115 genLabel (iCode * ic)
3117 /* special case never generate */
3118 if (IC_LABEL (ic) == entryLabel)
3121 D (emitcode (";", "genLabel ");
3124 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3127 /*-----------------------------------------------------------------*/
3128 /* genGoto - generates a ljmp */
3129 /*-----------------------------------------------------------------*/
3131 genGoto (iCode * ic)
3133 D (emitcode (";", "genGoto ");
3135 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3138 /*-----------------------------------------------------------------*/
3139 /* findLabelBackwards: walks back through the iCode chain looking */
3140 /* for the given label. Returns number of iCode instructions */
3141 /* between that label and given ic. */
3142 /* Returns zero if label not found. */
3143 /*-----------------------------------------------------------------*/
3145 findLabelBackwards (iCode * ic, int key)
3154 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3156 /* printf("findLabelBackwards = %d\n", count); */
3164 /*-----------------------------------------------------------------*/
3165 /* genPlusIncr :- does addition with increment if possible */
3166 /*-----------------------------------------------------------------*/
3168 genPlusIncr (iCode * ic)
3170 unsigned int icount;
3171 unsigned int size = getDataSize (IC_RESULT (ic));
3173 /* will try to generate an increment */
3174 /* if the right side is not a literal
3176 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3179 /* if the literal value of the right hand side
3180 is greater than 4 then it is not worth it */
3181 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3184 /* if increment 16 bits in register */
3186 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3187 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3188 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3196 /* If the next instruction is a goto and the goto target
3197 * is <= 5 instructions previous to this, we can generate
3198 * jumps straight to that target.
3200 if (ic->next && ic->next->op == GOTO
3201 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3204 emitcode (";", "tail increment optimized (range %d)", labelRange);
3205 tlbl = IC_LABEL (ic->next);
3210 tlbl = newiTempLabel (NULL);
3213 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3214 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3215 IS_AOP_PREG (IC_RESULT (ic)))
3216 emitcode ("cjne", "%s,#0x00,%05d$"
3217 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3221 emitcode ("clr", "a");
3222 emitcode ("cjne", "a,%s,%05d$"
3223 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3227 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3230 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3231 IS_AOP_PREG (IC_RESULT (ic)))
3232 emitcode ("cjne", "%s,#0x00,%05d$"
3233 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3236 emitcode ("cjne", "a,%s,%05d$"
3237 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3240 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3244 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3245 IS_AOP_PREG (IC_RESULT (ic)))
3246 emitcode ("cjne", "%s,#0x00,%05d$"
3247 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3251 emitcode ("cjne", "a,%s,%05d$"
3252 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3255 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3260 emitcode ("", "%05d$:", tlbl->key + 100);
3265 /* if the sizes are greater than 1 then we cannot */
3266 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3267 AOP_SIZE (IC_LEFT (ic)) > 1)
3270 /* we can if the aops of the left & result match or
3271 if they are in registers and the registers are the
3274 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3275 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3276 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3281 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3282 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3283 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3288 _startLazyDPSEvaluation ();
3291 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3293 _endLazyDPSEvaluation ();
3302 /*-----------------------------------------------------------------*/
3303 /* outBitAcc - output a bit in acc */
3304 /*-----------------------------------------------------------------*/
3306 outBitAcc (operand * result)
3308 symbol *tlbl = newiTempLabel (NULL);
3309 /* if the result is a bit */
3310 if (AOP_TYPE (result) == AOP_CRY)
3312 aopPut (AOP (result), "a", 0);
3316 emitcode ("jz", "%05d$", tlbl->key + 100);
3317 emitcode ("mov", "a,%s", one);
3318 emitcode ("", "%05d$:", tlbl->key + 100);
3323 /*-----------------------------------------------------------------*/
3324 /* genPlusBits - generates code for addition of two bits */
3325 /*-----------------------------------------------------------------*/
3327 genPlusBits (iCode * ic)
3329 D (emitcode (";", "genPlusBits ");
3331 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3333 symbol *lbl = newiTempLabel (NULL);
3334 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3335 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3336 emitcode ("cpl", "c");
3337 emitcode ("", "%05d$:", (lbl->key + 100));
3338 outBitC (IC_RESULT (ic));
3342 emitcode ("clr", "a");
3343 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3344 emitcode ("rlc", "a");
3345 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3346 emitcode ("addc", "a,#0x00");
3347 outAcc (IC_RESULT (ic));
3352 adjustArithmeticResult (iCode * ic)
3354 if (opIsGptr (IC_RESULT (ic)) &&
3355 opIsGptr (IC_LEFT (ic)) &&
3356 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3358 aopPut (AOP (IC_RESULT (ic)),
3359 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3363 if (opIsGptr (IC_RESULT (ic)) &&
3364 opIsGptr (IC_RIGHT (ic)) &&
3365 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3367 aopPut (AOP (IC_RESULT (ic)),
3368 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3372 if (opIsGptr (IC_RESULT (ic)) &&
3373 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3374 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3375 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3376 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3379 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3380 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3384 #if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
3385 // Please don't bring it back without a really good reason.
3386 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3387 // (because all three operands are in far space).
3388 #define AOP_OP_3(ic) \
3389 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3390 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3391 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3392 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3393 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3394 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3396 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3398 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3402 // Macro to aopOp all three operands of an ic. If this cannot be done,
3403 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3404 // will be set TRUE. The caller must then handle the case specially, noting
3405 // that the IC_RESULT operand is not aopOp'd.
3406 #define AOP_OP_3_NOFATAL(ic, rc) \
3407 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3408 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3409 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3410 isOperandInFarSpace(IC_RESULT(ic))) \
3412 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3417 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3418 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3420 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3421 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3423 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3425 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3429 // aopOp the left & right operands of an ic.
3430 #define AOP_OP_2(ic) \
3431 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3432 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3434 // convienience macro.
3435 #define AOP_SET_LOCALS(ic) \
3436 left = IC_LEFT(ic); \
3437 right = IC_RIGHT(ic); \
3438 result = IC_RESULT(ic);
3441 // Given an integer value of pushedSize bytes on the stack,
3442 // adjust it to be resultSize bytes, either by discarding
3443 // the most significant bytes or by zero-padding.
3445 // On exit from this macro, pushedSize will have been adjusted to
3446 // equal resultSize, and ACC may be trashed.
3447 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3448 /* If the pushed data is bigger than the result, \
3449 * simply discard unused bytes. Icky, but works. \
3451 while (pushedSize > resultSize) \
3453 D (emitcode (";", "discarding unused result byte."););\
3454 emitcode ("pop", "acc"); \
3457 if (pushedSize < resultSize) \
3459 emitcode ("clr", "a"); \
3460 /* Conversly, we haven't pushed enough here. \
3461 * just zero-pad, and all is well. \
3463 while (pushedSize < resultSize) \
3465 emitcode("push", "acc"); \
3469 assert(pushedSize == resultSize);
3471 /*-----------------------------------------------------------------*/
3472 /* genPlus - generates code for addition */
3473 /*-----------------------------------------------------------------*/
3475 genPlus (iCode * ic)
3477 int size, offset = 0;
3478 bool pushResult = FALSE;
3481 D (emitcode (";", "genPlus "););
3483 /* special cases :- */
3485 AOP_OP_3_NOFATAL (ic, pushResult);
3488 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3493 /* if literal, literal on the right or
3494 if left requires ACC or right is already
3496 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3497 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3498 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3500 operand *t = IC_RIGHT (ic);
3501 IC_RIGHT (ic) = IC_LEFT (ic);
3503 emitcode (";", "Swapped plus args.");
3506 /* if both left & right are in bit
3508 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3509 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3515 /* if left in bit space & right literal */
3516 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3517 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3519 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3520 /* if result in bit space */
3521 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3523 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3524 emitcode ("cpl", "c");
3525 outBitC (IC_RESULT (ic));
3529 size = getDataSize (IC_RESULT (ic));
3530 _startLazyDPSEvaluation ();
3533 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3534 emitcode ("addc", "a,#00");
3535 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3537 _endLazyDPSEvaluation ();
3542 /* if I can do an increment instead
3543 of add then GOOD for ME */
3544 if (genPlusIncr (ic) == TRUE)
3546 emitcode (";", "did genPlusIncr");
3551 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3553 _startLazyDPSEvaluation ();
3556 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3558 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3560 emitcode ("add", "a,%s",
3561 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3563 emitcode ("addc", "a,%s",
3564 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3568 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3570 /* right is going to use ACC or we would have taken the
3573 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3575 D(emitcode(";", "+ AOP_ACC special case."););
3576 emitcode("xch", "a, %s", DP2_RESULT_REG);
3578 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3581 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3584 emitcode("add", "a, %s", DP2_RESULT_REG);
3588 emitcode ("add", "a,%s",
3589 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3594 emitcode ("addc", "a,%s",
3595 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3600 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3604 emitcode ("push", "acc");
3608 _endLazyDPSEvaluation ();
3612 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3614 size = getDataSize (IC_LEFT (ic));
3615 rSize = getDataSize (IC_RESULT (ic));
3617 ADJUST_PUSHED_RESULT(size, rSize);
3619 _startLazyDPSEvaluation ();
3622 emitcode ("pop", "acc");
3623 aopPut (AOP (IC_RESULT (ic)), "a", size);
3625 _endLazyDPSEvaluation ();
3628 adjustArithmeticResult (ic);
3631 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3632 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3633 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3636 /*-----------------------------------------------------------------*/
3637 /* genMinusDec :- does subtraction with deccrement if possible */
3638 /*-----------------------------------------------------------------*/
3640 genMinusDec (iCode * ic)
3642 unsigned int icount;
3643 unsigned int size = getDataSize (IC_RESULT (ic));
3645 /* will try to generate an increment */
3646 /* if the right side is not a literal
3648 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3651 /* if the literal value of the right hand side
3652 is greater than 4 then it is not worth it */
3653 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3656 /* if decrement 16 bits in register */
3657 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3658 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3659 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3667 /* If the next instruction is a goto and the goto target
3668 * is <= 5 instructions previous to this, we can generate
3669 * jumps straight to that target.
3671 if (ic->next && ic->next->op == GOTO
3672 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3675 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3676 tlbl = IC_LABEL (ic->next);
3681 tlbl = newiTempLabel (NULL);
3685 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3686 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3687 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3688 IS_AOP_PREG (IC_RESULT (ic)))
3689 emitcode ("cjne", "%s,#0xff,%05d$"
3690 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3694 emitcode ("mov", "a,#0xff");
3695 emitcode ("cjne", "a,%s,%05d$"
3696 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3699 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3702 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3703 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3704 IS_AOP_PREG (IC_RESULT (ic)))
3705 emitcode ("cjne", "%s,#0xff,%05d$"
3706 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3710 emitcode ("cjne", "a,%s,%05d$"
3711 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3714 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3718 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3719 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3720 IS_AOP_PREG (IC_RESULT (ic)))
3721 emitcode ("cjne", "%s,#0xff,%05d$"
3722 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3726 emitcode ("cjne", "a,%s,%05d$"
3727 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3730 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3734 emitcode ("", "%05d$:", tlbl->key + 100);
3739 /* if the sizes are greater than 1 then we cannot */
3740 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3741 AOP_SIZE (IC_LEFT (ic)) > 1)
3744 /* we can if the aops of the left & result match or
3745 if they are in registers and the registers are the
3748 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3749 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3750 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3753 _startLazyDPSEvaluation ();
3756 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3758 _endLazyDPSEvaluation ();
3766 /*-----------------------------------------------------------------*/
3767 /* addSign - complete with sign */
3768 /*-----------------------------------------------------------------*/
3770 addSign (operand * result, int offset, int sign)
3772 int size = (getDataSize (result) - offset);
3775 _startLazyDPSEvaluation();
3778 emitcode ("rlc", "a");
3779 emitcode ("subb", "a,acc");
3782 aopPut (AOP (result), "a", offset++);
3789 aopPut (AOP (result), zero, offset++);
3792 _endLazyDPSEvaluation();
3796 /*-----------------------------------------------------------------*/
3797 /* genMinusBits - generates code for subtraction of two bits */
3798 /*-----------------------------------------------------------------*/
3800 genMinusBits (iCode * ic)
3802 symbol *lbl = newiTempLabel (NULL);
3804 D (emitcode (";", "genMinusBits "););
3806 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3808 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3809 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3810 emitcode ("cpl", "c");
3811 emitcode ("", "%05d$:", (lbl->key + 100));
3812 outBitC (IC_RESULT (ic));
3816 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3817 emitcode ("subb", "a,acc");
3818 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3819 emitcode ("inc", "a");
3820 emitcode ("", "%05d$:", (lbl->key + 100));
3821 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3822 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3826 /*-----------------------------------------------------------------*/
3827 /* genMinus - generates code for subtraction */
3828 /*-----------------------------------------------------------------*/
3830 genMinus (iCode * ic)
3832 int size, offset = 0;
3834 unsigned long lit = 0L;
3835 bool pushResult = FALSE;
3837 D (emitcode (";", "genMinus "););
3839 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3840 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3841 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3842 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3848 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3850 /* special cases :- */
3851 /* if both left & right are in bit space */
3852 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3853 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3859 /* if I can do an decrement instead
3860 of subtract then GOOD for ME */
3861 if (genMinusDec (ic) == TRUE)
3866 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3868 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3874 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3879 /* if literal, add a,#-lit, else normal subb */
3880 _startLazyDPSEvaluation ();
3883 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3884 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3885 emitcode ("subb", "a,%s",
3886 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3889 /* first add without previous c */
3891 if (!size && lit==-1) {
3892 emitcode ("dec", "a");
3894 emitcode ("add", "a,#0x%02x",
3895 (unsigned int) (lit & 0x0FFL));
3898 emitcode ("addc", "a,#0x%02x",
3899 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3905 emitcode ("push", "acc");
3909 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3913 _endLazyDPSEvaluation ();
3917 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3919 size = getDataSize (IC_LEFT (ic));
3920 rSize = getDataSize (IC_RESULT (ic));
3922 ADJUST_PUSHED_RESULT(size, rSize);
3924 _startLazyDPSEvaluation ();
3927 emitcode ("pop", "acc");
3928 aopPut (AOP (IC_RESULT (ic)), "a", size);
3930 _endLazyDPSEvaluation ();
3933 adjustArithmeticResult (ic);
3936 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3937 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3938 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3942 /*-----------------------------------------------------------------*/
3943 /* genMultbits :- multiplication of bits */
3944 /*-----------------------------------------------------------------*/
3946 genMultbits (operand * left,
3951 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3952 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3953 aopOp(result, ic, TRUE, FALSE);
3958 /*-----------------------------------------------------------------*/
3959 /* genMultOneByte : 8*8=8/16 bit multiplication */
3960 /*-----------------------------------------------------------------*/
3962 genMultOneByte (operand * left,
3967 sym_link *opetype = operandType (result);
3971 /* (if two literals: the value is computed before) */
3972 /* if one literal, literal on the right */
3973 if (AOP_TYPE (left) == AOP_LIT)
3978 emitcode (";", "swapped left and right");
3981 if (SPEC_USIGN(opetype)
3982 // ignore the sign of left and right, what else can we do?
3983 || (SPEC_USIGN(operandType(left)) &&
3984 SPEC_USIGN(operandType(right)))) {
3985 // just an unsigned 8*8=8/16 multiply
3986 //emitcode (";","unsigned");
3987 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3988 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3989 emitcode ("mul", "ab");
3992 aopOp(result, ic, TRUE, FALSE);
3994 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
3996 // this should never happen
3997 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3998 AOP_SIZE(result), __FILE__, lineno);
4002 aopPut (AOP (result), "a", 0);
4004 if (AOP_SIZE(result)==2)
4006 aopPut (AOP (result), "b", 1);
4011 // we have to do a signed multiply
4013 emitcode (";", "signed");
4014 emitcode ("clr", "F0"); // reset sign flag
4015 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4017 lbl=newiTempLabel(NULL);
4018 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
4019 // left side is negative, 8-bit two's complement, this fails for -128
4020 emitcode ("setb", "F0"); // set sign flag
4021 emitcode ("cpl", "a");
4022 emitcode ("inc", "a");
4024 emitcode ("", "%05d$:", lbl->key+100);
4027 if (AOP_TYPE(right)==AOP_LIT) {
4028 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4029 /* AND literal negative */
4030 if ((int) val < 0) {
4031 emitcode ("cpl", "F0"); // complement sign flag
4032 emitcode ("mov", "b,#0x%02x", -val);
4034 emitcode ("mov", "b,#0x%02x", val);
4037 lbl=newiTempLabel(NULL);
4038 emitcode ("mov", "b,a");
4039 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4040 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
4041 // right side is negative, 8-bit two's complement
4042 emitcode ("cpl", "F0"); // complement sign flag
4043 emitcode ("cpl", "a");
4044 emitcode ("inc", "a");
4045 emitcode ("", "%05d$:", lbl->key+100);
4047 emitcode ("mul", "ab");
4050 aopOp(result, ic, TRUE, FALSE);
4052 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4054 // this should never happen
4055 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4056 AOP_SIZE(result), __FILE__, lineno);
4060 lbl=newiTempLabel(NULL);
4061 emitcode ("jnb", "F0,%05d$", lbl->key+100);
4062 // only ONE op was negative, we have to do a 8/16-bit two's complement
4063 emitcode ("cpl", "a"); // lsb
4064 if (AOP_SIZE(result)==1) {
4065 emitcode ("inc", "a");
4067 emitcode ("add", "a,#1");
4068 emitcode ("xch", "a,b");
4069 emitcode ("cpl", "a"); // msb
4070 emitcode ("addc", "a,#0");
4071 emitcode ("xch", "a,b");
4074 emitcode ("", "%05d$:", lbl->key+100);
4075 aopPut (AOP (result), "a", 0);
4077 if (AOP_SIZE(result)==2) {
4078 aopPut (AOP (result), "b", 1);
4082 /*-----------------------------------------------------------------*/
4083 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4084 /*-----------------------------------------------------------------*/
4085 static void genMultTwoByte (operand *left, operand *right,
4086 operand *result, iCode *ic)
4088 sym_link *retype = getSpec(operandType(right));
4089 sym_link *letype = getSpec(operandType(left));
4090 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4093 if (AOP_TYPE (left) == AOP_LIT) {
4098 /* save EA bit in F1 */
4099 lbl = newiTempLabel(NULL);
4100 emitcode ("setb","F1");
4101 emitcode ("jbc","EA,%05d$",lbl->key+100);
4102 emitcode ("clr","F1");
4103 emitcode("","%05d$:",lbl->key+100);
4105 /* load up MB with right */
4107 emitcode("clr","F0");
4108 if (AOP_TYPE(right) == AOP_LIT) {
4109 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4111 emitcode("setb","F0");
4114 emitcode ("mov","mb,#0x%02x",val & 0xff);
4115 emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4117 lbl = newiTempLabel(NULL);
4118 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4119 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4120 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4121 emitcode ("xch", "a,b");
4122 emitcode ("cpl","a");
4123 emitcode ("add", "a,#1");
4124 emitcode ("xch", "a,b");
4125 emitcode ("cpl", "a"); // msb
4126 emitcode ("addc", "a,#0");
4127 emitcode ("setb","F0");
4128 emitcode ("","%05d$:",lbl->key+100);
4129 emitcode ("mov","mb,b");
4130 emitcode ("mov","mb,a");
4133 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4134 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4136 /* load up MA with left */
4138 lbl = newiTempLabel(NULL);
4139 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4140 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4141 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4142 emitcode ("xch", "a,b");
4143 emitcode ("cpl","a");
4144 emitcode ("add", "a,#1");
4145 emitcode ("xch", "a,b");
4146 emitcode ("cpl", "a"); // msb
4147 emitcode ("addc","a,#0");
4148 emitcode ("jbc","F0,%05d$",lbl->key+100);
4149 emitcode ("setb","F0");
4150 emitcode ("","%05d$:",lbl->key+100);
4151 emitcode ("mov","ma,b");
4152 emitcode ("mov","ma,a");
4154 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4155 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4157 /* wait for multiplication to finish */
4158 lbl = newiTempLabel(NULL);
4159 emitcode("","%05d$:", lbl->key+100);
4160 emitcode("mov","a,mcnt1");
4161 emitcode("anl","a,#0x80");
4162 emitcode("jnz","%05d$",lbl->key+100);
4164 freeAsmop (left, NULL, ic, TRUE);
4165 freeAsmop (right, NULL, ic,TRUE);
4166 aopOp(result, ic, TRUE, FALSE);
4168 /* if unsigned then simple */
4170 emitcode ("mov","a,ma");
4171 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4172 emitcode ("mov","a,ma");
4173 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4174 aopPut(AOP(result),"ma",1);
4175 aopPut(AOP(result),"ma",0);
4177 emitcode("push","ma");
4178 emitcode("push","ma");
4179 emitcode("push","ma");
4181 /* negate result if needed */
4182 lbl = newiTempLabel(NULL);
4183 emitcode("jnb","F0,%05d$",lbl->key+100);
4184 emitcode("cpl","a");
4185 emitcode("add","a,#1");
4186 emitcode("","%05d$:", lbl->key+100);
4187 if (AOP_TYPE(result) == AOP_ACC)
4189 D(emitcode(";", "ACC special case."););
4190 /* We know result is the only live aop, and
4191 * it's obviously not a DPTR2, so AP is available.
4193 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4197 aopPut(AOP(result),"a",0);
4200 emitcode("pop","acc");
4201 lbl = newiTempLabel(NULL);
4202 emitcode("jnb","F0,%05d$",lbl->key+100);
4203 emitcode("cpl","a");
4204 emitcode("addc","a,#0");
4205 emitcode("","%05d$:", lbl->key+100);
4206 aopPut(AOP(result),"a",1);
4207 emitcode("pop","acc");
4208 if (AOP_SIZE(result) >= 3) {
4209 lbl = newiTempLabel(NULL);
4210 emitcode("jnb","F0,%05d$",lbl->key+100);
4211 emitcode("cpl","a");
4212 emitcode("addc","a,#0");
4213 emitcode("","%05d$:", lbl->key+100);
4214 aopPut(AOP(result),"a",2);
4216 emitcode("pop","acc");
4217 if (AOP_SIZE(result) >= 4) {
4218 lbl = newiTempLabel(NULL);
4219 emitcode("jnb","F0,%05d$",lbl->key+100);
4220 emitcode("cpl","a");
4221 emitcode("addc","a,#0");
4222 emitcode("","%05d$:", lbl->key+100);
4223 aopPut(AOP(result),"a",3);
4225 if (AOP_TYPE(result) == AOP_ACC)
4227 /* We stashed the result away above. */
4228 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4232 freeAsmop (result, NULL, ic, TRUE);
4234 /* restore EA bit in F1 */
4235 lbl = newiTempLabel(NULL);
4236 emitcode ("jnb","F1,%05d$",lbl->key+100);
4237 emitcode ("setb","EA");
4238 emitcode("","%05d$:",lbl->key+100);
4242 /*-----------------------------------------------------------------*/
4243 /* genMult - generates code for multiplication */
4244 /*-----------------------------------------------------------------*/
4246 genMult (iCode * ic)
4248 operand *left = IC_LEFT (ic);
4249 operand *right = IC_RIGHT (ic);
4250 operand *result = IC_RESULT (ic);
4252 D (emitcode (";", "genMult "););
4254 /* assign the amsops */
4257 /* special cases first */
4259 if (AOP_TYPE (left) == AOP_CRY &&
4260 AOP_TYPE (right) == AOP_CRY)
4262 genMultbits (left, right, result, ic);
4266 /* if both are of size == 1 */
4267 if (AOP_SIZE (left) == 1 &&
4268 AOP_SIZE (right) == 1)
4270 genMultOneByte (left, right, result, ic);
4274 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4275 /* use the ds390 ARITHMETIC accel UNIT */
4276 genMultTwoByte (left, right, result, ic);
4279 /* should have been converted to function call */
4283 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4284 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4285 freeAsmop (result, NULL, ic, TRUE);
4288 /*-----------------------------------------------------------------*/
4289 /* genDivbits :- division of bits */
4290 /*-----------------------------------------------------------------*/
4292 genDivbits (operand * left,
4300 /* the result must be bit */
4301 LOAD_AB_FOR_DIV (left, right, l);
4302 emitcode ("div", "ab");
4303 emitcode ("rrc", "a");
4304 aopOp(result, ic, TRUE, FALSE);
4306 aopPut (AOP (result), "c", 0);
4309 /*-----------------------------------------------------------------*/
4310 /* genDivOneByte : 8 bit division */
4311 /*-----------------------------------------------------------------*/
4313 genDivOneByte (operand * left,
4318 sym_link *opetype = operandType (result);
4324 /* signed or unsigned */
4325 if (SPEC_USIGN (opetype))
4327 /* unsigned is easy */
4328 LOAD_AB_FOR_DIV (left, right, l);
4329 emitcode ("div", "ab");
4332 aopOp(result, ic, TRUE, FALSE);
4333 aopPut (AOP (result), "a", 0);
4336 size = AOP_SIZE (result) - 1;
4340 aopPut (AOP (result), zero, offset++);
4345 /* signed is a little bit more difficult */
4347 /* save the signs of the operands */
4348 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4350 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4351 emitcode ("push", "acc"); /* save it on the stack */
4353 /* now sign adjust for both left & right */
4354 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4356 lbl = newiTempLabel (NULL);
4357 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4358 emitcode ("cpl", "a");
4359 emitcode ("inc", "a");
4360 emitcode ("", "%05d$:", (lbl->key + 100));
4361 emitcode ("mov", "b,a");
4363 /* sign adjust left side */
4364 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4367 lbl = newiTempLabel (NULL);
4368 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4369 emitcode ("cpl", "a");
4370 emitcode ("inc", "a");
4371 emitcode ("", "%05d$:", (lbl->key + 100));
4373 /* now the division */
4374 emitcode ("nop", "; workaround for DS80C390 div bug.");
4375 emitcode ("div", "ab");
4376 /* we are interested in the lower order
4378 emitcode ("mov", "b,a");
4379 lbl = newiTempLabel (NULL);
4380 emitcode ("pop", "acc");
4381 /* if there was an over flow we don't
4382 adjust the sign of the result */
4383 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4384 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4386 emitcode ("clr", "a");
4387 emitcode ("subb", "a,b");
4388 emitcode ("mov", "b,a");
4389 emitcode ("", "%05d$:", (lbl->key + 100));
4391 /* now we are done */
4393 aopOp(result, ic, TRUE, FALSE);
4395 aopPut (AOP (result), "b", 0);
4397 size = AOP_SIZE (result) - 1;
4401 emitcode ("mov", "c,b.7");
4402 emitcode ("subb", "a,acc");
4406 aopPut (AOP (result), "a", offset++);
4412 /*-----------------------------------------------------------------*/
4413 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4414 /*-----------------------------------------------------------------*/
4415 static void genDivTwoByte (operand *left, operand *right,
4416 operand *result, iCode *ic)
4418 sym_link *retype = getSpec(operandType(right));
4419 sym_link *letype = getSpec(operandType(left));
4420 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4423 /* save EA bit in F1 */
4424 lbl = newiTempLabel(NULL);
4425 emitcode ("setb","F1");
4426 emitcode ("jbc","EA,%05d$",lbl->key+100);
4427 emitcode ("clr","F1");
4428 emitcode("","%05d$:",lbl->key+100);
4430 /* load up MA with left */
4432 emitcode("clr","F0");
4433 lbl = newiTempLabel(NULL);
4434 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4435 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4436 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4437 emitcode ("xch", "a,b");
4438 emitcode ("cpl","a");
4439 emitcode ("add", "a,#1");
4440 emitcode ("xch", "a,b");
4441 emitcode ("cpl", "a"); // msb
4442 emitcode ("addc","a,#0");
4443 emitcode ("setb","F0");
4444 emitcode ("","%05d$:",lbl->key+100);
4445 emitcode ("mov","ma,b");
4446 emitcode ("mov","ma,a");
4448 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4449 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4452 /* load up MB with right */
4454 if (AOP_TYPE(right) == AOP_LIT) {
4455 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4457 lbl = newiTempLabel(NULL);
4458 emitcode ("jbc","F0,%05d$",lbl->key+100);
4459 emitcode("setb","F0");
4460 emitcode ("","%05d$:",lbl->key+100);
4463 emitcode ("mov","mb,#0x%02x",val & 0xff);
4464 emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4466 lbl = newiTempLabel(NULL);
4467 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4468 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4469 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4470 emitcode ("xch", "a,b");
4471 emitcode ("cpl","a");
4472 emitcode ("add", "a,#1");
4473 emitcode ("xch", "a,b");
4474 emitcode ("cpl", "a"); // msb
4475 emitcode ("addc", "a,#0");
4476 emitcode ("jbc","F0,%05d$",lbl->key+100);
4477 emitcode ("setb","F0");
4478 emitcode ("","%05d$:",lbl->key+100);
4479 emitcode ("mov","mb,b");
4480 emitcode ("mov","mb,a");
4483 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4484 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4487 /* wait for multiplication to finish */
4488 lbl = newiTempLabel(NULL);
4489 emitcode("","%05d$:", lbl->key+100);
4490 emitcode("mov","a,mcnt1");
4491 emitcode("anl","a,#0x80");
4492 emitcode("jnz","%05d$",lbl->key+100);
4494 freeAsmop (left, NULL, ic, TRUE);
4495 freeAsmop (right, NULL, ic,TRUE);
4496 aopOp(result, ic, TRUE, FALSE);
4498 /* if unsigned then simple */
4500 aopPut(AOP(result),"ma",1);
4501 aopPut(AOP(result),"ma",0);
4503 emitcode("push","ma");
4505 /* negate result if needed */
4506 lbl = newiTempLabel(NULL);
4507 emitcode("jnb","F0,%05d$",lbl->key+100);
4508 emitcode("cpl","a");
4509 emitcode("add","a,#1");
4510 emitcode("","%05d$:", lbl->key+100);
4511 aopPut(AOP(result),"a",0);
4512 emitcode("pop","acc");
4513 lbl = newiTempLabel(NULL);
4514 emitcode("jnb","F0,%05d$",lbl->key+100);
4515 emitcode("cpl","a");
4516 emitcode("addc","a,#0");
4517 emitcode("","%05d$:", lbl->key+100);
4518 aopPut(AOP(result),"a",1);
4520 freeAsmop (result, NULL, ic, TRUE);
4521 /* restore EA bit in F1 */
4522 lbl = newiTempLabel(NULL);
4523 emitcode ("jnb","F1,%05d$",lbl->key+100);
4524 emitcode ("setb","EA");
4525 emitcode("","%05d$:",lbl->key+100);
4529 /*-----------------------------------------------------------------*/
4530 /* genDiv - generates code for division */
4531 /*-----------------------------------------------------------------*/
4535 operand *left = IC_LEFT (ic);
4536 operand *right = IC_RIGHT (ic);
4537 operand *result = IC_RESULT (ic);
4539 D (emitcode (";", "genDiv "););
4541 /* assign the amsops */
4544 /* special cases first */
4546 if (AOP_TYPE (left) == AOP_CRY &&
4547 AOP_TYPE (right) == AOP_CRY)
4549 genDivbits (left, right, result, ic);
4553 /* if both are of size == 1 */
4554 if (AOP_SIZE (left) == 1 &&
4555 AOP_SIZE (right) == 1)
4557 genDivOneByte (left, right, result, ic);
4561 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4562 /* use the ds390 ARITHMETIC accel UNIT */
4563 genDivTwoByte (left, right, result, ic);
4566 /* should have been converted to function call */
4569 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4570 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4571 freeAsmop (result, NULL, ic, TRUE);
4574 /*-----------------------------------------------------------------*/
4575 /* genModbits :- modulus of bits */
4576 /*-----------------------------------------------------------------*/
4578 genModbits (operand * left,
4586 /* the result must be bit */
4587 LOAD_AB_FOR_DIV (left, right, l);
4588 emitcode ("div", "ab");
4589 emitcode ("mov", "a,b");
4590 emitcode ("rrc", "a");
4591 aopOp(result, ic, TRUE, FALSE);
4592 aopPut (AOP (result), "c", 0);
4595 /*-----------------------------------------------------------------*/
4596 /* genModOneByte : 8 bit modulus */
4597 /*-----------------------------------------------------------------*/
4599 genModOneByte (operand * left,
4604 sym_link *opetype = operandType (result);
4608 /* signed or unsigned */
4609 if (SPEC_USIGN (opetype))
4611 /* unsigned is easy */
4612 LOAD_AB_FOR_DIV (left, right, l);
4613 emitcode ("div", "ab");
4614 aopOp(result, ic, TRUE, FALSE);
4615 aopPut (AOP (result), "b", 0);
4619 /* signed is a little bit more difficult */
4621 /* save the signs of the operands */
4622 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4625 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4626 emitcode ("push", "acc"); /* save it on the stack */
4628 /* now sign adjust for both left & right */
4629 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4632 lbl = newiTempLabel (NULL);
4633 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4634 emitcode ("cpl", "a");
4635 emitcode ("inc", "a");
4636 emitcode ("", "%05d$:", (lbl->key + 100));
4637 emitcode ("mov", "b,a");
4639 /* sign adjust left side */
4640 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4643 lbl = newiTempLabel (NULL);
4644 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4645 emitcode ("cpl", "a");
4646 emitcode ("inc", "a");
4647 emitcode ("", "%05d$:", (lbl->key + 100));
4649 /* now the multiplication */
4650 emitcode ("nop", "; workaround for DS80C390 div bug.");
4651 emitcode ("div", "ab");
4652 /* we are interested in the lower order
4654 lbl = newiTempLabel (NULL);
4655 emitcode ("pop", "acc");
4656 /* if there was an over flow we don't
4657 adjust the sign of the result */
4658 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4659 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4661 emitcode ("clr", "a");
4662 emitcode ("subb", "a,b");
4663 emitcode ("mov", "b,a");
4664 emitcode ("", "%05d$:", (lbl->key + 100));
4666 /* now we are done */
4667 aopOp(result, ic, TRUE, FALSE);
4668 aopPut (AOP (result), "b", 0);
4672 /*-----------------------------------------------------------------*/
4673 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
4674 /*-----------------------------------------------------------------*/
4675 static void genModTwoByte (operand *left, operand *right,
4676 operand *result, iCode *ic)
4678 sym_link *retype = getSpec(operandType(right));
4679 sym_link *letype = getSpec(operandType(left));
4680 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4683 /* load up MA with left */
4684 /* save EA bit in F1 */
4685 lbl = newiTempLabel(NULL);
4686 emitcode ("setb","F1");
4687 emitcode ("jbc","EA,%05d$",lbl->key+100);
4688 emitcode ("clr","F1");
4689 emitcode("","%05d$:",lbl->key+100);
4692 lbl = newiTempLabel(NULL);
4693 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4694 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4695 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4696 emitcode ("xch", "a,b");
4697 emitcode ("cpl","a");
4698 emitcode ("add", "a,#1");
4699 emitcode ("xch", "a,b");
4700 emitcode ("cpl", "a"); // msb
4701 emitcode ("addc","a,#0");
4702 emitcode ("","%05d$:",lbl->key+100);
4703 emitcode ("mov","ma,b");
4704 emitcode ("mov","ma,a");
4706 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4707 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4710 /* load up MB with right */
4712 if (AOP_TYPE(right) == AOP_LIT) {
4713 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4717 emitcode ("mov","mb,#0x%02x",val & 0xff);
4718 emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4720 lbl = newiTempLabel(NULL);
4721 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4722 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4723 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4724 emitcode ("xch", "a,b");
4725 emitcode ("cpl","a");
4726 emitcode ("add", "a,#1");
4727 emitcode ("xch", "a,b");
4728 emitcode ("cpl", "a"); // msb
4729 emitcode ("addc", "a,#0");
4730 emitcode ("","%05d$:",lbl->key+100);
4731 emitcode ("mov","mb,b");
4732 emitcode ("mov","mb,a");
4735 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4736 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4739 /* wait for multiplication to finish */
4740 lbl = newiTempLabel(NULL);
4741 emitcode("","%05d$:", lbl->key+100);
4742 emitcode("mov","a,mcnt1");
4743 emitcode("anl","a,#0x80");
4744 emitcode("jnz","%05d$",lbl->key+100);
4746 freeAsmop (left, NULL, ic, TRUE);
4747 freeAsmop (right, NULL, ic,TRUE);
4748 aopOp(result, ic, TRUE, FALSE);
4750 aopPut(AOP(result),"mb",1);
4751 aopPut(AOP(result),"mb",0);
4752 freeAsmop (result, NULL, ic, TRUE);
4754 /* restore EA bit in F1 */
4755 lbl = newiTempLabel(NULL);
4756 emitcode ("jnb","F1,%05d$",lbl->key+100);
4757 emitcode ("setb","EA");
4758 emitcode("","%05d$:",lbl->key+100);
4762 /*-----------------------------------------------------------------*/
4763 /* genMod - generates code for division */
4764 /*-----------------------------------------------------------------*/
4768 operand *left = IC_LEFT (ic);
4769 operand *right = IC_RIGHT (ic);
4770 operand *result = IC_RESULT (ic);
4772 D (emitcode (";", "genMod "); );
4774 /* assign the amsops */
4777 /* special cases first */
4779 if (AOP_TYPE (left) == AOP_CRY &&
4780 AOP_TYPE (right) == AOP_CRY)
4782 genModbits (left, right, result, ic);
4786 /* if both are of size == 1 */
4787 if (AOP_SIZE (left) == 1 &&
4788 AOP_SIZE (right) == 1)
4790 genModOneByte (left, right, result, ic);
4794 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4795 /* use the ds390 ARITHMETIC accel UNIT */
4796 genModTwoByte (left, right, result, ic);
4800 /* should have been converted to function call */
4804 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4805 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4806 freeAsmop (result, NULL, ic, TRUE);
4809 /*-----------------------------------------------------------------*/
4810 /* genIfxJump :- will create a jump depending on the ifx */
4811 /*-----------------------------------------------------------------*/
4813 genIfxJump (iCode * ic, char *jval)
4816 symbol *tlbl = newiTempLabel (NULL);
4819 D (emitcode (";", "genIfxJump ");
4822 /* if true label then we jump if condition
4826 jlbl = IC_TRUE (ic);
4827 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4828 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4832 /* false label is present */
4833 jlbl = IC_FALSE (ic);
4834 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4835 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4837 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4838 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4840 emitcode (inst, "%05d$", tlbl->key + 100);
4841 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4842 emitcode ("", "%05d$:", tlbl->key + 100);
4844 /* mark the icode as generated */
4848 /*-----------------------------------------------------------------*/
4849 /* genCmp :- greater or less than comparison */
4850 /*-----------------------------------------------------------------*/
4852 genCmp (operand * left, operand * right,
4853 iCode * ic, iCode * ifx, int sign)
4855 int size, offset = 0;
4856 unsigned long lit = 0L;
4859 D (emitcode (";", "genCmp");
4862 result = IC_RESULT (ic);
4864 /* if left & right are bit variables */
4865 if (AOP_TYPE (left) == AOP_CRY &&
4866 AOP_TYPE (right) == AOP_CRY)
4868 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4869 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4873 /* subtract right from left if at the
4874 end the carry flag is set then we know that
4875 left is greater than right */
4876 size = max (AOP_SIZE (left), AOP_SIZE (right));
4878 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4879 if ((size == 1) && !sign &&
4880 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4882 symbol *lbl = newiTempLabel (NULL);
4883 emitcode ("cjne", "%s,%s,%05d$",
4884 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4885 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4887 emitcode ("", "%05d$:", lbl->key + 100);
4891 if (AOP_TYPE (right) == AOP_LIT)
4893 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4894 /* optimize if(x < 0) or if(x >= 0) */
4903 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4905 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4906 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4908 aopOp (result, ic, FALSE, FALSE);
4910 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4912 freeAsmop (result, NULL, ic, TRUE);
4913 genIfxJump (ifx, "acc.7");
4918 emitcode ("rlc", "a");
4920 goto release_freedLR;
4928 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4929 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4930 emitcode (";", "genCmp #2");
4931 if (sign && (size == 0))
4933 emitcode (";", "genCmp #3");
4934 emitcode ("xrl", "a,#0x80");
4935 if (AOP_TYPE (right) == AOP_LIT)
4937 unsigned long lit = (unsigned long)
4938 floatFromVal (AOP (right)->aopu.aop_lit);
4939 emitcode (";", "genCmp #3.1");
4940 emitcode ("subb", "a,#0x%02x",
4941 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4945 emitcode (";", "genCmp #3.2");
4946 if (AOP_NEEDSACC (right))
4948 emitcode ("push", "acc");
4950 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4951 FALSE, FALSE, FALSE));
4952 emitcode ("xrl", "b,#0x80");
4953 if (AOP_NEEDSACC (right))
4955 emitcode ("pop", "acc");
4957 emitcode ("subb", "a,b");
4964 emitcode (";", "genCmp #4");
4965 if (AOP_NEEDSACC (right))
4968 emitcode (";", "genCmp #4.1");
4969 emitcode ("xch", "a, b");
4970 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4971 emitcode ("xch", "a, b");
4976 emitcode (";", "genCmp #4.2");
4977 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4980 emitcode ("subb", "a,%s", s);
4987 /* Don't need the left & right operands any more; do need the result. */
4988 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4989 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4991 aopOp (result, ic, FALSE, FALSE);
4995 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5001 /* if the result is used in the next
5002 ifx conditional branch then generate
5003 code a little differently */
5006 genIfxJump (ifx, "c");
5012 /* leave the result in acc */
5014 freeAsmop (result, NULL, ic, TRUE);
5017 /*-----------------------------------------------------------------*/
5018 /* genCmpGt :- greater than comparison */
5019 /*-----------------------------------------------------------------*/
5021 genCmpGt (iCode * ic, iCode * ifx)
5023 operand *left, *right;
5024 sym_link *letype, *retype;
5027 D (emitcode (";", "genCmpGt ");
5030 left = IC_LEFT (ic);
5031 right = IC_RIGHT (ic);
5033 letype = getSpec (operandType (left));
5034 retype = getSpec (operandType (right));
5035 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5037 /* assign the left & right amsops */
5040 genCmp (right, left, ic, ifx, sign);
5043 /*-----------------------------------------------------------------*/
5044 /* genCmpLt - less than comparisons */
5045 /*-----------------------------------------------------------------*/
5047 genCmpLt (iCode * ic, iCode * ifx)
5049 operand *left, *right;
5050 sym_link *letype, *retype;
5053 D (emitcode (";", "genCmpLt "););
5055 left = IC_LEFT (ic);
5056 right = IC_RIGHT (ic);
5058 letype = getSpec (operandType (left));
5059 retype = getSpec (operandType (right));
5060 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5062 /* assign the left & right amsops */
5065 genCmp (left, right, ic, ifx, sign);
5068 /*-----------------------------------------------------------------*/
5069 /* gencjneshort - compare and jump if not equal */
5070 /*-----------------------------------------------------------------*/
5072 gencjneshort (operand * left, operand * right, symbol * lbl)
5074 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5076 unsigned long lit = 0L;
5078 D (emitcode (";", "gencjneshort");
5081 /* if the left side is a literal or
5082 if the right is in a pointer register and left
5084 if ((AOP_TYPE (left) == AOP_LIT) ||
5085 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5092 if (AOP_TYPE (right) == AOP_LIT)
5093 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5095 if (opIsGptr (left) || opIsGptr (right))
5097 /* We are comparing a generic pointer to something.
5098 * Exclude the generic type byte from the comparison.
5101 D (emitcode (";", "cjneshort: generic ptr special case.");
5106 /* if the right side is a literal then anything goes */
5107 if (AOP_TYPE (right) == AOP_LIT &&
5108 AOP_TYPE (left) != AOP_DIR)
5112 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5114 emitcode ("cjne", "a,%s,%05d$",
5115 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5121 /* if the right side is in a register or in direct space or
5122 if the left is a pointer register & right is not */
5123 else if (AOP_TYPE (right) == AOP_REG ||
5124 AOP_TYPE (right) == AOP_DIR ||
5125 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5126 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5130 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5131 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5132 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5133 emitcode ("jnz", "%05d$", lbl->key + 100);
5135 emitcode ("cjne", "a,%s,%05d$",
5136 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5143 /* right is a pointer reg need both a & b */
5146 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5147 if (strcmp (l, "b"))
5148 emitcode ("mov", "b,%s", l);
5149 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5150 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5156 /*-----------------------------------------------------------------*/
5157 /* gencjne - compare and jump if not equal */
5158 /*-----------------------------------------------------------------*/
5160 gencjne (operand * left, operand * right, symbol * lbl)
5162 symbol *tlbl = newiTempLabel (NULL);
5164 D (emitcode (";", "gencjne");
5167 gencjneshort (left, right, lbl);
5169 emitcode ("mov", "a,%s", one);
5170 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5171 emitcode ("", "%05d$:", lbl->key + 100);
5172 emitcode ("clr", "a");
5173 emitcode ("", "%05d$:", tlbl->key + 100);
5176 /*-----------------------------------------------------------------*/
5177 /* genCmpEq - generates code for equal to */
5178 /*-----------------------------------------------------------------*/
5180 genCmpEq (iCode * ic, iCode * ifx)
5182 operand *left, *right, *result;
5184 D (emitcode (";", "genCmpEq ");
5188 AOP_SET_LOCALS (ic);
5190 /* if literal, literal on the right or
5191 if the right is in a pointer register and left
5193 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5194 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5196 operand *t = IC_RIGHT (ic);
5197 IC_RIGHT (ic) = IC_LEFT (ic);
5201 if (ifx && /* !AOP_SIZE(result) */
5202 OP_SYMBOL (result) &&
5203 OP_SYMBOL (result)->regType == REG_CND)
5206 /* if they are both bit variables */
5207 if (AOP_TYPE (left) == AOP_CRY &&
5208 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5210 if (AOP_TYPE (right) == AOP_LIT)
5212 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5215 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5216 emitcode ("cpl", "c");
5220 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5224 emitcode ("clr", "c");
5226 /* AOP_TYPE(right) == AOP_CRY */
5230 symbol *lbl = newiTempLabel (NULL);
5231 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5232 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5233 emitcode ("cpl", "c");
5234 emitcode ("", "%05d$:", (lbl->key + 100));
5236 /* if true label then we jump if condition
5238 tlbl = newiTempLabel (NULL);
5241 emitcode ("jnc", "%05d$", tlbl->key + 100);
5242 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5246 emitcode ("jc", "%05d$", tlbl->key + 100);
5247 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5249 emitcode ("", "%05d$:", tlbl->key + 100);
5253 tlbl = newiTempLabel (NULL);
5254 gencjneshort (left, right, tlbl);
5257 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5258 emitcode ("", "%05d$:", tlbl->key + 100);
5262 symbol *lbl = newiTempLabel (NULL);
5263 emitcode ("sjmp", "%05d$", lbl->key + 100);
5264 emitcode ("", "%05d$:", tlbl->key + 100);
5265 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5266 emitcode ("", "%05d$:", lbl->key + 100);
5269 /* mark the icode as generated */
5272 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5273 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5277 /* if they are both bit variables */
5278 if (AOP_TYPE (left) == AOP_CRY &&
5279 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5281 if (AOP_TYPE (right) == AOP_LIT)
5283 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5286 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5287 emitcode ("cpl", "c");
5291 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5295 emitcode ("clr", "c");
5297 /* AOP_TYPE(right) == AOP_CRY */
5301 symbol *lbl = newiTempLabel (NULL);
5302 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5303 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5304 emitcode ("cpl", "c");
5305 emitcode ("", "%05d$:", (lbl->key + 100));
5308 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5309 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5311 aopOp (result, ic, TRUE, FALSE);
5314 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5321 genIfxJump (ifx, "c");
5324 /* if the result is used in an arithmetic operation
5325 then put the result in place */
5330 gencjne (left, right, newiTempLabel (NULL));
5332 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5333 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5335 aopOp (result, ic, TRUE, FALSE);
5337 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5339 aopPut (AOP (result), "a", 0);
5344 genIfxJump (ifx, "a");
5347 /* if the result is used in an arithmetic operation
5348 then put the result in place */
5349 if (AOP_TYPE (result) != AOP_CRY)
5351 /* leave the result in acc */
5355 freeAsmop (result, NULL, ic, TRUE);
5358 /*-----------------------------------------------------------------*/
5359 /* ifxForOp - returns the icode containing the ifx for operand */
5360 /*-----------------------------------------------------------------*/
5362 ifxForOp (operand * op, iCode * ic)
5364 /* if true symbol then needs to be assigned */
5365 if (IS_TRUE_SYMOP (op))
5368 /* if this has register type condition and
5369 the next instruction is ifx with the same operand
5370 and live to of the operand is upto the ifx only then */
5372 ic->next->op == IFX &&
5373 IC_COND (ic->next)->key == op->key &&
5374 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5379 /*-----------------------------------------------------------------*/
5380 /* hasInc - operand is incremented before any other use */
5381 /*-----------------------------------------------------------------*/
5383 hasInc (operand *op, iCode *ic)
5385 sym_link *type = operandType(op);
5386 sym_link *retype = getSpec (type);
5387 iCode *lic = ic->next;
5390 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5391 if (!IS_SYMOP(op)) return NULL;
5393 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5394 isize = getSize(type->next);
5396 /* if operand of the form op = op + <sizeof *op> */
5397 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5398 isOperandEqual(IC_RESULT(lic),op) &&
5399 isOperandLiteral(IC_RIGHT(lic)) &&
5400 operandLitValue(IC_RIGHT(lic)) == isize) {
5403 /* if the operand used or deffed */
5404 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5412 /*-----------------------------------------------------------------*/
5413 /* genAndOp - for && operation */
5414 /*-----------------------------------------------------------------*/
5416 genAndOp (iCode * ic)
5418 operand *left, *right, *result;
5421 D (emitcode (";", "genAndOp "););
5423 /* note here that && operations that are in an
5424 if statement are taken away by backPatchLabels
5425 only those used in arthmetic operations remain */
5427 AOP_SET_LOCALS (ic);
5429 /* if both are bit variables */
5430 if (AOP_TYPE (left) == AOP_CRY &&
5431 AOP_TYPE (right) == AOP_CRY)
5433 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5434 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5435 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5436 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5438 aopOp (result,ic,FALSE, FALSE);
5443 tlbl = newiTempLabel (NULL);
5445 emitcode ("jz", "%05d$", tlbl->key + 100);
5447 emitcode ("", "%05d$:", tlbl->key + 100);
5448 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5449 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5451 aopOp (result,ic,FALSE, FALSE);
5454 freeAsmop (result, NULL, ic, TRUE);
5458 /*-----------------------------------------------------------------*/
5459 /* genOrOp - for || operation */
5460 /*-----------------------------------------------------------------*/
5462 genOrOp (iCode * ic)
5464 operand *left, *right, *result;
5467 D (emitcode (";", "genOrOp "););
5469 /* note here that || operations that are in an
5470 if statement are taken away by backPatchLabels
5471 only those used in arthmetic operations remain */
5473 AOP_SET_LOCALS (ic);
5475 /* if both are bit variables */
5476 if (AOP_TYPE (left) == AOP_CRY &&
5477 AOP_TYPE (right) == AOP_CRY)
5479 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5480 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5481 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5482 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5484 aopOp (result,ic,FALSE, FALSE);
5490 tlbl = newiTempLabel (NULL);
5492 emitcode ("jnz", "%05d$", tlbl->key + 100);
5494 emitcode ("", "%05d$:", tlbl->key + 100);
5495 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5496 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5498 aopOp (result,ic,FALSE, FALSE);
5503 freeAsmop (result, NULL, ic, TRUE);
5506 /*-----------------------------------------------------------------*/
5507 /* isLiteralBit - test if lit == 2^n */
5508 /*-----------------------------------------------------------------*/
5510 isLiteralBit (unsigned long lit)
5512 unsigned long pw[32] =
5513 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5514 0x100L, 0x200L, 0x400L, 0x800L,
5515 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5516 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5517 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5518 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5519 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5522 for (idx = 0; idx < 32; idx++)
5528 /*-----------------------------------------------------------------*/
5529 /* continueIfTrue - */
5530 /*-----------------------------------------------------------------*/
5532 continueIfTrue (iCode * ic)
5535 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5539 /*-----------------------------------------------------------------*/
5541 /*-----------------------------------------------------------------*/
5543 jumpIfTrue (iCode * ic)
5546 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5550 /*-----------------------------------------------------------------*/
5551 /* jmpTrueOrFalse - */
5552 /*-----------------------------------------------------------------*/
5554 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5556 // ugly but optimized by peephole
5559 symbol *nlbl = newiTempLabel (NULL);
5560 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5561 emitcode ("", "%05d$:", tlbl->key + 100);
5562 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5563 emitcode ("", "%05d$:", nlbl->key + 100);
5567 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5568 emitcode ("", "%05d$:", tlbl->key + 100);
5573 // Generate code to perform a bit-wise logic operation
5574 // on two operands in far space (assumed to already have been
5575 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5576 // in far space. This requires pushing the result on the stack
5577 // then popping it into the result.
5579 genFarFarLogicOp(iCode *ic, char *logicOp)
5581 int size, resultSize, compSize;
5585 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5586 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5587 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5589 _startLazyDPSEvaluation();
5590 for (size = compSize; (size--); offset++)
5592 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5593 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5594 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5596 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5597 emitcode ("push", "acc");
5599 _endLazyDPSEvaluation();
5601 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5602 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5603 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5605 resultSize = AOP_SIZE(IC_RESULT(ic));
5607 ADJUST_PUSHED_RESULT(compSize, resultSize);
5609 _startLazyDPSEvaluation();
5612 emitcode ("pop", "acc");
5613 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5615 _endLazyDPSEvaluation();
5616 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5620 /*-----------------------------------------------------------------*/
5621 /* genAnd - code for and */
5622 /*-----------------------------------------------------------------*/
5624 genAnd (iCode * ic, iCode * ifx)
5626 operand *left, *right, *result;
5627 int size, offset = 0;
5628 unsigned long lit = 0L;
5633 D (emitcode (";", "genAnd "););
5635 AOP_OP_3_NOFATAL (ic, pushResult);
5636 AOP_SET_LOCALS (ic);
5640 genFarFarLogicOp(ic, "anl");
5645 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5647 AOP_TYPE (left), AOP_TYPE (right));
5648 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5650 AOP_SIZE (left), AOP_SIZE (right));
5653 /* if left is a literal & right is not then exchange them */
5654 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5655 #ifdef LOGIC_OPS_BROKEN
5656 || AOP_NEEDSACC (left)
5660 operand *tmp = right;
5665 /* if result = right then exchange them */
5666 if (sameRegs (AOP (result), AOP (right)))
5668 operand *tmp = right;
5673 /* if right is bit then exchange them */
5674 if (AOP_TYPE (right) == AOP_CRY &&
5675 AOP_TYPE (left) != AOP_CRY)
5677 operand *tmp = right;
5681 if (AOP_TYPE (right) == AOP_LIT)
5682 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5684 size = AOP_SIZE (result);
5687 // result = bit & yy;
5688 if (AOP_TYPE (left) == AOP_CRY)
5690 // c = bit & literal;
5691 if (AOP_TYPE (right) == AOP_LIT)
5695 if (size && sameRegs (AOP (result), AOP (left)))
5698 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5703 if (size && (AOP_TYPE (result) == AOP_CRY))
5705 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5708 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5713 emitcode ("clr", "c");
5718 if (AOP_TYPE (right) == AOP_CRY)
5721 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5722 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5727 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5729 emitcode ("rrc", "a");
5730 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5738 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5739 genIfxJump (ifx, "c");
5743 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5744 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5745 if ((AOP_TYPE (right) == AOP_LIT) &&
5746 (AOP_TYPE (result) == AOP_CRY) &&
5747 (AOP_TYPE (left) != AOP_CRY))
5749 int posbit = isLiteralBit (lit);
5754 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5757 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5763 sprintf (buffer, "acc.%d", posbit & 0x07);
5764 genIfxJump (ifx, buffer);
5771 symbol *tlbl = newiTempLabel (NULL);
5772 int sizel = AOP_SIZE (left);
5774 emitcode ("setb", "c");
5777 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5779 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5781 if ((posbit = isLiteralBit (bytelit)) != 0)
5782 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5785 if (bytelit != 0x0FFL)
5786 emitcode ("anl", "a,%s",
5787 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5788 emitcode ("jnz", "%05d$", tlbl->key + 100);
5793 // bit = left & literal
5796 emitcode ("clr", "c");
5797 emitcode ("", "%05d$:", tlbl->key + 100);
5799 // if(left & literal)
5803 jmpTrueOrFalse (ifx, tlbl);
5811 /* if left is same as result */
5812 if (sameRegs (AOP (result), AOP (left)))
5814 for (; size--; offset++)
5816 if (AOP_TYPE (right) == AOP_LIT)
5818 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5820 else if (bytelit == 0)
5821 aopPut (AOP (result), zero, offset);
5822 else if (IS_AOP_PREG (result))
5824 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5825 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5826 aopPut (AOP (result), "a", offset);
5829 emitcode ("anl", "%s,%s",
5830 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5831 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5835 if (AOP_TYPE (left) == AOP_ACC)
5836 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5839 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5840 if (IS_AOP_PREG (result))
5842 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5843 aopPut (AOP (result), "a", offset);
5847 emitcode ("anl", "%s,a",
5848 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5855 // left & result in different registers
5856 if (AOP_TYPE (result) == AOP_CRY)
5859 // if(size), result in bit
5860 // if(!size && ifx), conditional oper: if(left & right)
5861 symbol *tlbl = newiTempLabel (NULL);
5862 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5864 emitcode ("setb", "c");
5867 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5868 emitcode ("anl", "a,%s",
5869 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5871 if (AOP_TYPE(left)==AOP_ACC) {
5872 emitcode("mov", "b,a");
5873 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5874 emitcode("anl", "a,b");
5876 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5877 emitcode ("anl", "a,%s",
5878 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5881 emitcode ("jnz", "%05d$", tlbl->key + 100);
5887 emitcode ("", "%05d$:", tlbl->key + 100);
5891 jmpTrueOrFalse (ifx, tlbl);
5895 for (; (size--); offset++)
5898 // result = left & right
5899 if (AOP_TYPE (right) == AOP_LIT)
5901 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5903 aopPut (AOP (result),
5904 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5908 else if (bytelit == 0)
5910 aopPut (AOP (result), zero, offset);
5913 D (emitcode (";", "better literal AND."););
5914 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5915 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5916 FALSE, FALSE, FALSE));
5921 // faster than result <- left, anl result,right
5922 // and better if result is SFR
5923 if (AOP_TYPE (left) == AOP_ACC)
5925 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5926 FALSE, FALSE, FALSE));
5930 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
5931 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
5933 emitcode("mov", "b,a");
5937 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5938 emitcode ("anl", "a,%s", rOp);
5941 aopPut (AOP (result), "a", offset);
5947 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5948 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5949 freeAsmop (result, NULL, ic, TRUE);
5953 /*-----------------------------------------------------------------*/
5954 /* genOr - code for or */
5955 /*-----------------------------------------------------------------*/
5957 genOr (iCode * ic, iCode * ifx)
5959 operand *left, *right, *result;
5960 int size, offset = 0;
5961 unsigned long lit = 0L;
5964 D (emitcode (";", "genOr "););
5966 AOP_OP_3_NOFATAL (ic, pushResult);
5967 AOP_SET_LOCALS (ic);
5971 genFarFarLogicOp(ic, "orl");
5977 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5979 AOP_TYPE (left), AOP_TYPE (right));
5980 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5982 AOP_SIZE (left), AOP_SIZE (right));
5985 /* if left is a literal & right is not then exchange them */
5986 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5987 #ifdef LOGIC_OPS_BROKEN
5988 || AOP_NEEDSACC (left) // I think this is a net loss now.
5992 operand *tmp = right;
5997 /* if result = right then exchange them */
5998 if (sameRegs (AOP (result), AOP (right)))
6000 operand *tmp = right;
6005 /* if right is bit then exchange them */
6006 if (AOP_TYPE (right) == AOP_CRY &&
6007 AOP_TYPE (left) != AOP_CRY)
6009 operand *tmp = right;
6013 if (AOP_TYPE (right) == AOP_LIT)
6014 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6016 size = AOP_SIZE (result);
6020 if (AOP_TYPE (left) == AOP_CRY)
6022 if (AOP_TYPE (right) == AOP_LIT)
6024 // c = bit & literal;
6027 // lit != 0 => result = 1
6028 if (AOP_TYPE (result) == AOP_CRY)
6031 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6033 continueIfTrue (ifx);
6036 emitcode ("setb", "c");
6040 // lit == 0 => result = left
6041 if (size && sameRegs (AOP (result), AOP (left)))
6043 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6048 if (AOP_TYPE (right) == AOP_CRY)
6051 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6052 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6057 symbol *tlbl = newiTempLabel (NULL);
6058 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6059 emitcode ("setb", "c");
6060 emitcode ("jb", "%s,%05d$",
6061 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6063 emitcode ("jnz", "%05d$", tlbl->key + 100);
6064 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6066 jmpTrueOrFalse (ifx, tlbl);
6072 emitcode ("", "%05d$:", tlbl->key + 100);
6081 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6082 genIfxJump (ifx, "c");
6086 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6087 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6088 if ((AOP_TYPE (right) == AOP_LIT) &&
6089 (AOP_TYPE (result) == AOP_CRY) &&
6090 (AOP_TYPE (left) != AOP_CRY))
6096 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6098 continueIfTrue (ifx);
6103 // lit = 0, result = boolean(left)
6105 emitcode ("setb", "c");
6109 symbol *tlbl = newiTempLabel (NULL);
6110 emitcode ("jnz", "%05d$", tlbl->key + 100);
6112 emitcode ("", "%05d$:", tlbl->key + 100);
6116 genIfxJump (ifx, "a");
6124 /* if left is same as result */
6125 if (sameRegs (AOP (result), AOP (left)))
6127 for (; size--; offset++)
6129 if (AOP_TYPE (right) == AOP_LIT)
6131 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6137 if (IS_AOP_PREG (left))
6139 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6140 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6141 aopPut (AOP (result), "a", offset);
6145 emitcode ("orl", "%s,%s",
6146 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6147 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6153 if (AOP_TYPE (left) == AOP_ACC)
6155 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6159 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6160 if (IS_AOP_PREG (left))
6162 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6163 aopPut (AOP (result), "a", offset);
6167 emitcode ("orl", "%s,a",
6168 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6176 // left & result in different registers
6177 if (AOP_TYPE (result) == AOP_CRY)
6180 // if(size), result in bit
6181 // if(!size && ifx), conditional oper: if(left | right)
6182 symbol *tlbl = newiTempLabel (NULL);
6183 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6185 emitcode ("setb", "c");
6188 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6189 emitcode ("orl", "a,%s",
6190 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6192 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6193 emitcode ("orl", "a,%s",
6194 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6196 emitcode ("jnz", "%05d$", tlbl->key + 100);
6202 emitcode ("", "%05d$:", tlbl->key + 100);
6206 jmpTrueOrFalse (ifx, tlbl);
6210 _startLazyDPSEvaluation();
6211 for (; (size--); offset++)
6214 // result = left & right
6215 if (AOP_TYPE (right) == AOP_LIT)
6217 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6219 aopPut (AOP (result),
6220 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6224 D (emitcode (";", "better literal OR."););
6225 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6226 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6227 FALSE, FALSE, FALSE));
6232 // faster than result <- left, anl result,right
6233 // and better if result is SFR
6234 if (AOP_TYPE (left) == AOP_ACC)
6236 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6237 FALSE, FALSE, FALSE));
6241 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6243 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6245 emitcode("mov", "b,a");
6249 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6250 emitcode ("orl", "a,%s", rOp);
6253 aopPut (AOP (result), "a", offset);
6255 _endLazyDPSEvaluation();
6260 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6261 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6262 freeAsmop (result, NULL, ic, TRUE);
6265 /*-----------------------------------------------------------------*/
6266 /* genXor - code for xclusive or */
6267 /*-----------------------------------------------------------------*/
6269 genXor (iCode * ic, iCode * ifx)
6271 operand *left, *right, *result;
6272 int size, offset = 0;
6273 unsigned long lit = 0L;
6276 D (emitcode (";", "genXor "););
6278 AOP_OP_3_NOFATAL (ic, pushResult);
6279 AOP_SET_LOCALS (ic);
6283 genFarFarLogicOp(ic, "xrl");
6288 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6290 AOP_TYPE (left), AOP_TYPE (right));
6291 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6293 AOP_SIZE (left), AOP_SIZE (right));
6296 /* if left is a literal & right is not ||
6297 if left needs acc & right does not */
6298 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6299 #ifdef LOGIC_OPS_BROKEN
6300 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6304 operand *tmp = right;
6309 /* if result = right then exchange them */
6310 if (sameRegs (AOP (result), AOP (right)))
6312 operand *tmp = right;
6317 /* if right is bit then exchange them */
6318 if (AOP_TYPE (right) == AOP_CRY &&
6319 AOP_TYPE (left) != AOP_CRY)
6321 operand *tmp = right;
6325 if (AOP_TYPE (right) == AOP_LIT)
6326 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6328 size = AOP_SIZE (result);
6332 if (AOP_TYPE (left) == AOP_CRY)
6334 if (AOP_TYPE (right) == AOP_LIT)
6336 // c = bit & literal;
6339 // lit>>1 != 0 => result = 1
6340 if (AOP_TYPE (result) == AOP_CRY)
6343 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6345 continueIfTrue (ifx);
6348 emitcode ("setb", "c");
6355 // lit == 0, result = left
6356 if (size && sameRegs (AOP (result), AOP (left)))
6358 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6362 // lit == 1, result = not(left)
6363 if (size && sameRegs (AOP (result), AOP (left)))
6365 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6370 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6371 emitcode ("cpl", "c");
6380 symbol *tlbl = newiTempLabel (NULL);
6381 if (AOP_TYPE (right) == AOP_CRY)
6384 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6388 int sizer = AOP_SIZE (right);
6390 // if val>>1 != 0, result = 1
6391 emitcode ("setb", "c");
6394 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6396 // test the msb of the lsb
6397 emitcode ("anl", "a,#0xfe");
6398 emitcode ("jnz", "%05d$", tlbl->key + 100);
6402 emitcode ("rrc", "a");
6404 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6405 emitcode ("cpl", "c");
6406 emitcode ("", "%05d$:", (tlbl->key + 100));
6413 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6414 genIfxJump (ifx, "c");
6418 if (sameRegs (AOP (result), AOP (left)))
6420 /* if left is same as result */
6421 for (; size--; offset++)
6423 if (AOP_TYPE (right) == AOP_LIT)
6425 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6427 else if (IS_AOP_PREG (left))
6429 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6430 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6431 aopPut (AOP (result), "a", offset);
6434 emitcode ("xrl", "%s,%s",
6435 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6436 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6440 if (AOP_TYPE (left) == AOP_ACC)
6441 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6444 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6445 if (IS_AOP_PREG (left))
6447 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6448 aopPut (AOP (result), "a", offset);
6451 emitcode ("xrl", "%s,a",
6452 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6459 // left & result in different registers
6460 if (AOP_TYPE (result) == AOP_CRY)
6463 // if(size), result in bit
6464 // if(!size && ifx), conditional oper: if(left ^ right)
6465 symbol *tlbl = newiTempLabel (NULL);
6466 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6468 emitcode ("setb", "c");
6471 if ((AOP_TYPE (right) == AOP_LIT) &&
6472 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6474 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6478 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6479 emitcode ("xrl", "a,%s",
6480 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6482 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6483 emitcode ("xrl", "a,%s",
6484 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6487 emitcode ("jnz", "%05d$", tlbl->key + 100);
6493 emitcode ("", "%05d$:", tlbl->key + 100);
6497 jmpTrueOrFalse (ifx, tlbl);
6500 for (; (size--); offset++)
6503 // result = left & right
6504 if (AOP_TYPE (right) == AOP_LIT)
6506 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6508 aopPut (AOP (result),
6509 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6513 D (emitcode (";", "better literal XOR.");
6515 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6516 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6517 FALSE, FALSE, FALSE));
6521 // faster than result <- left, anl result,right
6522 // and better if result is SFR
6523 if (AOP_TYPE (left) == AOP_ACC)
6525 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6526 FALSE, FALSE, FALSE));
6530 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6531 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6533 emitcode("mov", "b,a");
6537 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6538 emitcode ("xrl", "a,%s", rOp);
6541 aopPut (AOP (result), "a", offset);
6546 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6547 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6548 freeAsmop (result, NULL, ic, TRUE);
6551 /*-----------------------------------------------------------------*/
6552 /* genInline - write the inline code out */
6553 /*-----------------------------------------------------------------*/
6555 genInline (iCode * ic)
6557 char *buffer, *bp, *bp1;
6559 D (emitcode (";", "genInline ");
6562 _G.inLine += (!options.asmpeep);
6564 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6565 strcpy (buffer, IC_INLINE (ic));
6567 /* emit each line as a code */
6592 /* emitcode("",buffer); */
6593 _G.inLine -= (!options.asmpeep);
6596 /*-----------------------------------------------------------------*/
6597 /* genRRC - rotate right with carry */
6598 /*-----------------------------------------------------------------*/
6602 operand *left, *result;
6603 int size, offset = 0;
6606 D (emitcode (";", "genRRC ");
6609 /* rotate right with carry */
6610 left = IC_LEFT (ic);
6611 result = IC_RESULT (ic);
6612 aopOp (left, ic, FALSE, FALSE);
6613 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6615 /* move it to the result */
6616 size = AOP_SIZE (result);
6620 _startLazyDPSEvaluation ();
6623 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6625 emitcode ("rrc", "a");
6626 if (AOP_SIZE (result) > 1)
6627 aopPut (AOP (result), "a", offset--);
6629 _endLazyDPSEvaluation ();
6631 /* now we need to put the carry into the
6632 highest order byte of the result */
6633 if (AOP_SIZE (result) > 1)
6635 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6638 emitcode ("mov", "acc.7,c");
6639 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6640 freeAsmop (left, NULL, ic, TRUE);
6641 freeAsmop (result, NULL, ic, TRUE);
6644 /*-----------------------------------------------------------------*/
6645 /* genRLC - generate code for rotate left with carry */
6646 /*-----------------------------------------------------------------*/
6650 operand *left, *result;
6651 int size, offset = 0;
6654 D (emitcode (";", "genRLC ");
6657 /* rotate right with carry */
6658 left = IC_LEFT (ic);
6659 result = IC_RESULT (ic);
6660 aopOp (left, ic, FALSE, FALSE);
6661 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6663 /* move it to the result */
6664 size = AOP_SIZE (result);
6668 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6670 emitcode ("add", "a,acc");
6671 if (AOP_SIZE (result) > 1)
6673 aopPut (AOP (result), "a", offset++);
6676 _startLazyDPSEvaluation ();
6679 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6681 emitcode ("rlc", "a");
6682 if (AOP_SIZE (result) > 1)
6683 aopPut (AOP (result), "a", offset++);
6685 _endLazyDPSEvaluation ();
6687 /* now we need to put the carry into the
6688 highest order byte of the result */
6689 if (AOP_SIZE (result) > 1)
6691 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6694 emitcode ("mov", "acc.0,c");
6695 aopPut (AOP (result), "a", 0);
6696 freeAsmop (left, NULL, ic, TRUE);
6697 freeAsmop (result, NULL, ic, TRUE);
6700 /*-----------------------------------------------------------------*/
6701 /* genGetHbit - generates code get highest order bit */
6702 /*-----------------------------------------------------------------*/
6704 genGetHbit (iCode * ic)
6706 operand *left, *result;
6707 left = IC_LEFT (ic);
6708 result = IC_RESULT (ic);
6709 aopOp (left, ic, FALSE, FALSE);
6710 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6712 D (emitcode (";", "genGetHbit ");
6715 /* get the highest order byte into a */
6716 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6717 if (AOP_TYPE (result) == AOP_CRY)
6719 emitcode ("rlc", "a");
6724 emitcode ("rl", "a");
6725 emitcode ("anl", "a,#0x01");
6730 freeAsmop (left, NULL, ic, TRUE);
6731 freeAsmop (result, NULL, ic, TRUE);
6734 /*-----------------------------------------------------------------*/
6735 /* AccRol - rotate left accumulator by known count */
6736 /*-----------------------------------------------------------------*/
6738 AccRol (int shCount)
6740 shCount &= 0x0007; // shCount : 0..7
6747 emitcode ("rl", "a");
6750 emitcode ("rl", "a");
6751 emitcode ("rl", "a");
6754 emitcode ("swap", "a");
6755 emitcode ("rr", "a");
6758 emitcode ("swap", "a");
6761 emitcode ("swap", "a");
6762 emitcode ("rl", "a");
6765 emitcode ("rr", "a");
6766 emitcode ("rr", "a");
6769 emitcode ("rr", "a");
6774 /*-----------------------------------------------------------------*/
6775 /* AccLsh - left shift accumulator by known count */
6776 /*-----------------------------------------------------------------*/
6778 AccLsh (int shCount)
6783 emitcode ("add", "a,acc");
6784 else if (shCount == 2)
6786 emitcode ("add", "a,acc");
6787 emitcode ("add", "a,acc");
6791 /* rotate left accumulator */
6793 /* and kill the lower order bits */
6794 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6799 /*-----------------------------------------------------------------*/
6800 /* AccRsh - right shift accumulator by known count */
6801 /*-----------------------------------------------------------------*/
6803 AccRsh (int shCount)
6810 emitcode ("rrc", "a");
6814 /* rotate right accumulator */
6815 AccRol (8 - shCount);
6816 /* and kill the higher order bits */
6817 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6822 #ifdef BETTER_LITERAL_SHIFT
6823 /*-----------------------------------------------------------------*/
6824 /* AccSRsh - signed right shift accumulator by known count */
6825 /*-----------------------------------------------------------------*/
6827 AccSRsh (int shCount)
6834 emitcode ("mov", "c,acc.7");
6835 emitcode ("rrc", "a");
6837 else if (shCount == 2)
6839 emitcode ("mov", "c,acc.7");
6840 emitcode ("rrc", "a");
6841 emitcode ("mov", "c,acc.7");
6842 emitcode ("rrc", "a");
6846 tlbl = newiTempLabel (NULL);
6847 /* rotate right accumulator */
6848 AccRol (8 - shCount);
6849 /* and kill the higher order bits */
6850 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6851 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6852 emitcode ("orl", "a,#0x%02x",
6853 (unsigned char) ~SRMask[shCount]);
6854 emitcode ("", "%05d$:", tlbl->key + 100);
6860 #ifdef BETTER_LITERAL_SHIFT
6861 /*-----------------------------------------------------------------*/
6862 /* shiftR1Left2Result - shift right one byte from left to result */
6863 /*-----------------------------------------------------------------*/
6865 shiftR1Left2Result (operand * left, int offl,
6866 operand * result, int offr,
6867 int shCount, int sign)
6869 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6870 /* shift right accumulator */
6875 aopPut (AOP (result), "a", offr);
6879 #ifdef BETTER_LITERAL_SHIFT
6880 /*-----------------------------------------------------------------*/
6881 /* shiftL1Left2Result - shift left one byte from left to result */
6882 /*-----------------------------------------------------------------*/
6884 shiftL1Left2Result (operand * left, int offl,
6885 operand * result, int offr, int shCount)
6887 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6888 /* shift left accumulator */
6890 aopPut (AOP (result), "a", offr);
6894 #ifdef BETTER_LITERAL_SHIFT
6895 /*-----------------------------------------------------------------*/
6896 /* movLeft2Result - move byte from left to result */
6897 /*-----------------------------------------------------------------*/
6899 movLeft2Result (operand * left, int offl,
6900 operand * result, int offr, int sign)
6903 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6905 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6907 if (*l == '@' && (IS_AOP_PREG (result)))
6909 emitcode ("mov", "a,%s", l);
6910 aopPut (AOP (result), "a", offr);
6916 aopPut (AOP (result), l, offr);
6920 /* MSB sign in acc.7 ! */
6921 if (getDataSize (left) == offl + 1)
6923 emitcode ("mov", "a,%s", l);
6924 aopPut (AOP (result), "a", offr);
6932 #ifdef BETTER_LITERAL_SHIFT
6933 /*-----------------------------------------------------------------*/
6934 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6935 /*-----------------------------------------------------------------*/
6939 emitcode ("rrc", "a");
6940 emitcode ("xch", "a,%s", x);
6941 emitcode ("rrc", "a");
6942 emitcode ("xch", "a,%s", x);
6946 #ifdef BETTER_LITERAL_SHIFT
6948 /*-----------------------------------------------------------------*/
6949 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6950 /*-----------------------------------------------------------------*/
6954 emitcode ("xch", "a,%s", x);
6955 emitcode ("rlc", "a");
6956 emitcode ("xch", "a,%s", x);
6957 emitcode ("rlc", "a");
6961 #ifdef BETTER_LITERAL_SHIFT
6962 /*-----------------------------------------------------------------*/
6963 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6964 /*-----------------------------------------------------------------*/
6968 emitcode ("xch", "a,%s", x);
6969 emitcode ("add", "a,acc");
6970 emitcode ("xch", "a,%s", x);
6971 emitcode ("rlc", "a");
6975 #ifdef BETTER_LITERAL_SHIFT
6976 /*-----------------------------------------------------------------*/
6977 /* AccAXLsh - left shift a:x by known count (0..7) */
6978 /*-----------------------------------------------------------------*/
6980 AccAXLsh (char *x, int shCount)
6995 case 5: // AAAAABBB:CCCCCDDD
6997 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6999 emitcode ("anl", "a,#0x%02x",
7000 SLMask[shCount]); // BBB00000:CCCCCDDD
7002 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7004 AccRol (shCount); // DDDCCCCC:BBB00000
7006 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7008 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7010 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7012 emitcode ("anl", "a,#0x%02x",
7013 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7015 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7017 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7020 case 6: // AAAAAABB:CCCCCCDD
7021 emitcode ("anl", "a,#0x%02x",
7022 SRMask[shCount]); // 000000BB:CCCCCCDD
7023 emitcode ("mov", "c,acc.0"); // c = B
7024 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7026 AccAXRrl1 (x); // BCCCCCCD:D000000B
7027 AccAXRrl1 (x); // BBCCCCCC:DD000000
7029 emitcode("rrc","a");
7030 emitcode("xch","a,%s", x);
7031 emitcode("rrc","a");
7032 emitcode("mov","c,acc.0"); //<< get correct bit
7033 emitcode("xch","a,%s", x);
7035 emitcode("rrc","a");
7036 emitcode("xch","a,%s", x);
7037 emitcode("rrc","a");
7038 emitcode("xch","a,%s", x);
7041 case 7: // a:x <<= 7
7043 emitcode ("anl", "a,#0x%02x",
7044 SRMask[shCount]); // 0000000B:CCCCCCCD
7046 emitcode ("mov", "c,acc.0"); // c = B
7048 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7050 AccAXRrl1 (x); // BCCCCCCC:D0000000
7059 #ifdef BETTER_LITERAL_SHIFT
7061 /*-----------------------------------------------------------------*/
7062 /* AccAXRsh - right shift a:x known count (0..7) */
7063 /*-----------------------------------------------------------------*/
7065 AccAXRsh (char *x, int shCount)
7073 AccAXRrl1 (x); // 0->a:x
7078 AccAXRrl1 (x); // 0->a:x
7081 AccAXRrl1 (x); // 0->a:x
7086 case 5: // AAAAABBB:CCCCCDDD = a:x
7088 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7090 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7092 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7094 emitcode ("anl", "a,#0x%02x",
7095 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7097 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7099 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7101 emitcode ("anl", "a,#0x%02x",
7102 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7104 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7106 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7108 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7111 case 6: // AABBBBBB:CCDDDDDD
7113 emitcode ("mov", "c,acc.7");
7114 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7116 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7118 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7120 emitcode ("anl", "a,#0x%02x",
7121 SRMask[shCount]); // 000000AA:BBBBBBCC
7124 case 7: // ABBBBBBB:CDDDDDDD
7126 emitcode ("mov", "c,acc.7"); // c = A
7128 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7130 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7132 emitcode ("anl", "a,#0x%02x",
7133 SRMask[shCount]); // 0000000A:BBBBBBBC
7142 #ifdef BETTER_LITERAL_SHIFT
7143 /*-----------------------------------------------------------------*/
7144 /* AccAXRshS - right shift signed a:x known count (0..7) */
7145 /*-----------------------------------------------------------------*/
7147 AccAXRshS (char *x, int shCount)
7155 emitcode ("mov", "c,acc.7");
7156 AccAXRrl1 (x); // s->a:x
7160 emitcode ("mov", "c,acc.7");
7161 AccAXRrl1 (x); // s->a:x
7163 emitcode ("mov", "c,acc.7");
7164 AccAXRrl1 (x); // s->a:x
7169 case 5: // AAAAABBB:CCCCCDDD = a:x
7171 tlbl = newiTempLabel (NULL);
7172 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7174 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7176 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7178 emitcode ("anl", "a,#0x%02x",
7179 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7181 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7183 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7185 emitcode ("anl", "a,#0x%02x",
7186 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7188 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7190 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7192 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7194 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7195 emitcode ("orl", "a,#0x%02x",
7196 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7198 emitcode ("", "%05d$:", tlbl->key + 100);
7199 break; // SSSSAAAA:BBBCCCCC
7201 case 6: // AABBBBBB:CCDDDDDD
7203 tlbl = newiTempLabel (NULL);
7204 emitcode ("mov", "c,acc.7");
7205 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7207 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7209 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7211 emitcode ("anl", "a,#0x%02x",
7212 SRMask[shCount]); // 000000AA:BBBBBBCC
7214 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7215 emitcode ("orl", "a,#0x%02x",
7216 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7218 emitcode ("", "%05d$:", tlbl->key + 100);
7220 case 7: // ABBBBBBB:CDDDDDDD
7222 tlbl = newiTempLabel (NULL);
7223 emitcode ("mov", "c,acc.7"); // c = A
7225 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7227 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7229 emitcode ("anl", "a,#0x%02x",
7230 SRMask[shCount]); // 0000000A:BBBBBBBC
7232 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7233 emitcode ("orl", "a,#0x%02x",
7234 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7236 emitcode ("", "%05d$:", tlbl->key + 100);
7244 #ifdef BETTER_LITERAL_SHIFT
7246 _loadLeftIntoAx(char **lsb,
7252 // Get the initial value from left into a pair of registers.
7253 // MSB must be in A, LSB can be any register.
7255 // If the result is held in registers, it is an optimization
7256 // if the LSB can be held in the register which will hold the,
7257 // result LSB since this saves us from having to copy it into
7258 // the result following AccAXLsh.
7260 // If the result is addressed indirectly, this is not a gain.
7261 if (AOP_NEEDSACC(result))
7265 _startLazyDPSEvaluation();
7266 if (AOP_TYPE(left) == AOP_DPTR2)
7269 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7270 // get LSB in DP2_RESULT_REG.
7271 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7272 assert(!strcmp(leftByte, DP2_RESULT_REG));
7276 // get LSB into DP2_RESULT_REG
7277 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7278 if (strcmp(leftByte, DP2_RESULT_REG))
7281 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7284 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7285 assert(strcmp(leftByte, DP2_RESULT_REG));
7288 _endLazyDPSEvaluation();
7289 *lsb = DP2_RESULT_REG;
7293 if (sameRegs (AOP (result), AOP (left)) &&
7294 ((offl + MSB16) == offr))
7296 /* don't crash result[offr] */
7297 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7298 emitcode ("xch", "a,%s",
7299 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7303 movLeft2Result (left, offl, result, offr, 0);
7304 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7306 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7307 assert(strcmp(*lsb,"a"));
7312 _storeAxResults(char *lsb,
7316 _startLazyDPSEvaluation();
7317 if (AOP_NEEDSACC(result))
7319 /* We have to explicitly update the result LSB.
7321 emitcode("xch","a,%s", lsb);
7322 aopPut(AOP(result), "a", offr);
7323 emitcode("mov","a,%s", lsb);
7325 if (getDataSize (result) > 1)
7327 aopPut (AOP (result), "a", offr + MSB16);
7329 _endLazyDPSEvaluation();
7332 /*-----------------------------------------------------------------*/
7333 /* shiftL2Left2Result - shift left two bytes from left to result */
7334 /*-----------------------------------------------------------------*/
7336 shiftL2Left2Result (operand * left, int offl,
7337 operand * result, int offr, int shCount)
7341 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7343 AccAXLsh (lsb, shCount);
7345 _storeAxResults(lsb, result, offr);
7349 #ifdef BETTER_LITERAL_SHIFT
7350 /*-----------------------------------------------------------------*/
7351 /* shiftR2Left2Result - shift right two bytes from left to result */
7352 /*-----------------------------------------------------------------*/
7354 shiftR2Left2Result (operand * left, int offl,
7355 operand * result, int offr,
7356 int shCount, int sign)
7360 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7362 /* a:x >> shCount (x = lsb(result)) */
7365 AccAXRshS(lsb, shCount);
7369 AccAXRsh(lsb, shCount);
7372 _storeAxResults(lsb, result, offr);
7378 /*-----------------------------------------------------------------*/
7379 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7380 /*-----------------------------------------------------------------*/
7382 shiftLLeftOrResult (operand * left, int offl,
7383 operand * result, int offr, int shCount)
7385 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7386 /* shift left accumulator */
7388 /* or with result */
7389 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7390 /* back to result */
7391 aopPut (AOP (result), "a", offr);
7397 /*-----------------------------------------------------------------*/
7398 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7399 /*-----------------------------------------------------------------*/
7401 shiftRLeftOrResult (operand * left, int offl,
7402 operand * result, int offr, int shCount)
7404 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7405 /* shift right accumulator */
7407 /* or with result */
7408 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7409 /* back to result */
7410 aopPut (AOP (result), "a", offr);
7414 #ifdef BETTER_LITERAL_SHIFT
7415 /*-----------------------------------------------------------------*/
7416 /* genlshOne - left shift a one byte quantity by known count */
7417 /*-----------------------------------------------------------------*/
7419 genlshOne (operand * result, operand * left, int shCount)
7421 D (emitcode (";", "genlshOne "););
7422 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7426 #ifdef BETTER_LITERAL_SHIFT
7427 /*-----------------------------------------------------------------*/
7428 /* genlshTwo - left shift two bytes by known amount != 0 */
7429 /*-----------------------------------------------------------------*/
7431 genlshTwo (operand * result, operand * left, int shCount)
7435 D (emitcode (";", "genlshTwo "););
7437 size = getDataSize (result);
7439 /* if shCount >= 8 */
7444 _startLazyDPSEvaluation();
7450 _endLazyDPSEvaluation();
7451 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7452 aopPut (AOP (result), zero, LSB);
7456 movLeft2Result (left, LSB, result, MSB16, 0);
7457 aopPut (AOP (result), zero, LSB);
7458 _endLazyDPSEvaluation();
7463 aopPut (AOP (result), zero, LSB);
7464 _endLazyDPSEvaluation();
7468 /* 1 <= shCount <= 7 */
7473 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7477 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7485 /*-----------------------------------------------------------------*/
7486 /* shiftLLong - shift left one long from left to result */
7487 /* offl = LSB or MSB16 */
7488 /*-----------------------------------------------------------------*/
7490 shiftLLong (operand * left, operand * result, int offr)
7493 int size = AOP_SIZE (result);
7495 if (size >= LSB + offr)
7497 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7499 emitcode ("add", "a,acc");
7500 if (sameRegs (AOP (left), AOP (result)) &&
7501 size >= MSB16 + offr && offr != LSB)
7502 emitcode ("xch", "a,%s",
7503 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7505 aopPut (AOP (result), "a", LSB + offr);
7508 if (size >= MSB16 + offr)
7510 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7512 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7515 emitcode ("rlc", "a");
7516 if (sameRegs (AOP (left), AOP (result)) &&
7517 size >= MSB24 + offr && offr != LSB)
7518 emitcode ("xch", "a,%s",
7519 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7521 aopPut (AOP (result), "a", MSB16 + offr);
7524 if (size >= MSB24 + offr)
7526 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7528 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7531 emitcode ("rlc", "a");
7532 if (sameRegs (AOP (left), AOP (result)) &&
7533 size >= MSB32 + offr && offr != LSB)
7534 emitcode ("xch", "a,%s",
7535 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7537 aopPut (AOP (result), "a", MSB24 + offr);
7540 if (size > MSB32 + offr)
7542 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7544 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7547 emitcode ("rlc", "a");
7548 aopPut (AOP (result), "a", MSB32 + offr);
7551 aopPut (AOP (result), zero, LSB);
7557 /*-----------------------------------------------------------------*/
7558 /* genlshFour - shift four byte by a known amount != 0 */
7559 /*-----------------------------------------------------------------*/
7561 genlshFour (operand * result, operand * left, int shCount)
7565 D (emitcode (";", "genlshFour ");
7568 size = AOP_SIZE (result);
7570 /* if shifting more that 3 bytes */
7575 /* lowest order of left goes to the highest
7576 order of the destination */
7577 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7579 movLeft2Result (left, LSB, result, MSB32, 0);
7580 aopPut (AOP (result), zero, LSB);
7581 aopPut (AOP (result), zero, MSB16);
7582 aopPut (AOP (result), zero, MSB24);
7586 /* more than two bytes */
7587 else if (shCount >= 16)
7589 /* lower order two bytes goes to higher order two bytes */
7591 /* if some more remaining */
7593 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7596 movLeft2Result (left, MSB16, result, MSB32, 0);
7597 movLeft2Result (left, LSB, result, MSB24, 0);
7599 aopPut (AOP (result), zero, MSB16);
7600 aopPut (AOP (result), zero, LSB);
7604 /* if more than 1 byte */
7605 else if (shCount >= 8)
7607 /* lower order three bytes goes to higher order three bytes */
7612 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7614 movLeft2Result (left, LSB, result, MSB16, 0);
7620 movLeft2Result (left, MSB24, result, MSB32, 0);
7621 movLeft2Result (left, MSB16, result, MSB24, 0);
7622 movLeft2Result (left, LSB, result, MSB16, 0);
7623 aopPut (AOP (result), zero, LSB);
7625 else if (shCount == 1)
7626 shiftLLong (left, result, MSB16);
7629 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7630 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7631 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7632 aopPut (AOP (result), zero, LSB);
7637 /* 1 <= shCount <= 7 */
7638 else if (shCount <= 2)
7640 shiftLLong (left, result, LSB);
7642 shiftLLong (result, result, LSB);
7644 /* 3 <= shCount <= 7, optimize */
7647 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7648 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7649 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7654 #ifdef BETTER_LITERAL_SHIFT
7655 /*-----------------------------------------------------------------*/
7656 /* genLeftShiftLiteral - left shifting by known count */
7657 /*-----------------------------------------------------------------*/
7659 genLeftShiftLiteral (operand * left,
7664 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7667 size = getSize (operandType (result));
7669 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7671 /* We only handle certain easy cases so far. */
7673 && (shCount < (size * 8))
7677 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7681 freeAsmop (right, NULL, ic, TRUE);
7683 aopOp(left, ic, FALSE, FALSE);
7684 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7687 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7689 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7690 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7692 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7695 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7697 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7698 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7700 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7706 emitcode ("; shift left ", "result %d, left %d", size,
7710 /* I suppose that the left size >= result size */
7713 _startLazyDPSEvaluation();
7716 movLeft2Result (left, size, result, size, 0);
7718 _endLazyDPSEvaluation();
7720 else if (shCount >= (size * 8))
7722 _startLazyDPSEvaluation();
7725 aopPut (AOP (result), zero, size);
7727 _endLazyDPSEvaluation();
7734 genlshOne (result, left, shCount);
7738 genlshTwo (result, left, shCount);
7742 genlshFour (result, left, shCount);
7746 fprintf(stderr, "*** ack! mystery literal shift!\n");
7750 freeAsmop (left, NULL, ic, TRUE);
7751 freeAsmop (result, NULL, ic, TRUE);
7756 /*-----------------------------------------------------------------*/
7757 /* genLeftShift - generates code for left shifting */
7758 /*-----------------------------------------------------------------*/
7760 genLeftShift (iCode * ic)
7762 operand *left, *right, *result;
7765 symbol *tlbl, *tlbl1;
7767 D (emitcode (";", "genLeftShift "););
7769 right = IC_RIGHT (ic);
7770 left = IC_LEFT (ic);
7771 result = IC_RESULT (ic);
7773 aopOp (right, ic, FALSE, FALSE);
7776 #ifdef BETTER_LITERAL_SHIFT
7777 /* if the shift count is known then do it
7778 as efficiently as possible */
7779 if (AOP_TYPE (right) == AOP_LIT)
7781 if (genLeftShiftLiteral (left, right, result, ic))
7788 /* shift count is unknown then we have to form
7789 a loop get the loop count in B : Note: we take
7790 only the lower order byte since shifting
7791 more that 32 bits make no sense anyway, ( the
7792 largest size of an object can be only 32 bits ) */
7794 if (AOP_TYPE (right) == AOP_LIT)
7796 /* Really should be handled by genLeftShiftLiteral,
7797 * but since I'm too lazy to fix that today, at least we can make
7798 * some small improvement.
7800 emitcode("mov", "b,#0x%02x",
7801 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7805 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7806 emitcode ("inc", "b");
7808 freeAsmop (right, NULL, ic, TRUE);
7809 aopOp (left, ic, FALSE, FALSE);
7810 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7812 /* now move the left to the result if they are not the
7814 if (!sameRegs (AOP (left), AOP (result)) &&
7815 AOP_SIZE (result) > 1)
7818 size = AOP_SIZE (result);
7820 _startLazyDPSEvaluation ();
7823 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7824 if (*l == '@' && (IS_AOP_PREG (result)))
7827 emitcode ("mov", "a,%s", l);
7828 aopPut (AOP (result), "a", offset);
7831 aopPut (AOP (result), l, offset);
7834 _endLazyDPSEvaluation ();
7837 tlbl = newiTempLabel (NULL);
7838 size = AOP_SIZE (result);
7840 tlbl1 = newiTempLabel (NULL);
7842 /* if it is only one byte then */
7845 symbol *tlbl1 = newiTempLabel (NULL);
7847 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7849 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7850 emitcode ("", "%05d$:", tlbl->key + 100);
7851 emitcode ("add", "a,acc");
7852 emitcode ("", "%05d$:", tlbl1->key + 100);
7853 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7854 aopPut (AOP (result), "a", 0);
7858 reAdjustPreg (AOP (result));
7860 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7861 emitcode ("", "%05d$:", tlbl->key + 100);
7862 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7864 emitcode ("add", "a,acc");
7865 aopPut (AOP (result), "a", offset++);
7866 _startLazyDPSEvaluation ();
7869 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7871 emitcode ("rlc", "a");
7872 aopPut (AOP (result), "a", offset++);
7874 _endLazyDPSEvaluation ();
7875 reAdjustPreg (AOP (result));
7877 emitcode ("", "%05d$:", tlbl1->key + 100);
7878 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7880 freeAsmop (left, NULL, ic, TRUE);
7881 freeAsmop (result, NULL, ic, TRUE);
7884 #ifdef BETTER_LITERAL_SHIFT
7885 /*-----------------------------------------------------------------*/
7886 /* genrshOne - right shift a one byte quantity by known count */
7887 /*-----------------------------------------------------------------*/
7889 genrshOne (operand * result, operand * left,
7890 int shCount, int sign)
7892 D (emitcode (";", "genrshOne"););
7893 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7897 #ifdef BETTER_LITERAL_SHIFT
7898 /*-----------------------------------------------------------------*/
7899 /* genrshTwo - right shift two bytes by known amount != 0 */
7900 /*-----------------------------------------------------------------*/
7902 genrshTwo (operand * result, operand * left,
7903 int shCount, int sign)
7905 D (emitcode (";", "genrshTwo"););
7907 /* if shCount >= 8 */
7911 _startLazyDPSEvaluation();
7914 shiftR1Left2Result (left, MSB16, result, LSB,
7919 movLeft2Result (left, MSB16, result, LSB, sign);
7921 addSign (result, MSB16, sign);
7922 _endLazyDPSEvaluation();
7925 /* 1 <= shCount <= 7 */
7928 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7935 /*-----------------------------------------------------------------*/
7936 /* shiftRLong - shift right one long from left to result */
7937 /* offl = LSB or MSB16 */
7938 /*-----------------------------------------------------------------*/
7940 shiftRLong (operand * left, int offl,
7941 operand * result, int sign)
7943 int isSameRegs=sameRegs(AOP(left),AOP(result));
7945 if (isSameRegs && offl>1) {
7946 // we are in big trouble, but this shouldn't happen
7947 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7950 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7955 emitcode ("rlc", "a");
7956 emitcode ("subb", "a,acc");
7957 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7959 aopPut (AOP(result), zero, MSB32);
7964 emitcode ("clr", "c");
7966 emitcode ("mov", "c,acc.7");
7969 emitcode ("rrc", "a");
7971 if (isSameRegs && offl==MSB16) {
7972 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7974 aopPut (AOP (result), "a", MSB32);
7975 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7978 emitcode ("rrc", "a");
7979 if (isSameRegs && offl==1) {
7980 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7982 aopPut (AOP (result), "a", MSB24);
7983 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7985 emitcode ("rrc", "a");
7986 aopPut (AOP (result), "a", MSB16 - offl);
7990 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7991 emitcode ("rrc", "a");
7992 aopPut (AOP (result), "a", LSB);
7999 /*-----------------------------------------------------------------*/
8000 /* genrshFour - shift four byte by a known amount != 0 */
8001 /*-----------------------------------------------------------------*/
8003 genrshFour (operand * result, operand * left,
8004 int shCount, int sign)
8006 D (emitcode (";", "genrshFour");
8009 /* if shifting more that 3 bytes */
8014 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8016 movLeft2Result (left, MSB32, result, LSB, sign);
8017 addSign (result, MSB16, sign);
8019 else if (shCount >= 16)
8023 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8026 movLeft2Result (left, MSB24, result, LSB, 0);
8027 movLeft2Result (left, MSB32, result, MSB16, sign);
8029 addSign (result, MSB24, sign);
8031 else if (shCount >= 8)
8035 shiftRLong (left, MSB16, result, sign);
8036 else if (shCount == 0)
8038 movLeft2Result (left, MSB16, result, LSB, 0);
8039 movLeft2Result (left, MSB24, result, MSB16, 0);
8040 movLeft2Result (left, MSB32, result, MSB24, sign);
8041 addSign (result, MSB32, sign);
8045 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8046 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8047 /* the last shift is signed */
8048 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8049 addSign (result, MSB32, sign);
8053 { /* 1 <= shCount <= 7 */
8056 shiftRLong (left, LSB, result, sign);
8058 shiftRLong (result, LSB, result, sign);
8062 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8063 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8064 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8070 #ifdef BETTER_LITERAL_SHIFT
8071 /*-----------------------------------------------------------------*/
8072 /* genRightShiftLiteral - right shifting by known count */
8073 /*-----------------------------------------------------------------*/
8075 genRightShiftLiteral (operand * left,
8081 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8084 size = getSize (operandType (result));
8086 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8088 /* We only handle certain easy cases so far. */
8090 && (shCount < (size * 8))
8094 D(emitcode (";", "genRightShiftLiteral wimping out"););
8098 freeAsmop (right, NULL, ic, TRUE);
8100 aopOp (left, ic, FALSE, FALSE);
8101 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8104 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8108 /* test the LEFT size !!! */
8110 /* I suppose that the left size >= result size */
8113 size = getDataSize (result);
8114 _startLazyDPSEvaluation();
8117 movLeft2Result (left, size, result, size, 0);
8119 _endLazyDPSEvaluation();
8121 else if (shCount >= (size * 8))
8125 /* get sign in acc.7 */
8126 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8128 addSign (result, LSB, sign);
8135 genrshOne (result, left, shCount, sign);
8139 genrshTwo (result, left, shCount, sign);
8143 genrshFour (result, left, shCount, sign);
8150 freeAsmop (left, NULL, ic, TRUE);
8151 freeAsmop (result, NULL, ic, TRUE);
8157 /*-----------------------------------------------------------------*/
8158 /* genSignedRightShift - right shift of signed number */
8159 /*-----------------------------------------------------------------*/
8161 genSignedRightShift (iCode * ic)
8163 operand *right, *left, *result;
8166 symbol *tlbl, *tlbl1;
8168 D (emitcode (";", "genSignedRightShift "););
8170 /* we do it the hard way put the shift count in b
8171 and loop thru preserving the sign */
8173 right = IC_RIGHT (ic);
8174 left = IC_LEFT (ic);
8175 result = IC_RESULT (ic);
8177 aopOp (right, ic, FALSE, FALSE);
8179 #ifdef BETTER_LITERAL_SHIFT
8180 if (AOP_TYPE (right) == AOP_LIT)
8182 if (genRightShiftLiteral (left, right, result, ic, 1))
8188 /* shift count is unknown then we have to form
8189 a loop get the loop count in B : Note: we take
8190 only the lower order byte since shifting
8191 more that 32 bits make no sense anyway, ( the
8192 largest size of an object can be only 32 bits ) */
8194 if (AOP_TYPE (right) == AOP_LIT)
8196 /* Really should be handled by genRightShiftLiteral,
8197 * but since I'm too lazy to fix that today, at least we can make
8198 * some small improvement.
8200 emitcode("mov", "b,#0x%02x",
8201 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8205 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8206 emitcode ("inc", "b");
8208 freeAsmop (right, NULL, ic, TRUE);
8209 aopOp (left, ic, FALSE, FALSE);
8210 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8212 /* now move the left to the result if they are not the
8214 if (!sameRegs (AOP (left), AOP (result)) &&
8215 AOP_SIZE (result) > 1)
8218 size = AOP_SIZE (result);
8220 _startLazyDPSEvaluation ();
8223 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8224 if (*l == '@' && IS_AOP_PREG (result))
8227 emitcode ("mov", "a,%s", l);
8228 aopPut (AOP (result), "a", offset);
8231 aopPut (AOP (result), l, offset);
8234 _endLazyDPSEvaluation ();
8237 /* mov the highest order bit to OVR */
8238 tlbl = newiTempLabel (NULL);
8239 tlbl1 = newiTempLabel (NULL);
8241 size = AOP_SIZE (result);
8243 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8244 emitcode ("rlc", "a");
8245 emitcode ("mov", "ov,c");
8246 /* if it is only one byte then */
8249 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8251 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8252 emitcode ("", "%05d$:", tlbl->key + 100);
8253 emitcode ("mov", "c,ov");
8254 emitcode ("rrc", "a");
8255 emitcode ("", "%05d$:", tlbl1->key + 100);
8256 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8257 aopPut (AOP (result), "a", 0);
8261 reAdjustPreg (AOP (result));
8262 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8263 emitcode ("", "%05d$:", tlbl->key + 100);
8264 emitcode ("mov", "c,ov");
8265 _startLazyDPSEvaluation ();
8268 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8270 emitcode ("rrc", "a");
8271 aopPut (AOP (result), "a", offset--);
8273 _endLazyDPSEvaluation ();
8274 reAdjustPreg (AOP (result));
8275 emitcode ("", "%05d$:", tlbl1->key + 100);
8276 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8279 freeAsmop (left, NULL, ic, TRUE);
8280 freeAsmop (result, NULL, ic, TRUE);
8283 /*-----------------------------------------------------------------*/
8284 /* genRightShift - generate code for right shifting */
8285 /*-----------------------------------------------------------------*/
8287 genRightShift (iCode * ic)
8289 operand *right, *left, *result;
8293 symbol *tlbl, *tlbl1;
8295 D (emitcode (";", "genRightShift "););
8297 /* if signed then we do it the hard way preserve the
8298 sign bit moving it inwards */
8299 retype = getSpec (operandType (IC_RESULT (ic)));
8301 if (!SPEC_USIGN (retype))
8303 genSignedRightShift (ic);
8307 /* signed & unsigned types are treated the same : i.e. the
8308 signed is NOT propagated inwards : quoting from the
8309 ANSI - standard : "for E1 >> E2, is equivalent to division
8310 by 2**E2 if unsigned or if it has a non-negative value,
8311 otherwise the result is implementation defined ", MY definition
8312 is that the sign does not get propagated */
8314 right = IC_RIGHT (ic);
8315 left = IC_LEFT (ic);
8316 result = IC_RESULT (ic);
8318 aopOp (right, ic, FALSE, FALSE);
8320 #ifdef BETTER_LITERAL_SHIFT
8321 /* if the shift count is known then do it
8322 as efficiently as possible */
8323 if (AOP_TYPE (right) == AOP_LIT)
8325 if (genRightShiftLiteral (left, right, result, ic, 0))
8332 /* shift count is unknown then we have to form
8333 a loop get the loop count in B : Note: we take
8334 only the lower order byte since shifting
8335 more that 32 bits make no sense anyway, ( the
8336 largest size of an object can be only 32 bits ) */
8338 if (AOP_TYPE (right) == AOP_LIT)
8340 /* Really should be handled by genRightShiftLiteral,
8341 * but since I'm too lazy to fix that today, at least we can make
8342 * some small improvement.
8344 emitcode("mov", "b,#0x%02x",
8345 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8349 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8350 emitcode ("inc", "b");
8352 freeAsmop (right, NULL, ic, TRUE);
8353 aopOp (left, ic, FALSE, FALSE);
8354 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8356 /* now move the left to the result if they are not the
8358 if (!sameRegs (AOP (left), AOP (result)) &&
8359 AOP_SIZE (result) > 1)
8362 size = AOP_SIZE (result);
8364 _startLazyDPSEvaluation ();
8367 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8368 if (*l == '@' && IS_AOP_PREG (result))
8371 emitcode ("mov", "a,%s", l);
8372 aopPut (AOP (result), "a", offset);
8375 aopPut (AOP (result), l, offset);
8378 _endLazyDPSEvaluation ();
8381 tlbl = newiTempLabel (NULL);
8382 tlbl1 = newiTempLabel (NULL);
8383 size = AOP_SIZE (result);
8386 /* if it is only one byte then */
8389 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8391 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8392 emitcode ("", "%05d$:", tlbl->key + 100);
8394 emitcode ("rrc", "a");
8395 emitcode ("", "%05d$:", tlbl1->key + 100);
8396 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8397 aopPut (AOP (result), "a", 0);
8401 reAdjustPreg (AOP (result));
8402 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8403 emitcode ("", "%05d$:", tlbl->key + 100);
8405 _startLazyDPSEvaluation ();
8408 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8410 emitcode ("rrc", "a");
8411 aopPut (AOP (result), "a", offset--);
8413 _endLazyDPSEvaluation ();
8414 reAdjustPreg (AOP (result));
8416 emitcode ("", "%05d$:", tlbl1->key + 100);
8417 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8420 freeAsmop (left, NULL, ic, TRUE);
8421 freeAsmop (result, NULL, ic, TRUE);
8424 /*-----------------------------------------------------------------*/
8425 /* genUnpackBits - generates code for unpacking bits */
8426 /*-----------------------------------------------------------------*/
8428 genUnpackBits (operand * result, char *rname, int ptype)
8435 D (emitcode (";", "genUnpackBits ");
8438 etype = getSpec (operandType (result));
8440 /* read the first byte */
8446 emitcode ("mov", "a,@%s", rname);
8450 emitcode ("movx", "a,@%s", rname);
8454 emitcode ("movx", "a,@dptr");
8458 emitcode ("clr", "a");
8459 emitcode ("movc", "a,@a+dptr");
8463 emitcode ("lcall", "__gptrget");
8467 /* if we have bitdisplacement then it fits */
8468 /* into this byte completely or if length is */
8469 /* less than a byte */
8470 if ((shCnt = SPEC_BSTR (etype)) ||
8471 (SPEC_BLEN (etype) <= 8))
8474 /* shift right acc */
8477 emitcode ("anl", "a,#0x%02x",
8478 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8479 aopPut (AOP (result), "a", offset);
8483 /* bit field did not fit in a byte */
8484 rlen = SPEC_BLEN (etype) - 8;
8485 aopPut (AOP (result), "a", offset++);
8494 emitcode ("inc", "%s", rname);
8495 emitcode ("mov", "a,@%s", rname);
8499 emitcode ("inc", "%s", rname);
8500 emitcode ("movx", "a,@%s", rname);
8504 emitcode ("inc", "dptr");
8505 emitcode ("movx", "a,@dptr");
8509 emitcode ("clr", "a");
8510 emitcode ("inc", "dptr");
8511 emitcode ("movc", "a,@a+dptr");
8515 emitcode ("inc", "dptr");
8516 emitcode ("lcall", "__gptrget");
8521 /* if we are done */
8525 aopPut (AOP (result), "a", offset++);
8531 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
8532 aopPut (AOP (result), "a", offset);
8539 /*-----------------------------------------------------------------*/
8540 /* genDataPointerGet - generates code when ptr offset is known */
8541 /*-----------------------------------------------------------------*/
8543 genDataPointerGet (operand * left,
8549 int size, offset = 0;
8550 aopOp (result, ic, TRUE, FALSE);
8552 /* get the string representation of the name */
8553 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8554 size = AOP_SIZE (result);
8555 _startLazyDPSEvaluation ();
8559 sprintf (buffer, "(%s + %d)", l + 1, offset);
8561 sprintf (buffer, "%s", l + 1);
8562 aopPut (AOP (result), buffer, offset++);
8564 _endLazyDPSEvaluation ();
8566 freeAsmop (left, NULL, ic, TRUE);
8567 freeAsmop (result, NULL, ic, TRUE);
8570 /*-----------------------------------------------------------------*/
8571 /* genNearPointerGet - emitcode for near pointer fetch */
8572 /*-----------------------------------------------------------------*/
8574 genNearPointerGet (operand * left,
8582 sym_link *rtype, *retype, *letype;
8583 sym_link *ltype = operandType (left);
8586 rtype = operandType (result);
8587 retype = getSpec (rtype);
8588 letype = getSpec (ltype);
8590 aopOp (left, ic, FALSE, FALSE);
8592 /* if left is rematerialisable and
8593 result is not bit variable type and
8594 the left is pointer to data space i.e
8595 lower 128 bytes of space */
8596 if (AOP_TYPE (left) == AOP_IMMD &&
8597 !IS_BITVAR (retype) &&
8598 !IS_BITVAR (letype) &&
8599 DCL_TYPE (ltype) == POINTER)
8601 genDataPointerGet (left, result, ic);
8605 /* if the value is already in a pointer register
8606 then don't need anything more */
8607 if (!AOP_INPREG (AOP (left)))
8609 /* otherwise get a free pointer register */
8611 preg = getFreePtr (ic, &aop, FALSE);
8612 emitcode ("mov", "%s,%s",
8614 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8618 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8620 freeAsmop (left, NULL, ic, TRUE);
8621 aopOp (result, ic, FALSE, FALSE);
8623 /* if bitfield then unpack the bits */
8624 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8625 genUnpackBits (result, rname, POINTER);
8628 /* we have can just get the values */
8629 int size = AOP_SIZE (result);
8634 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8637 emitcode ("mov", "a,@%s", rname);
8638 aopPut (AOP (result), "a", offset);
8642 sprintf (buffer, "@%s", rname);
8643 aopPut (AOP (result), buffer, offset);
8647 emitcode ("inc", "%s", rname);
8651 /* now some housekeeping stuff */
8654 /* we had to allocate for this iCode */
8655 if (pi) { /* post increment present */
8656 aopPut(AOP ( left ),rname,0);
8658 freeAsmop (NULL, aop, ic, TRUE);
8662 /* we did not allocate which means left
8663 already in a pointer register, then
8664 if size > 0 && this could be used again
8665 we have to point it back to where it
8667 if (AOP_SIZE (result) > 1 &&
8668 !OP_SYMBOL (left)->remat &&
8669 (OP_SYMBOL (left)->liveTo > ic->seq ||
8673 int size = AOP_SIZE (result) - 1;
8675 emitcode ("dec", "%s", rname);
8680 freeAsmop (result, NULL, ic, TRUE);
8681 if (pi) pi->generated = 1;
8684 /*-----------------------------------------------------------------*/
8685 /* genPagedPointerGet - emitcode for paged pointer fetch */
8686 /*-----------------------------------------------------------------*/
8688 genPagedPointerGet (operand * left,
8696 sym_link *rtype, *retype, *letype;
8698 rtype = operandType (result);
8699 retype = getSpec (rtype);
8700 letype = getSpec (operandType (left));
8701 aopOp (left, ic, FALSE, FALSE);
8703 /* if the value is already in a pointer register
8704 then don't need anything more */
8705 if (!AOP_INPREG (AOP (left)))
8707 /* otherwise get a free pointer register */
8709 preg = getFreePtr (ic, &aop, FALSE);
8710 emitcode ("mov", "%s,%s",
8712 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8716 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8718 freeAsmop (left, NULL, ic, TRUE);
8719 aopOp (result, ic, FALSE, FALSE);
8721 /* if bitfield then unpack the bits */
8722 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8723 genUnpackBits (result, rname, PPOINTER);
8726 /* we have can just get the values */
8727 int size = AOP_SIZE (result);
8733 emitcode ("movx", "a,@%s", rname);
8734 aopPut (AOP (result), "a", offset);
8739 emitcode ("inc", "%s", rname);
8743 /* now some housekeeping stuff */
8746 /* we had to allocate for this iCode */
8747 if (pi) aopPut ( AOP (left), rname, 0);
8748 freeAsmop (NULL, aop, ic, TRUE);
8752 /* we did not allocate which means left
8753 already in a pointer register, then
8754 if size > 0 && this could be used again
8755 we have to point it back to where it
8757 if (AOP_SIZE (result) > 1 &&
8758 !OP_SYMBOL (left)->remat &&
8759 (OP_SYMBOL (left)->liveTo > ic->seq ||
8763 int size = AOP_SIZE (result) - 1;
8765 emitcode ("dec", "%s", rname);
8770 freeAsmop (result, NULL, ic, TRUE);
8771 if (pi) pi->generated = 1;
8774 /*-----------------------------------------------------------------*/
8775 /* genFarPointerGet - gget value from far space */
8776 /*-----------------------------------------------------------------*/
8778 genFarPointerGet (operand * left,
8779 operand * result, iCode * ic, iCode *pi)
8782 sym_link *retype = getSpec (operandType (result));
8783 sym_link *letype = getSpec (operandType (left));
8784 D (emitcode (";", "genFarPointerGet");
8787 aopOp (left, ic, FALSE, FALSE);
8789 /* if the operand is already in dptr
8790 then we do nothing else we move the value to dptr */
8791 if (AOP_TYPE (left) != AOP_STR)
8793 /* if this is remateriazable */
8794 if (AOP_TYPE (left) == AOP_IMMD)
8796 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8800 /* we need to get it byte by byte */
8801 _startLazyDPSEvaluation ();
8802 if (AOP_TYPE (left) != AOP_DPTR)
8804 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8805 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8806 if (options.model == MODEL_FLAT24)
8807 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8811 /* We need to generate a load to DPTR indirect through DPTR. */
8812 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8814 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8815 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8816 if (options.model == MODEL_FLAT24)
8817 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8818 emitcode ("pop", "dph");
8819 emitcode ("pop", "dpl");
8821 _endLazyDPSEvaluation ();
8824 /* so dptr know contains the address */
8825 freeAsmop (left, NULL, ic, TRUE);
8826 aopOp (result, ic, FALSE, TRUE);
8828 /* if bit then unpack */
8829 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8830 genUnpackBits (result, "dptr", FPOINTER);
8833 size = AOP_SIZE (result);
8836 _startLazyDPSEvaluation ();
8843 emitcode ("movx", "a,@dptr");
8844 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
8845 emitcode ("inc", "dptr");
8847 aopPut (AOP (result), "a", offset++);
8849 _endLazyDPSEvaluation ();
8851 if (pi && AOP_TYPE (left) != AOP_IMMD) {
8852 aopPut ( AOP (left), "dpl", 0);
8853 aopPut ( AOP (left), "dph", 1);
8854 if (options.model == MODEL_FLAT24)
8855 aopPut ( AOP (left), "dpx", 2);
8859 freeAsmop (result, NULL, ic, TRUE);
8862 /*-----------------------------------------------------------------*/
8863 /* emitcodePointerGet - gget value from code space */
8864 /*-----------------------------------------------------------------*/
8866 emitcodePointerGet (operand * left,
8867 operand * result, iCode * ic, iCode *pi)
8870 sym_link *retype = getSpec (operandType (result));
8872 aopOp (left, ic, FALSE, FALSE);
8874 /* if the operand is already in dptr
8875 then we do nothing else we move the value to dptr */
8876 if (AOP_TYPE (left) != AOP_STR)
8878 /* if this is remateriazable */
8879 if (AOP_TYPE (left) == AOP_IMMD)
8881 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8884 { /* we need to get it byte by byte */
8885 _startLazyDPSEvaluation ();
8886 if (AOP_TYPE (left) != AOP_DPTR)
8888 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8889 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8890 if (options.model == MODEL_FLAT24)
8891 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8895 /* We need to generate a load to DPTR indirect through DPTR. */
8896 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8898 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8899 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8900 if (options.model == MODEL_FLAT24)
8901 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8902 emitcode ("pop", "dph");
8903 emitcode ("pop", "dpl");
8905 _endLazyDPSEvaluation ();
8908 /* so dptr know contains the address */
8909 aopOp (result, ic, FALSE, TRUE);
8911 /* if bit then unpack */
8912 if (IS_BITVAR (retype))
8913 genUnpackBits (result, "dptr", CPOINTER);
8916 size = AOP_SIZE (result);
8919 _startLazyDPSEvaluation ();
8925 emitcode ("clr", "a");
8926 emitcode ("movc", "a,@a+dptr");
8927 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
8928 emitcode ("inc", "dptr");
8929 aopPut (AOP (result), "a", offset++);
8931 _endLazyDPSEvaluation ();
8933 if (pi && AOP_TYPE (left) != AOP_IMMD) {
8934 aopPut ( AOP (left), "dpl", 0);
8935 aopPut ( AOP (left), "dph", 1);
8936 if (options.model == MODEL_FLAT24)
8937 aopPut ( AOP (left), "dpx", 2);
8941 freeAsmop (left, NULL, ic, TRUE);
8942 freeAsmop (result, NULL, ic, TRUE);
8945 /*-----------------------------------------------------------------*/
8946 /* genGenPointerGet - gget value from generic pointer space */
8947 /*-----------------------------------------------------------------*/
8949 genGenPointerGet (operand * left,
8950 operand * result, iCode * ic, iCode * pi)
8953 sym_link *retype = getSpec (operandType (result));
8954 sym_link *letype = getSpec (operandType (left));
8956 D (emitcode (";", "genGenPointerGet "); );
8958 aopOp (left, ic, FALSE, (OP_SYMBOL(left)->ruonly ? FALSE : TRUE));
8960 /* if the operand is already in dptr
8961 then we do nothing else we move the value to dptr */
8962 if (AOP_TYPE (left) != AOP_STR)
8964 /* if this is remateriazable */
8965 if (AOP_TYPE (left) == AOP_IMMD)
8967 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8968 if (AOP(left)->aopu.aop_immd.from_cast_remat)
8969 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
8971 emitcode ("mov", "b,#%d", pointerCode (retype));
8974 { /* we need to get it byte by byte */
8975 _startLazyDPSEvaluation ();
8976 if (AOP(left)->type==AOP_DPTR2) {
8978 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8981 emitcode ("mov", "dpl,%s", l);
8982 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8985 emitcode ("mov", "dph,%s", l);
8986 if (options.model == MODEL_FLAT24) {
8987 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8990 emitcode ("mov", "dpx,%s", l);
8991 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8993 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8996 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8997 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8998 if (options.model == MODEL_FLAT24) {
8999 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9000 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9002 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9005 _endLazyDPSEvaluation ();
9008 /* so dptr know contains the address */
9009 aopOp (result, ic, FALSE, TRUE);
9011 /* if bit then unpack */
9012 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9013 genUnpackBits (result, "dptr", GPOINTER);
9016 size = AOP_SIZE (result);
9021 emitcode ("lcall", "__gptrget");
9022 aopPut (AOP (result), "a", offset++);
9023 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9024 emitcode ("inc", "dptr");
9028 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9029 aopPut ( AOP (left), "dpl", 0);
9030 aopPut ( AOP (left), "dph", 1);
9031 if (options.model == MODEL_FLAT24) {
9032 aopPut ( AOP (left), "dpx", 2);
9033 aopPut ( AOP (left), "b", 3);
9034 } else aopPut ( AOP (left), "b", 2);
9037 freeAsmop (left, NULL, ic, TRUE);
9038 freeAsmop (result, NULL, ic, TRUE);
9041 /*-----------------------------------------------------------------*/
9042 /* genPointerGet - generate code for pointer get */
9043 /*-----------------------------------------------------------------*/
9045 genPointerGet (iCode * ic, iCode *pi)
9047 operand *left, *result;
9048 sym_link *type, *etype;
9051 D (emitcode (";", "genPointerGet ");
9054 left = IC_LEFT (ic);
9055 result = IC_RESULT (ic);
9057 /* depending on the type of pointer we need to
9058 move it to the correct pointer register */
9059 type = operandType (left);
9060 etype = getSpec (type);
9061 /* if left is of type of pointer then it is simple */
9062 if (IS_PTR (type) && !IS_FUNC (type->next))
9063 p_type = DCL_TYPE (type);
9066 /* we have to go by the storage class */
9067 p_type = PTR_TYPE (SPEC_OCLS (etype));
9069 /* special case when cast remat */
9070 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9071 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9072 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9073 type = type = operandType (left);
9074 p_type = DCL_TYPE (type);
9076 /* now that we have the pointer type we assign
9077 the pointer values */
9083 genNearPointerGet (left, result, ic, pi);
9087 genPagedPointerGet (left, result, ic, pi);
9091 genFarPointerGet (left, result, ic, pi);
9095 emitcodePointerGet (left, result, ic, pi);
9099 genGenPointerGet (left, result, ic, pi);
9105 /*-----------------------------------------------------------------*/
9106 /* genPackBits - generates code for packed bit storage */
9107 /*-----------------------------------------------------------------*/
9109 genPackBits (sym_link * etype,
9111 char *rname, int p_type)
9119 blen = SPEC_BLEN (etype);
9120 bstr = SPEC_BSTR (etype);
9122 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9125 /* if the bit lenth is less than or */
9126 /* it exactly fits a byte then */
9127 if (SPEC_BLEN (etype) <= 8)
9129 shCount = SPEC_BSTR (etype);
9131 /* shift left acc */
9134 if (SPEC_BLEN (etype) < 8)
9135 { /* if smaller than a byte */
9141 emitcode ("mov", "b,a");
9142 emitcode ("mov", "a,@%s", rname);
9146 emitcode ("mov", "b,a");
9147 emitcode ("movx", "a,@dptr");
9151 emitcode ("push", "b");
9152 emitcode ("push", "acc");
9153 emitcode ("lcall", "__gptrget");
9154 emitcode ("pop", "b");
9158 emitcode ("anl", "a,#0x%02x", (unsigned char)
9159 ((unsigned char) (0xFF << (blen + bstr)) |
9160 (unsigned char) (0xFF >> (8 - bstr))));
9161 emitcode ("orl", "a,b");
9162 if (p_type == GPOINTER)
9163 emitcode ("pop", "b");
9170 emitcode ("mov", "@%s,a", rname);
9174 emitcode ("movx", "@dptr,a");
9178 emitcode ("lcall", "__gptrput");
9183 if (SPEC_BLEN (etype) <= 8)
9186 emitcode ("inc", "%s", rname);
9187 rLen = SPEC_BLEN (etype);
9189 /* now generate for lengths greater than one byte */
9193 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9205 emitcode ("mov", "@%s,a", rname);
9208 emitcode ("mov", "@%s,%s", rname, l);
9213 emitcode ("movx", "@dptr,a");
9218 emitcode ("lcall", "__gptrput");
9221 emitcode ("inc", "%s", rname);
9226 /* last last was not complete */
9229 /* save the byte & read byte */
9233 emitcode ("mov", "b,a");
9234 emitcode ("mov", "a,@%s", rname);
9238 emitcode ("mov", "b,a");
9239 emitcode ("movx", "a,@dptr");
9243 emitcode ("push", "b");
9244 emitcode ("push", "acc");
9245 emitcode ("lcall", "__gptrget");
9246 emitcode ("pop", "b");
9250 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
9251 emitcode ("orl", "a,b");
9254 if (p_type == GPOINTER)
9255 emitcode ("pop", "b");
9261 emitcode ("mov", "@%s,a", rname);
9265 emitcode ("movx", "@dptr,a");
9269 emitcode ("lcall", "__gptrput");
9273 /*-----------------------------------------------------------------*/
9274 /* genDataPointerSet - remat pointer to data space */
9275 /*-----------------------------------------------------------------*/
9277 genDataPointerSet (operand * right,
9281 int size, offset = 0;
9282 char *l, buffer[256];
9284 aopOp (right, ic, FALSE, FALSE);
9286 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9287 size = AOP_SIZE (right);
9291 sprintf (buffer, "(%s + %d)", l + 1, offset);
9293 sprintf (buffer, "%s", l + 1);
9294 emitcode ("mov", "%s,%s", buffer,
9295 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9298 freeAsmop (right, NULL, ic, TRUE);
9299 freeAsmop (result, NULL, ic, TRUE);
9302 /*-----------------------------------------------------------------*/
9303 /* genNearPointerSet - emitcode for near pointer put */
9304 /*-----------------------------------------------------------------*/
9306 genNearPointerSet (operand * right,
9314 sym_link *retype, *letype;
9315 sym_link *ptype = operandType (result);
9317 retype = getSpec (operandType (right));
9318 letype = getSpec (ptype);
9320 aopOp (result, ic, FALSE, FALSE);
9322 /* if the result is rematerializable &
9323 in data space & not a bit variable */
9324 if (AOP_TYPE (result) == AOP_IMMD &&
9325 DCL_TYPE (ptype) == POINTER &&
9326 !IS_BITVAR (retype) &&
9327 !IS_BITVAR (letype))
9329 genDataPointerSet (right, result, ic);
9333 /* if the value is already in a pointer register
9334 then don't need anything more */
9335 if (!AOP_INPREG (AOP (result)))
9337 /* otherwise get a free pointer register */
9339 preg = getFreePtr (ic, &aop, FALSE);
9340 emitcode ("mov", "%s,%s",
9342 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9346 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9348 aopOp (right, ic, FALSE, FALSE);
9350 /* if bitfield then unpack the bits */
9351 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9352 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9355 /* we have can just get the values */
9356 int size = AOP_SIZE (right);
9361 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9365 emitcode ("mov", "@%s,a", rname);
9368 emitcode ("mov", "@%s,%s", rname, l);
9370 emitcode ("inc", "%s", rname);
9375 /* now some housekeeping stuff */
9378 /* we had to allocate for this iCode */
9379 if (pi) aopPut (AOP (result),rname,0);
9380 freeAsmop (NULL, aop, ic, TRUE);
9384 /* we did not allocate which means left
9385 already in a pointer register, then
9386 if size > 0 && this could be used again
9387 we have to point it back to where it
9389 if (AOP_SIZE (right) > 1 &&
9390 !OP_SYMBOL (result)->remat &&
9391 (OP_SYMBOL (result)->liveTo > ic->seq ||
9395 int size = AOP_SIZE (right) - 1;
9397 emitcode ("dec", "%s", rname);
9402 if (pi) pi->generated = 1;
9403 freeAsmop (result, NULL, ic, TRUE);
9404 freeAsmop (right, NULL, ic, TRUE);
9409 /*-----------------------------------------------------------------*/
9410 /* genPagedPointerSet - emitcode for Paged pointer put */
9411 /*-----------------------------------------------------------------*/
9413 genPagedPointerSet (operand * right,
9421 sym_link *retype, *letype;
9423 retype = getSpec (operandType (right));
9424 letype = getSpec (operandType (result));
9426 aopOp (result, ic, FALSE, FALSE);
9428 /* if the value is already in a pointer register
9429 then don't need anything more */
9430 if (!AOP_INPREG (AOP (result)))
9432 /* otherwise get a free pointer register */
9434 preg = getFreePtr (ic, &aop, FALSE);
9435 emitcode ("mov", "%s,%s",
9437 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9441 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9443 aopOp (right, ic, FALSE, FALSE);
9445 /* if bitfield then unpack the bits */
9446 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9447 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9450 /* we have can just get the values */
9451 int size = AOP_SIZE (right);
9456 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9459 emitcode ("movx", "@%s,a", rname);
9462 emitcode ("inc", "%s", rname);
9468 /* now some housekeeping stuff */
9471 if (pi) aopPut (AOP (result),rname,0);
9472 /* we had to allocate for this iCode */
9473 freeAsmop (NULL, aop, ic, TRUE);
9477 /* we did not allocate which means left
9478 already in a pointer register, then
9479 if size > 0 && this could be used again
9480 we have to point it back to where it
9482 if (AOP_SIZE (right) > 1 &&
9483 !OP_SYMBOL (result)->remat &&
9484 (OP_SYMBOL (result)->liveTo > ic->seq ||
9488 int size = AOP_SIZE (right) - 1;
9490 emitcode ("dec", "%s", rname);
9495 if (pi) pi->generated = 1;
9496 freeAsmop (result, NULL, ic, TRUE);
9497 freeAsmop (right, NULL, ic, TRUE);
9502 /*-----------------------------------------------------------------*/
9503 /* genFarPointerSet - set value from far space */
9504 /*-----------------------------------------------------------------*/
9506 genFarPointerSet (operand * right,
9507 operand * result, iCode * ic, iCode *pi)
9510 sym_link *retype = getSpec (operandType (right));
9511 sym_link *letype = getSpec (operandType (result));
9513 aopOp (result, ic, FALSE, FALSE);
9515 /* if the operand is already in dptr
9516 then we do nothing else we move the value to dptr */
9517 if (AOP_TYPE (result) != AOP_STR)
9519 /* if this is remateriazable */
9520 if (AOP_TYPE (result) == AOP_IMMD)
9521 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9524 /* we need to get it byte by byte */
9525 _startLazyDPSEvaluation ();
9526 if (AOP_TYPE (result) != AOP_DPTR)
9528 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9529 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9530 if (options.model == MODEL_FLAT24)
9531 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9535 /* We need to generate a load to DPTR indirect through DPTR. */
9536 D (emitcode (";", "genFarPointerSet -- indirection special case.");
9538 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9539 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9540 if (options.model == MODEL_FLAT24)
9541 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9542 emitcode ("pop", "dph");
9543 emitcode ("pop", "dpl");
9545 _endLazyDPSEvaluation ();
9548 /* so dptr know contains the address */
9549 aopOp (right, ic, FALSE, TRUE);
9551 /* if bit then unpack */
9552 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9553 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9556 size = AOP_SIZE (right);
9559 _startLazyDPSEvaluation ();
9562 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9568 emitcode ("movx", "@dptr,a");
9569 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
9570 emitcode ("inc", "dptr");
9572 _endLazyDPSEvaluation ();
9575 if (pi && AOP_TYPE (result) != AOP_IMMD) {
9576 aopPut (AOP(result),"dpl",0);
9577 aopPut (AOP(result),"dph",1);
9578 if (options.model == MODEL_FLAT24)
9579 aopPut (AOP(result),"dpx",2);
9582 freeAsmop (result, NULL, ic, TRUE);
9583 freeAsmop (right, NULL, ic, TRUE);
9586 /*-----------------------------------------------------------------*/
9587 /* genGenPointerSet - set value from generic pointer space */
9588 /*-----------------------------------------------------------------*/
9590 genGenPointerSet (operand * right,
9591 operand * result, iCode * ic, iCode *pi)
9594 sym_link *retype = getSpec (operandType (right));
9595 sym_link *letype = getSpec (operandType (result));
9597 aopOp (result, ic, FALSE, OP_SYMBOL(result)->ruonly ? FALSE : TRUE);
9599 /* if the operand is already in dptr
9600 then we do nothing else we move the value to dptr */
9601 if (AOP_TYPE (result) != AOP_STR)
9603 _startLazyDPSEvaluation ();
9604 /* if this is remateriazable */
9605 if (AOP_TYPE (result) == AOP_IMMD)
9607 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9608 if (AOP(result)->aopu.aop_immd.from_cast_remat)
9609 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
9611 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9614 { /* we need to get it byte by byte */
9615 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9616 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9617 if (options.model == MODEL_FLAT24) {
9618 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9619 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9621 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9624 _endLazyDPSEvaluation ();
9626 /* so dptr know contains the address */
9627 aopOp (right, ic, FALSE, TRUE);
9629 /* if bit then unpack */
9630 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9631 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9634 size = AOP_SIZE (right);
9637 _startLazyDPSEvaluation ();
9640 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9646 emitcode ("lcall", "__gptrput");
9647 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
9648 emitcode ("inc", "dptr");
9650 _endLazyDPSEvaluation ();
9653 if (pi && AOP_TYPE (result) != AOP_IMMD) {
9654 aopPut (AOP(result),"dpl",0);
9655 aopPut (AOP(result),"dph",1);
9656 if (options.model == MODEL_FLAT24) {
9657 aopPut (AOP(result),"dpx",2);
9658 aopPut (AOP(result),"b",3);
9660 aopPut (AOP(result),"b",2);
9664 freeAsmop (result, NULL, ic, TRUE);
9665 freeAsmop (right, NULL, ic, TRUE);
9668 /*-----------------------------------------------------------------*/
9669 /* genPointerSet - stores the value into a pointer location */
9670 /*-----------------------------------------------------------------*/
9672 genPointerSet (iCode * ic, iCode *pi)
9674 operand *right, *result;
9675 sym_link *type, *etype;
9678 D (emitcode (";", "genPointerSet ");
9681 right = IC_RIGHT (ic);
9682 result = IC_RESULT (ic);
9684 /* depending on the type of pointer we need to
9685 move it to the correct pointer register */
9686 type = operandType (result);
9687 etype = getSpec (type);
9688 /* if left is of type of pointer then it is simple */
9689 if (IS_PTR (type) && !IS_FUNC (type->next))
9691 p_type = DCL_TYPE (type);
9695 /* we have to go by the storage class */
9696 p_type = PTR_TYPE (SPEC_OCLS (etype));
9698 /* special case when cast remat */
9699 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9700 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9701 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9702 type = type = operandType (result);
9703 p_type = DCL_TYPE (type);
9706 /* now that we have the pointer type we assign
9707 the pointer values */
9713 genNearPointerSet (right, result, ic, pi);
9717 genPagedPointerSet (right, result, ic, pi);
9721 genFarPointerSet (right, result, ic, pi);
9725 genGenPointerSet (right, result, ic, pi);
9731 /*-----------------------------------------------------------------*/
9732 /* genIfx - generate code for Ifx statement */
9733 /*-----------------------------------------------------------------*/
9735 genIfx (iCode * ic, iCode * popIc)
9737 operand *cond = IC_COND (ic);
9740 D (emitcode (";", "genIfx "););
9742 aopOp (cond, ic, FALSE, FALSE);
9744 /* get the value into acc */
9745 if (AOP_TYPE (cond) != AOP_CRY)
9749 /* the result is now in the accumulator */
9750 freeAsmop (cond, NULL, ic, TRUE);
9752 /* if there was something to be popped then do it */
9756 /* if the condition is a bit variable */
9757 if (isbit && IS_ITEMP (cond) &&
9759 genIfxJump (ic, SPIL_LOC (cond)->rname);
9760 else if (isbit && !IS_ITEMP (cond))
9761 genIfxJump (ic, OP_SYMBOL (cond)->rname);
9763 genIfxJump (ic, "a");
9768 /*-----------------------------------------------------------------*/
9769 /* genAddrOf - generates code for address of */
9770 /*-----------------------------------------------------------------*/
9772 genAddrOf (iCode * ic)
9774 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9777 D (emitcode (";", "genAddrOf ");
9780 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9782 /* if the operand is on the stack then we
9783 need to get the stack offset of this
9787 /* if it has an offset then we need to compute
9791 emitcode ("mov", "a,_bp");
9792 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9793 aopPut (AOP (IC_RESULT (ic)), "a", 0);
9797 /* we can just move _bp */
9798 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9800 /* fill the result with zero */
9801 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9804 if (options.stack10bit && size < (FPTRSIZE - 1))
9807 "*** warning: pointer to stack var truncated.\n");
9814 if (options.stack10bit && offset == 2)
9816 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
9820 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9827 /* object not on stack then we need the name */
9828 size = AOP_SIZE (IC_RESULT (ic));
9833 char s[SDCC_NAME_MAX];
9835 sprintf (s, "#(%s >> %d)",
9839 sprintf (s, "#%s", sym->rname);
9840 aopPut (AOP (IC_RESULT (ic)), s, offset++);
9844 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9848 /*-----------------------------------------------------------------*/
9849 /* genArrayInit - generates code for address of */
9850 /*-----------------------------------------------------------------*/
9852 genArrayInit (iCode * ic)
9856 int elementSize = 0, eIndex;
9857 unsigned val, lastVal;
9859 operand *left=IC_LEFT(ic);
9861 D (emitcode (";", "genArrayInit "););
9863 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
9865 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
9867 // Load immediate value into DPTR.
9868 emitcode("mov", "dptr, %s",
9869 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
9871 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
9874 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9875 "Unexpected operand to genArrayInit.\n");
9878 // a regression because of SDCCcse.c:1.52
9879 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9880 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9881 if (options.model == MODEL_FLAT24)
9882 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9886 type = operandType(IC_LEFT(ic));
9888 if (type && type->next)
9890 elementSize = getSize(type->next);
9894 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9895 "can't determine element size in genArrayInit.\n");
9899 iLoop = IC_ARRAYILIST(ic);
9904 bool firstpass = TRUE;
9906 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
9907 iLoop->count, (int)iLoop->literalValue, elementSize);
9913 symbol *tlbl = NULL;
9915 count = ix > 256 ? 256 : ix;
9919 tlbl = newiTempLabel (NULL);
9920 if (firstpass || (count & 0xff))
9922 emitcode("mov", "b, #0x%x", count & 0xff);
9925 emitcode ("", "%05d$:", tlbl->key + 100);
9930 for (eIndex = 0; eIndex < elementSize; eIndex++)
9932 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
9935 emitcode("mov", "a, #0x%x", val);
9939 emitcode("movx", "@dptr, a");
9940 emitcode("inc", "dptr");
9945 emitcode("djnz", "b, %05d$", tlbl->key + 100);
9951 iLoop = iLoop->next;
9954 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
9957 /*-----------------------------------------------------------------*/
9958 /* genFarFarAssign - assignment when both are in far space */
9959 /*-----------------------------------------------------------------*/
9961 genFarFarAssign (operand * result, operand * right, iCode * ic)
9963 int size = AOP_SIZE (right);
9965 symbol *rSym = NULL;
9969 /* quick & easy case. */
9970 D(emitcode(";","genFarFarAssign (1 byte case)"););
9971 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9972 freeAsmop (right, NULL, ic, FALSE);
9973 /* now assign DPTR to result */
9975 aopOp(result, ic, FALSE, FALSE);
9977 aopPut(AOP(result), "a", 0);
9978 freeAsmop(result, NULL, ic, FALSE);
9982 /* See if we've got an underlying symbol to abuse. */
9983 if (IS_SYMOP(result) && OP_SYMBOL(result))
9985 if (IS_TRUE_SYMOP(result))
9987 rSym = OP_SYMBOL(result);
9989 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9991 rSym = OP_SYMBOL(result)->usl.spillLoc;
9995 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9997 /* We can use the '390 auto-toggle feature to good effect here. */
9999 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10000 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
10001 emitcode ("mov", "dptr,#%s", rSym->rname);
10002 /* DP2 = result, DP1 = right, DP1 is current. */
10005 emitcode("movx", "a,@dptr");
10006 emitcode("movx", "@dptr,a");
10009 emitcode("inc", "dptr");
10010 emitcode("inc", "dptr");
10013 emitcode("mov", "dps, #0");
10014 freeAsmop (right, NULL, ic, FALSE);
10016 some alternative code for processors without auto-toggle
10017 no time to test now, so later well put in...kpb
10018 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10019 emitcode("mov", "dps, #0x01"); /* Select DPTR2. */
10020 emitcode ("mov", "dptr,#%s", rSym->rname);
10021 /* DP2 = result, DP1 = right, DP1 is current. */
10025 emitcode("movx", "a,@dptr");
10027 emitcode("inc", "dptr");
10028 emitcode("inc", "dps");
10029 emitcode("movx", "@dptr,a");
10031 emitcode("inc", "dptr");
10032 emitcode("inc", "dps");
10034 emitcode("mov", "dps, #0");
10035 freeAsmop (right, NULL, ic, FALSE);
10040 D (emitcode (";", "genFarFarAssign"););
10041 aopOp (result, ic, TRUE, TRUE);
10043 _startLazyDPSEvaluation ();
10047 aopPut (AOP (result),
10048 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10051 _endLazyDPSEvaluation ();
10052 freeAsmop (result, NULL, ic, FALSE);
10053 freeAsmop (right, NULL, ic, FALSE);
10057 /*-----------------------------------------------------------------*/
10058 /* genAssign - generate code for assignment */
10059 /*-----------------------------------------------------------------*/
10061 genAssign (iCode * ic)
10063 operand *result, *right;
10065 unsigned long lit = 0L;
10067 D (emitcode (";", "genAssign ");
10070 result = IC_RESULT (ic);
10071 right = IC_RIGHT (ic);
10073 /* if they are the same */
10074 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10077 aopOp (right, ic, FALSE, FALSE);
10079 emitcode (";", "genAssign: resultIsFar = %s",
10080 isOperandInFarSpace (result) ?
10083 /* special case both in far space */
10084 if ((AOP_TYPE (right) == AOP_DPTR ||
10085 AOP_TYPE (right) == AOP_DPTR2) &&
10086 /* IS_TRUE_SYMOP(result) && */
10087 isOperandInFarSpace (result))
10089 genFarFarAssign (result, right, ic);
10093 aopOp (result, ic, TRUE, FALSE);
10095 /* if they are the same registers */
10096 if (sameRegs (AOP (right), AOP (result)))
10099 /* if the result is a bit */
10100 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10102 /* if the right size is a literal then
10103 we know what the value is */
10104 if (AOP_TYPE (right) == AOP_LIT)
10106 if (((int) operandLitValue (right)))
10107 aopPut (AOP (result), one, 0);
10109 aopPut (AOP (result), zero, 0);
10113 /* the right is also a bit variable */
10114 if (AOP_TYPE (right) == AOP_CRY)
10116 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10117 aopPut (AOP (result), "c", 0);
10121 /* we need to or */
10123 aopPut (AOP (result), "a", 0);
10127 /* bit variables done */
10129 size = AOP_SIZE (result);
10131 if (AOP_TYPE (right) == AOP_LIT)
10132 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10135 (AOP_TYPE (result) != AOP_REG) &&
10136 (AOP_TYPE (right) == AOP_LIT) &&
10137 !IS_FLOAT (operandType (right)))
10139 _startLazyDPSEvaluation ();
10140 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10142 aopPut (AOP (result),
10143 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10148 /* And now fill the rest with zeros. */
10151 emitcode ("clr", "a");
10155 aopPut (AOP (result), "a", offset++);
10157 _endLazyDPSEvaluation ();
10161 _startLazyDPSEvaluation ();
10164 aopPut (AOP (result),
10165 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10169 _endLazyDPSEvaluation ();
10173 freeAsmop (right, NULL, ic, FALSE);
10174 freeAsmop (result, NULL, ic, TRUE);
10177 /*-----------------------------------------------------------------*/
10178 /* genJumpTab - generates code for jump table */
10179 /*-----------------------------------------------------------------*/
10181 genJumpTab (iCode * ic)
10186 D (emitcode (";", "genJumpTab ");
10189 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10190 /* get the condition into accumulator */
10191 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10193 /* multiply by four! */
10194 emitcode ("add", "a,acc");
10195 emitcode ("add", "a,acc");
10196 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10198 jtab = newiTempLabel (NULL);
10199 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10200 emitcode ("jmp", "@a+dptr");
10201 emitcode ("", "%05d$:", jtab->key + 100);
10202 /* now generate the jump labels */
10203 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10204 jtab = setNextItem (IC_JTLABELS (ic)))
10205 emitcode ("ljmp", "%05d$", jtab->key + 100);
10209 /*-----------------------------------------------------------------*/
10210 /* genCast - gen code for casting */
10211 /*-----------------------------------------------------------------*/
10213 genCast (iCode * ic)
10215 operand *result = IC_RESULT (ic);
10216 sym_link *ctype = operandType (IC_LEFT (ic));
10217 sym_link *rtype = operandType (IC_RIGHT (ic));
10218 operand *right = IC_RIGHT (ic);
10221 D (emitcode (";", "genCast ");
10224 /* if they are equivalent then do nothing */
10225 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10228 aopOp (right, ic, FALSE, FALSE);
10229 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10231 /* if the result is a bit */
10232 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10233 if (IS_BITVAR(OP_SYMBOL(result)->type))
10235 /* if the right size is a literal then
10236 we know what the value is */
10237 if (AOP_TYPE (right) == AOP_LIT)
10239 if (((int) operandLitValue (right)))
10240 aopPut (AOP (result), one, 0);
10242 aopPut (AOP (result), zero, 0);
10247 /* the right is also a bit variable */
10248 if (AOP_TYPE (right) == AOP_CRY)
10250 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10251 aopPut (AOP (result), "c", 0);
10255 /* we need to or */
10257 aopPut (AOP (result), "a", 0);
10261 /* if they are the same size : or less */
10262 if (AOP_SIZE (result) <= AOP_SIZE (right))
10265 /* if they are in the same place */
10266 if (sameRegs (AOP (right), AOP (result)))
10269 /* if they in different places then copy */
10270 size = AOP_SIZE (result);
10272 _startLazyDPSEvaluation ();
10275 aopPut (AOP (result),
10276 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10280 _endLazyDPSEvaluation ();
10285 /* if the result is of type pointer */
10286 if (IS_PTR (ctype))
10290 sym_link *type = operandType (right);
10292 /* pointer to generic pointer */
10293 if (IS_GENPTR (ctype))
10299 p_type = DCL_TYPE (type);
10303 #if OLD_CAST_BEHAVIOR
10304 /* KV: we are converting a non-pointer type to
10305 * a generic pointer. This (ifdef'd out) code
10306 * says that the resulting generic pointer
10307 * should have the same class as the storage
10308 * location of the non-pointer variable.
10310 * For example, converting an int (which happens
10311 * to be stored in DATA space) to a pointer results
10312 * in a DATA generic pointer; if the original int
10313 * in XDATA space, so will be the resulting pointer.
10315 * I don't like that behavior, and thus this change:
10316 * all such conversions will be forced to XDATA and
10317 * throw a warning. If you want some non-XDATA
10318 * type, or you want to suppress the warning, you
10319 * must go through an intermediate cast, like so:
10321 * char _generic *gp = (char _xdata *)(intVar);
10323 sym_link *etype = getSpec (type);
10325 /* we have to go by the storage class */
10326 if (SPEC_OCLS (etype) != generic)
10328 p_type = PTR_TYPE (SPEC_OCLS (etype));
10333 /* Converting unknown class (i.e. register variable)
10334 * to generic pointer. This is not good, but
10335 * we'll make a guess (and throw a warning).
10338 werror (W_INT_TO_GEN_PTR_CAST);
10342 /* the first two bytes are known */
10343 size = GPTRSIZE - 1;
10345 _startLazyDPSEvaluation ();
10348 aopPut (AOP (result),
10349 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10353 _endLazyDPSEvaluation ();
10355 /* the last byte depending on type */
10373 /* this should never happen */
10374 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10375 "got unknown pointer type");
10378 aopPut (AOP (result), l, GPTRSIZE - 1);
10382 /* just copy the pointers */
10383 size = AOP_SIZE (result);
10385 _startLazyDPSEvaluation ();
10388 aopPut (AOP (result),
10389 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10393 _endLazyDPSEvaluation ();
10397 /* so we now know that the size of destination is greater
10398 than the size of the source */
10399 /* we move to result for the size of source */
10400 size = AOP_SIZE (right);
10402 _startLazyDPSEvaluation ();
10405 aopPut (AOP (result),
10406 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10410 _endLazyDPSEvaluation ();
10412 /* now depending on the sign of the source && destination */
10413 size = AOP_SIZE (result) - AOP_SIZE (right);
10414 /* if unsigned or not an integral type */
10415 /* also, if the source is a bit, we don't need to sign extend, because
10416 * it can't possibly have set the sign bit.
10418 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10422 aopPut (AOP (result), zero, offset++);
10427 /* we need to extend the sign :{ */
10428 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10429 FALSE, FALSE, TRUE);
10431 emitcode ("rlc", "a");
10432 emitcode ("subb", "a,acc");
10434 aopPut (AOP (result), "a", offset++);
10437 /* we are done hurray !!!! */
10440 freeAsmop (right, NULL, ic, TRUE);
10441 freeAsmop (result, NULL, ic, TRUE);
10445 /*-----------------------------------------------------------------*/
10446 /* genDjnz - generate decrement & jump if not zero instrucion */
10447 /*-----------------------------------------------------------------*/
10449 genDjnz (iCode * ic, iCode * ifx)
10451 symbol *lbl, *lbl1;
10455 /* if the if condition has a false label
10456 then we cannot save */
10457 if (IC_FALSE (ifx))
10460 /* if the minus is not of the form
10462 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10463 !IS_OP_LITERAL (IC_RIGHT (ic)))
10466 if (operandLitValue (IC_RIGHT (ic)) != 1)
10469 /* if the size of this greater than one then no
10471 if (getSize (operandType (IC_RESULT (ic))) > 1)
10474 /* otherwise we can save BIG */
10475 D(emitcode(";", "genDjnz"););
10477 lbl = newiTempLabel (NULL);
10478 lbl1 = newiTempLabel (NULL);
10480 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10482 if (AOP_NEEDSACC(IC_RESULT(ic)))
10484 /* If the result is accessed indirectly via
10485 * the accumulator, we must explicitly write
10486 * it back after the decrement.
10488 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10490 if (strcmp(rByte, "a"))
10492 /* Something is hopelessly wrong */
10493 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10494 __FILE__, __LINE__);
10495 /* We can just give up; the generated code will be inefficient,
10496 * but what the hey.
10498 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10501 emitcode ("dec", "%s", rByte);
10502 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10503 emitcode ("jnz", "%05d$", lbl->key + 100);
10505 else if (IS_AOP_PREG (IC_RESULT (ic)))
10507 emitcode ("dec", "%s",
10508 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10509 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10510 emitcode ("jnz", "%05d$", lbl->key + 100);
10514 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10517 emitcode ("sjmp", "%05d$", lbl1->key + 100);
10518 emitcode ("", "%05d$:", lbl->key + 100);
10519 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10520 emitcode ("", "%05d$:", lbl1->key + 100);
10522 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10523 ifx->generated = 1;
10527 /*-----------------------------------------------------------------*/
10528 /* genReceive - generate code for a receive iCode */
10529 /*-----------------------------------------------------------------*/
10531 genReceive (iCode * ic)
10534 D (emitcode (";", "genReceive ");
10537 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10538 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10539 IS_TRUE_SYMOP (IC_RESULT (ic))))
10541 int size = getSize (operandType (IC_RESULT (ic)));
10542 int offset = fReturnSizeDS390 - size;
10545 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10546 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10549 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10550 size = AOP_SIZE (IC_RESULT (ic));
10554 emitcode ("pop", "acc");
10555 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10562 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10564 assignResultValue (IC_RESULT (ic));
10567 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10570 /*-----------------------------------------------------------------*/
10571 /* gen390Code - generate code for Dallas 390 based controllers */
10572 /*-----------------------------------------------------------------*/
10574 gen390Code (iCode * lic)
10579 lineHead = lineCurr = NULL;
10581 if (options.model == MODEL_FLAT24) {
10582 fReturnSizeDS390 = 5;
10583 fReturn = fReturn24;
10585 fReturnSizeDS390 = 4;
10586 fReturn = fReturn16;
10587 options.stack10bit=0;
10591 /* print the allocation information */
10593 printAllocInfo (currFunc, codeOutFile);
10595 /* if debug information required */
10596 if (options.debug && currFunc)
10598 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
10600 if (IS_STATIC (currFunc->etype))
10601 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
10603 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
10606 /* stack pointer name */
10607 if (options.useXstack)
10613 for (ic = lic; ic; ic = ic->next)
10616 if (cln != ic->lineno)
10621 emitcode ("", "C$%s$%d$%d$%d ==.",
10622 FileBaseName (ic->filename), ic->lineno,
10623 ic->level, ic->block);
10626 emitcode (";", "%s %d", ic->filename, ic->lineno);
10629 /* if the result is marked as
10630 spilt and rematerializable or code for
10631 this has already been generated then
10633 if (resultRemat (ic) || ic->generated)
10636 /* depending on the operation */
10656 /* IPOP happens only when trying to restore a
10657 spilt live range, if there is an ifx statement
10658 following this pop then the if statement might
10659 be using some of the registers being popped which
10660 would destory the contents of the register so
10661 we need to check for this condition and handle it */
10663 ic->next->op == IFX &&
10664 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10665 genIfx (ic->next, ic);
10683 genEndFunction (ic);
10703 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10720 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10724 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10731 /* note these two are xlated by algebraic equivalence
10732 during parsing SDCC.y */
10733 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10734 "got '>=' or '<=' shouldn't have come here");
10738 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10750 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10754 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10758 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10782 genRightShift (ic);
10785 case GET_VALUE_AT_ADDRESS:
10786 genPointerGet (ic,hasInc(IC_LEFT(ic),ic));
10790 if (POINTER_SET (ic))
10791 genPointerSet (ic,hasInc(IC_RESULT(ic),ic));
10817 addSet (&_G.sendSet, ic);
10830 /* now we are ready to call the
10831 peep hole optimizer */
10832 if (!options.nopeep)
10833 peepHole (&lineHead);
10835 /* now do the actual printing */
10836 printLine (lineHead, codeOutFile);