1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for DS80C390
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 DS390 adaptation by Kevin Vigor <kevin@vigor.nu>
9 This program is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 In other words, you are welcome to use, share and improve this program.
24 You are forbidden to forbid anyone else to use, share and improve
25 what you give them. Help stamp out software-hoarding!
26 -------------------------------------------------------------------------*/
36 #include "SDCCglobl.h"
39 #ifdef HAVE_SYS_ISA_DEFS_H
40 #include <sys/isa_defs.h>
42 #ifdef HAVE_MACHINE_ENDIAN_H
43 #include <machine/endian.h>
48 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
49 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
50 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
56 #define BETTER_LITERAL_SHIFT
58 char *aopLiteral (value * val, int offset);
60 /* this is the down and dirty file with all kinds of
61 kludgy & hacky stuff. This is what it is all about
62 CODE GENERATION for a specific MCU . some of the
63 routines may be reusable, will have to see */
65 static char *zero = "#0x00";
66 static char *one = "#0x01";
71 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
72 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
74 unsigned fReturnSizeDS390 = 5; /* shared with ralloc.c */
75 static char *fReturn24[] =
76 {"dpl", "dph", "dpx", "b", "a"};
77 static char *fReturn16[] =
78 {"dpl", "dph", "b", "a"};
79 static char **fReturn = fReturn24;
80 static char *accUse[] =
83 static short rbank = -1;
97 static void saveRBank (int, iCode *, bool);
99 #define RESULTONSTACK(x) \
100 (IC_RESULT(x) && IC_RESULT(x)->aop && \
101 IC_RESULT(x)->aop->type == AOP_STK )
103 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
104 #define MOVA(x) { char *_mova_tmp = strdup(x); \
105 if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
107 emitcode("mov","a,%s",_mova_tmp); \
111 #define CLRC emitcode("clr","c")
112 #define SETC emitcode("setb","c")
114 // A scratch register which will be used to hold
115 // result bytes from operands in far space via DPTR2.
116 #define DP2_RESULT_REG "ap"
118 static lineNode *lineHead = NULL;
119 static lineNode *lineCurr = NULL;
121 static unsigned char SLMask[] =
122 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
123 0xE0, 0xC0, 0x80, 0x00};
124 static unsigned char SRMask[] =
125 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
126 0x07, 0x03, 0x01, 0x00};
133 /*-----------------------------------------------------------------*/
134 /* emitcode - writes the code into a file : for now it is simple */
135 /*-----------------------------------------------------------------*/
137 emitcode (char *inst, char *fmt,...)
140 char lb[INITIAL_INLINEASM];
148 sprintf (lb, "%s\t", inst);
150 sprintf (lb, "%s", inst);
151 vsprintf (lb + (strlen (lb)), fmt, ap);
154 vsprintf (lb, fmt, ap);
156 while (isspace (*lbp))
160 lineCurr = (lineCurr ?
161 connectLine (lineCurr, newLineNode (lb)) :
162 (lineHead = newLineNode (lb)));
163 lineCurr->isInline = _G.inLine;
164 lineCurr->isDebug = _G.debugLine;
168 /*-----------------------------------------------------------------*/
169 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
170 /*-----------------------------------------------------------------*/
172 getFreePtr (iCode * ic, asmop ** aopp, bool result)
174 bool r0iu = FALSE, r1iu = FALSE;
175 bool r0ou = FALSE, r1ou = FALSE;
177 /* the logic: if r0 & r1 used in the instruction
178 then we are in trouble otherwise */
180 /* first check if r0 & r1 are used by this
181 instruction, in which case we are in trouble */
182 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
183 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
188 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
189 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
191 /* if no usage of r0 then return it */
194 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
195 (*aopp)->type = AOP_R0;
197 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
200 /* if no usage of r1 then return it */
203 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
204 (*aopp)->type = AOP_R1;
206 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
209 /* now we know they both have usage */
210 /* if r0 not used in this instruction */
213 /* push it if not already pushed */
216 emitcode ("push", "%s",
217 ds390_regWithIdx (R0_IDX)->dname);
221 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
222 (*aopp)->type = AOP_R0;
224 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
227 /* if r1 not used then */
231 /* push it if not already pushed */
234 emitcode ("push", "%s",
235 ds390_regWithIdx (R1_IDX)->dname);
239 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
240 (*aopp)->type = AOP_R1;
241 return ds390_regWithIdx (R1_IDX);
245 /* I said end of world but not quite end of world yet */
246 /* if this is a result then we can push it on the stack */
249 (*aopp)->type = AOP_STK;
253 /* other wise this is true end of the world */
254 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
255 "getFreePtr should never reach here");
259 /*-----------------------------------------------------------------*/
260 /* newAsmop - creates a new asmOp */
261 /*-----------------------------------------------------------------*/
263 newAsmop (short type)
267 aop = Safe_calloc (1, sizeof (asmop));
272 static int _currentDPS; /* Current processor DPS. */
273 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
274 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
276 /*-----------------------------------------------------------------*/
277 /* genSetDPTR: generate code to select which DPTR is in use (zero */
278 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
279 /* alternate DPTR (DPL1/DPH1/DPX1). */
280 /*-----------------------------------------------------------------*/
285 /* If we are doing lazy evaluation, simply note the desired
286 * change, but don't emit any code yet.
296 emitcode ("mov", "dps, #0x00");
301 emitcode ("mov", "dps, #0x01");
305 /*-----------------------------------------------------------------*/
306 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
308 /* Any code that operates on DPTR (NB: not on the individual */
309 /* components, like DPH) *must* call _flushLazyDPS() before using */
310 /* DPTR within a lazy DPS evaluation block. */
312 /* Note that aopPut and aopGet already contain the proper calls to */
313 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
314 /* DPS evaluation block. */
316 /* Also, _flushLazyDPS must be called before any flow control */
317 /* operations that could potentially branch out of the block. */
319 /* Lazy DPS evaluation is simply an optimization (though an */
320 /* important one), so if in doubt, leave it out. */
321 /*-----------------------------------------------------------------*/
323 _startLazyDPSEvaluation (void)
327 #ifdef BETTER_LITERAL_SHIFT
334 /*-----------------------------------------------------------------*/
335 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
336 /* desired one. Call before using DPTR within a lazy DPS evaluation */
338 /*-----------------------------------------------------------------*/
348 if (_desiredDPS != _currentDPS)
352 emitcode ("inc", "dps");
356 emitcode ("dec", "dps");
358 _currentDPS = _desiredDPS;
362 /*-----------------------------------------------------------------*/
363 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
365 /* Forces us back to the safe state (standard DPTR selected). */
366 /*-----------------------------------------------------------------*/
368 _endLazyDPSEvaluation (void)
370 #ifdef BETTER_LITERAL_SHIFT
389 /*-----------------------------------------------------------------*/
390 /* pointerCode - returns the code for a pointer type */
391 /*-----------------------------------------------------------------*/
393 pointerCode (sym_link * etype)
396 return PTR_TYPE (SPEC_OCLS (etype));
400 /*-----------------------------------------------------------------*/
401 /* aopForSym - for a true symbol */
402 /*-----------------------------------------------------------------*/
404 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
407 memmap *space = SPEC_OCLS (sym->etype);
409 /* if already has one */
413 /* assign depending on the storage class */
414 /* if it is on the stack or indirectly addressable */
415 /* space we need to assign either r0 or r1 to it */
416 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
418 sym->aop = aop = newAsmop (0);
419 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
420 aop->size = getSize (sym->type);
422 /* now assign the address of the variable to
423 the pointer register */
424 if (aop->type != AOP_STK)
430 emitcode ("push", "acc");
432 emitcode ("mov", "a,_bp");
433 emitcode ("add", "a,#0x%02x",
435 ((char) (sym->stack - _G.nRegsSaved)) :
436 ((char) sym->stack)) & 0xff);
437 emitcode ("mov", "%s,a",
438 aop->aopu.aop_ptr->name);
441 emitcode ("pop", "acc");
444 emitcode ("mov", "%s,#%s",
445 aop->aopu.aop_ptr->name,
447 aop->paged = space->paged;
450 aop->aopu.aop_stk = sym->stack;
454 if (sym->onStack && options.stack10bit)
456 /* It's on the 10 bit stack, which is located in
461 emitcode ("push", "acc");
463 emitcode ("mov", "a,_bp");
464 emitcode ("add", "a,#0x%02x",
466 ((char) (sym->stack - _G.nRegsSaved)) :
467 ((char) sym->stack)) & 0xff);
471 if (options.model == MODEL_FLAT24)
472 emitcode ("mov", "dpx1,#0x40");
474 emitcode ("mov", "dph1,#0x00");
475 emitcode ("mov", "dpl1, a");
479 if (options.model == MODEL_FLAT24)
480 emitcode ("mov", "dpx,#0x40");
481 emitcode ("mov", "dph,#0x00");
482 emitcode ("mov", "dpl, a");
486 emitcode ("pop", "acc");
488 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
489 aop->size = getSize (sym->type);
493 /* if in bit space */
494 if (IN_BITSPACE (space))
496 sym->aop = aop = newAsmop (AOP_CRY);
497 aop->aopu.aop_dir = sym->rname;
498 aop->size = getSize (sym->type);
501 /* if it is in direct space */
502 if (IN_DIRSPACE (space))
504 sym->aop = aop = newAsmop (AOP_DIR);
505 aop->aopu.aop_dir = sym->rname;
506 aop->size = getSize (sym->type);
510 /* special case for a function */
511 if (IS_FUNC (sym->type))
513 sym->aop = aop = newAsmop (AOP_IMMD);
514 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
515 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
516 aop->size = FPTRSIZE;
520 /* only remaining is far space */
521 /* in which case DPTR gets the address */
522 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
527 emitcode ("mov", "dptr,#%s", sym->rname);
532 emitcode ("mov", "dptr,#%s", sym->rname);
534 aop->size = getSize (sym->type);
536 /* if it is in code space */
537 if (IN_CODESPACE (space))
543 /*-----------------------------------------------------------------*/
544 /* aopForRemat - rematerialzes an object */
545 /*-----------------------------------------------------------------*/
547 aopForRemat (symbol * sym)
549 iCode *ic = sym->rematiCode;
550 asmop *aop = newAsmop (AOP_IMMD);
557 val += (int) operandLitValue (IC_RIGHT (ic));
558 else if (ic->op == '-')
559 val -= (int) operandLitValue (IC_RIGHT (ic));
560 else if (IS_CAST_ICODE(ic)) {
561 sym_link *from_type = operandType(IC_RIGHT(ic));
562 aop->aopu.aop_immd.from_cast_remat = 1;
563 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
564 ptr_type = DCL_TYPE(from_type);
568 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
572 sprintf (buffer, "(%s %c 0x%04x)",
573 OP_SYMBOL (IC_LEFT (ic))->rname,
574 val >= 0 ? '+' : '-',
577 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
579 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
580 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
581 /* set immd2 field if required */
582 if (aop->aopu.aop_immd.from_cast_remat) {
583 sprintf(buffer,"#0x%02x",ptr_type);
584 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
585 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
591 /*-----------------------------------------------------------------*/
592 /* regsInCommon - two operands have some registers in common */
593 /*-----------------------------------------------------------------*/
595 regsInCommon (operand * op1, operand * op2)
600 /* if they have registers in common */
601 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
604 sym1 = OP_SYMBOL (op1);
605 sym2 = OP_SYMBOL (op2);
607 if (sym1->nRegs == 0 || sym2->nRegs == 0)
610 for (i = 0; i < sym1->nRegs; i++)
616 for (j = 0; j < sym2->nRegs; j++)
621 if (sym2->regs[j] == sym1->regs[i])
629 /*-----------------------------------------------------------------*/
630 /* operandsEqu - equivalent */
631 /*-----------------------------------------------------------------*/
633 operandsEqu (operand * op1, operand * op2)
637 /* if they not symbols */
638 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
641 sym1 = OP_SYMBOL (op1);
642 sym2 = OP_SYMBOL (op2);
644 /* if both are itemps & one is spilt
645 and the other is not then false */
646 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
647 sym1->isspilt != sym2->isspilt)
650 /* if they are the same */
654 if (strcmp (sym1->rname, sym2->rname) == 0)
658 /* if left is a tmp & right is not */
659 if (IS_ITEMP (op1) &&
662 (sym1->usl.spillLoc == sym2))
665 if (IS_ITEMP (op2) &&
669 (sym2->usl.spillLoc == sym1))
675 /*-----------------------------------------------------------------*/
676 /* sameRegs - two asmops have the same registers */
677 /*-----------------------------------------------------------------*/
679 sameRegs (asmop * aop1, asmop * aop2)
685 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
692 if (aop1->type != AOP_REG ||
693 aop2->type != AOP_REG)
696 if (aop1->size != aop2->size)
699 for (i = 0; i < aop1->size; i++)
700 if (aop1->aopu.aop_reg[i] !=
701 aop2->aopu.aop_reg[i])
707 /*-----------------------------------------------------------------*/
708 /* aopOp - allocates an asmop for an operand : */
709 /*-----------------------------------------------------------------*/
711 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
720 /* if this a literal */
721 if (IS_OP_LITERAL (op))
723 op->aop = aop = newAsmop (AOP_LIT);
724 aop->aopu.aop_lit = op->operand.valOperand;
725 aop->size = getSize (operandType (op));
729 /* if already has a asmop then continue */
733 /* if the underlying symbol has a aop */
734 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
736 op->aop = OP_SYMBOL (op)->aop;
740 /* if this is a true symbol */
741 if (IS_TRUE_SYMOP (op))
743 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
747 /* this is a temporary : this has
753 e) can be a return use only */
755 sym = OP_SYMBOL (op);
758 /* if the type is a conditional */
759 if (sym->regType == REG_CND)
761 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
766 /* if it is spilt then two situations
768 b) has a spill location */
769 if (sym->isspilt || sym->nRegs == 0)
772 /* rematerialize it NOW */
775 sym->aop = op->aop = aop =
777 aop->size = getSize (sym->type);
784 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
785 aop->size = getSize (sym->type);
786 for (i = 0; i < 2; i++)
787 aop->aopu.aop_str[i] = accUse[i];
797 /* a AOP_STR uses DPTR, but DPTR is already in use;
800 fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use!\n");
803 aop = op->aop = sym->aop = newAsmop (AOP_STR);
804 aop->size = getSize (sym->type);
805 for (i = 0; i < (int) fReturnSizeDS390; i++)
806 aop->aopu.aop_str[i] = fReturn[i];
810 /* else spill location */
811 sym->aop = op->aop = aop =
812 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
813 aop->size = getSize (sym->type);
817 /* must be in a register */
818 sym->aop = op->aop = aop = newAsmop (AOP_REG);
819 aop->size = sym->nRegs;
820 for (i = 0; i < sym->nRegs; i++)
821 aop->aopu.aop_reg[i] = sym->regs[i];
824 /*-----------------------------------------------------------------*/
825 /* freeAsmop - free up the asmop given to an operand */
826 /*----------------------------------------------------------------*/
828 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
845 /* depending on the asmop type only three cases need work AOP_RO
846 , AOP_R1 && AOP_STK */
854 emitcode ("pop", "ar0");
858 bitVectUnSetBit (ic->rUsed, R0_IDX);
866 emitcode ("pop", "ar1");
870 bitVectUnSetBit (ic->rUsed, R1_IDX);
876 int stk = aop->aopu.aop_stk + aop->size;
877 bitVectUnSetBit (ic->rUsed, R0_IDX);
878 bitVectUnSetBit (ic->rUsed, R1_IDX);
880 getFreePtr (ic, &aop, FALSE);
882 if (options.stack10bit)
884 /* I'm not sure what to do here yet... */
887 "*** Warning: probably generating bad code for "
888 "10 bit stack mode.\n");
893 emitcode ("mov", "a,_bp");
894 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
895 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
899 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
904 emitcode ("pop", "acc");
905 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
908 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
911 freeAsmop (op, NULL, ic, TRUE);
914 emitcode ("pop", "ar0");
920 emitcode ("pop", "ar1");
927 /* all other cases just dealloc */
933 OP_SYMBOL (op)->aop = NULL;
934 /* if the symbol has a spill */
936 SPIL_LOC (op)->aop = NULL;
941 /*------------------------------------------------------------------*/
942 /* aopGet - for fetching value of the aop */
944 /* Set canClobberACC if you are sure it is OK to clobber the value */
945 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
946 /* just less efficient. */
947 /*------------------------------------------------------------------*/
959 /* offset is greater than
961 if (offset > (aop->size - 1) &&
962 aop->type != AOP_LIT)
965 /* depending on type */
971 /* if we need to increment it */
972 while (offset > aop->coff)
974 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
978 while (offset < aop->coff)
980 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
987 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
988 return (dname ? "acc" : "a");
990 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
991 rs = Safe_calloc (1, strlen (s) + 1);
998 if (aop->type == AOP_DPTR2)
1004 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1010 while (offset > aop->coff)
1012 emitcode ("inc", "dptr");
1016 while (offset < aop->coff)
1018 emitcode ("lcall", "__decdptr");
1025 emitcode ("clr", "a");
1026 emitcode ("movc", "a,@a+dptr");
1030 emitcode ("movx", "a,@dptr");
1033 if (aop->type == AOP_DPTR2)
1039 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1040 return DP2_RESULT_REG;
1043 return (dname ? "acc" : "a");
1046 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1047 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1049 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1051 sprintf (s, "#(%s >> %d)",
1052 aop->aopu.aop_immd.aop_immd1,
1056 aop->aopu.aop_immd.aop_immd1);
1057 rs = Safe_calloc (1, strlen (s) + 1);
1063 sprintf (s, "(%s + %d)",
1067 sprintf (s, "%s", aop->aopu.aop_dir);
1068 rs = Safe_calloc (1, strlen (s) + 1);
1074 return aop->aopu.aop_reg[offset]->dname;
1076 return aop->aopu.aop_reg[offset]->name;
1079 emitcode ("clr", "a");
1080 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1081 emitcode ("rlc", "a");
1082 return (dname ? "acc" : "a");
1085 if (!offset && dname)
1087 return aop->aopu.aop_str[offset];
1090 return aopLiteral (aop->aopu.aop_lit, offset);
1094 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1098 return aop->aopu.aop_str[offset];
1102 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1103 "aopget got unsupported aop->type");
1106 /*-----------------------------------------------------------------*/
1107 /* aopPut - puts a string for a aop */
1108 /*-----------------------------------------------------------------*/
1110 aopPut (asmop * aop, char *s, int offset)
1114 if (aop->size && offset > (aop->size - 1))
1116 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1117 "aopPut got offset > aop->size");
1121 /* will assign value to value */
1122 /* depending on where it is ofcourse */
1127 sprintf (d, "(%s + %d)",
1128 aop->aopu.aop_dir, offset);
1130 sprintf (d, "%s", aop->aopu.aop_dir);
1133 emitcode ("mov", "%s,%s", d, s);
1138 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1139 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1142 strcmp (s, "r0") == 0 ||
1143 strcmp (s, "r1") == 0 ||
1144 strcmp (s, "r2") == 0 ||
1145 strcmp (s, "r3") == 0 ||
1146 strcmp (s, "r4") == 0 ||
1147 strcmp (s, "r5") == 0 ||
1148 strcmp (s, "r6") == 0 ||
1149 strcmp (s, "r7") == 0)
1150 emitcode ("mov", "%s,%s",
1151 aop->aopu.aop_reg[offset]->dname, s);
1153 emitcode ("mov", "%s,%s",
1154 aop->aopu.aop_reg[offset]->name, s);
1161 if (aop->type == AOP_DPTR2)
1169 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1170 "aopPut writting to code space");
1174 while (offset > aop->coff)
1177 emitcode ("inc", "dptr");
1180 while (offset < aop->coff)
1183 emitcode ("lcall", "__decdptr");
1188 /* if not in accumulater */
1191 emitcode ("movx", "@dptr,a");
1193 if (aop->type == AOP_DPTR2)
1201 while (offset > aop->coff)
1204 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1206 while (offset < aop->coff)
1209 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1216 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1222 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1224 else if (strcmp (s, "r0") == 0 ||
1225 strcmp (s, "r1") == 0 ||
1226 strcmp (s, "r2") == 0 ||
1227 strcmp (s, "r3") == 0 ||
1228 strcmp (s, "r4") == 0 ||
1229 strcmp (s, "r5") == 0 ||
1230 strcmp (s, "r6") == 0 ||
1231 strcmp (s, "r7") == 0)
1234 sprintf (buffer, "a%s", s);
1235 emitcode ("mov", "@%s,%s",
1236 aop->aopu.aop_ptr->name, buffer);
1239 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1244 if (strcmp (s, "a") == 0)
1245 emitcode ("push", "acc");
1249 emitcode ("push", "acc");
1251 emitcode ("push", s);
1257 /* if bit variable */
1258 if (!aop->aopu.aop_dir)
1260 emitcode ("clr", "a");
1261 emitcode ("rlc", "a");
1266 emitcode ("clr", "%s", aop->aopu.aop_dir);
1268 emitcode ("setb", "%s", aop->aopu.aop_dir);
1269 else if (!strcmp (s, "c"))
1270 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1273 if (strcmp (s, "a"))
1278 symbol *lbl = newiTempLabel (NULL);
1279 emitcode ("clr", "c");
1280 emitcode ("jz", "%05d$", lbl->key + 100);
1281 emitcode ("cpl", "c");
1282 emitcode ("", "%05d$:", lbl->key + 100);
1283 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1291 if (strcmp (aop->aopu.aop_str[offset], s))
1292 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1297 if (!offset && (strcmp (s, "acc") == 0))
1300 if (strcmp (aop->aopu.aop_str[offset], s))
1301 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1305 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1306 "aopPut got unsupported aop->type");
1313 /*--------------------------------------------------------------------*/
1314 /* reAdjustPreg - points a register back to where it should (coff==0) */
1315 /*--------------------------------------------------------------------*/
1317 reAdjustPreg (asmop * aop)
1319 if ((aop->coff==0) || (aop->size <= 1)) {
1328 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1332 if (aop->type == AOP_DPTR2)
1339 emitcode ("lcall", "__decdptr");
1342 if (aop->type == AOP_DPTR2)
1352 #define AOP(op) op->aop
1353 #define AOP_TYPE(op) AOP(op)->type
1354 #define AOP_SIZE(op) AOP(op)->size
1355 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1356 AOP_TYPE(x) == AOP_R0))
1358 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1359 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1362 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1363 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1364 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1366 /* Workaround for DS80C390 bug: div ab may return bogus results
1367 * if A is accessed in instruction immediately before the div.
1369 * Will be fixed in B4 rev of processor, Dallas claims.
1372 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1373 if (!AOP_NEEDSACC(RIGHT)) \
1375 /* We can load A first, then B, since \
1376 * B (the RIGHT operand) won't clobber A, \
1377 * thus avoiding touching A right before the div. \
1379 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1380 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1382 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1386 /* Just stuff in a nop after loading A. */ \
1387 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1388 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1390 emitcode("nop", "; workaround for DS80C390 div bug."); \
1393 /*-----------------------------------------------------------------*/
1394 /* genNotFloat - generates not for float operations */
1395 /*-----------------------------------------------------------------*/
1397 genNotFloat (operand * op, operand * res)
1403 D (emitcode (";", "genNotFloat ");
1406 /* we will put 127 in the first byte of
1408 aopPut (AOP (res), "#127", 0);
1409 size = AOP_SIZE (op) - 1;
1412 _startLazyDPSEvaluation ();
1413 l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1418 emitcode ("orl", "a,%s",
1420 offset++, FALSE, FALSE, FALSE));
1422 _endLazyDPSEvaluation ();
1424 tlbl = newiTempLabel (NULL);
1425 aopPut (res->aop, one, 1);
1426 emitcode ("jz", "%05d$", (tlbl->key + 100));
1427 aopPut (res->aop, zero, 1);
1428 emitcode ("", "%05d$:", (tlbl->key + 100));
1430 size = res->aop->size - 2;
1432 /* put zeros in the rest */
1434 aopPut (res->aop, zero, offset++);
1437 /*-----------------------------------------------------------------*/
1438 /* opIsGptr: returns non-zero if the passed operand is */
1439 /* a generic pointer type. */
1440 /*-----------------------------------------------------------------*/
1442 opIsGptr (operand * op)
1444 sym_link *type = operandType (op);
1446 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1453 /*-----------------------------------------------------------------*/
1454 /* getDataSize - get the operand data size */
1455 /*-----------------------------------------------------------------*/
1457 getDataSize (operand * op)
1460 size = AOP_SIZE (op);
1461 if (size == GPTRSIZE)
1463 sym_link *type = operandType (op);
1464 if (IS_GENPTR (type))
1466 /* generic pointer; arithmetic operations
1467 * should ignore the high byte (pointer type).
1475 /*-----------------------------------------------------------------*/
1476 /* outAcc - output Acc */
1477 /*-----------------------------------------------------------------*/
1479 outAcc (operand * result)
1482 size = getDataSize (result);
1485 aopPut (AOP (result), "a", 0);
1488 /* unsigned or positive */
1491 aopPut (AOP (result), zero, offset++);
1496 /*-----------------------------------------------------------------*/
1497 /* outBitC - output a bit C */
1498 /*-----------------------------------------------------------------*/
1500 outBitC (operand * result)
1502 /* if the result is bit */
1503 if (AOP_TYPE (result) == AOP_CRY)
1505 aopPut (AOP (result), "c", 0);
1509 emitcode ("clr", "a");
1510 emitcode ("rlc", "a");
1515 /*-----------------------------------------------------------------*/
1516 /* toBoolean - emit code for orl a,operator(sizeop) */
1517 /*-----------------------------------------------------------------*/
1519 toBoolean (operand * oper)
1521 int size = AOP_SIZE (oper) - 1;
1525 /* The generic part of a generic pointer should
1526 * not participate in it's truth value.
1528 * i.e. 0x10000000 is zero.
1530 if (opIsGptr (oper))
1532 D (emitcode (";", "toBoolean: generic ptr special case.");
1537 _startLazyDPSEvaluation ();
1538 if (AOP_NEEDSACC (oper) && size)
1541 emitcode ("push", "b");
1542 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1546 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1552 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1556 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1559 _endLazyDPSEvaluation ();
1563 emitcode ("mov", "a,b");
1564 emitcode ("pop", "b");
1569 /*-----------------------------------------------------------------*/
1570 /* genNot - generate code for ! operation */
1571 /*-----------------------------------------------------------------*/
1576 sym_link *optype = operandType (IC_LEFT (ic));
1578 D (emitcode (";", "genNot ");
1581 /* assign asmOps to operand & result */
1582 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1583 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1585 /* if in bit space then a special case */
1586 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1588 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1589 emitcode ("cpl", "c");
1590 outBitC (IC_RESULT (ic));
1594 /* if type float then do float */
1595 if (IS_FLOAT (optype))
1597 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1601 toBoolean (IC_LEFT (ic));
1603 tlbl = newiTempLabel (NULL);
1604 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1605 emitcode ("", "%05d$:", tlbl->key + 100);
1606 outBitC (IC_RESULT (ic));
1609 /* release the aops */
1610 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1611 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1615 /*-----------------------------------------------------------------*/
1616 /* genCpl - generate code for complement */
1617 /*-----------------------------------------------------------------*/
1624 D (emitcode (";", "genCpl ");
1628 /* assign asmOps to operand & result */
1629 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1630 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1632 /* if both are in bit space then
1634 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1635 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1638 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1639 emitcode ("cpl", "c");
1640 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1644 size = AOP_SIZE (IC_RESULT (ic));
1645 _startLazyDPSEvaluation ();
1648 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1650 emitcode ("cpl", "a");
1651 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1653 _endLazyDPSEvaluation ();
1657 /* release the aops */
1658 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1659 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1662 /*-----------------------------------------------------------------*/
1663 /* genUminusFloat - unary minus for floating points */
1664 /*-----------------------------------------------------------------*/
1666 genUminusFloat (operand * op, operand * result)
1668 int size, offset = 0;
1670 /* for this we just need to flip the
1671 first it then copy the rest in place */
1672 D (emitcode (";", "genUminusFloat");
1675 _startLazyDPSEvaluation ();
1676 size = AOP_SIZE (op) - 1;
1677 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1680 emitcode ("cpl", "acc.7");
1681 aopPut (AOP (result), "a", 3);
1685 aopPut (AOP (result),
1686 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1690 _endLazyDPSEvaluation ();
1693 /*-----------------------------------------------------------------*/
1694 /* genUminus - unary minus code generation */
1695 /*-----------------------------------------------------------------*/
1697 genUminus (iCode * ic)
1700 sym_link *optype, *rtype;
1702 D (emitcode (";", "genUminus ");
1707 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1708 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1710 /* if both in bit space then special
1712 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1713 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1716 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1717 emitcode ("cpl", "c");
1718 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1722 optype = operandType (IC_LEFT (ic));
1723 rtype = operandType (IC_RESULT (ic));
1725 /* if float then do float stuff */
1726 if (IS_FLOAT (optype))
1728 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1732 /* otherwise subtract from zero */
1733 size = AOP_SIZE (IC_LEFT (ic));
1735 _startLazyDPSEvaluation ();
1738 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1739 if (!strcmp (l, "a"))
1743 emitcode ("cpl", "a");
1744 emitcode ("addc", "a,#0");
1750 emitcode ("clr", "a");
1751 emitcode ("subb", "a,%s", l);
1753 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1755 _endLazyDPSEvaluation ();
1757 /* if any remaining bytes in the result */
1758 /* we just need to propagate the sign */
1759 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1761 emitcode ("rlc", "a");
1762 emitcode ("subb", "a,acc");
1764 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1768 /* release the aops */
1769 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1770 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1773 /*-----------------------------------------------------------------*/
1774 /* saveRegisters - will look for a call and save the registers */
1775 /*-----------------------------------------------------------------*/
1777 saveRegisters (iCode * lic)
1785 for (ic = lic; ic; ic = ic->next)
1786 if (ic->op == CALL || ic->op == PCALL)
1791 fprintf (stderr, "found parameter push with no function call\n");
1795 /* if the registers have been saved already then
1797 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type) ||
1798 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))))
1801 /* find the registers in use at this time
1802 and push them away to safety */
1803 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1807 if (options.useXstack)
1809 if (bitVectBitValue (rsave, R0_IDX))
1810 emitcode ("mov", "b,r0");
1811 emitcode ("mov", "r0,%s", spname);
1812 for (i = 0; i < ds390_nRegs; i++)
1814 if (bitVectBitValue (rsave, i))
1817 emitcode ("mov", "a,b");
1819 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1820 emitcode ("movx", "@r0,a");
1821 emitcode ("inc", "r0");
1824 emitcode ("mov", "%s,r0", spname);
1825 if (bitVectBitValue (rsave, R0_IDX))
1826 emitcode ("mov", "r0,b");
1829 for (i = 0; i < ds390_nRegs; i++)
1831 if (bitVectBitValue (rsave, i))
1832 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1835 detype = getSpec (operandType (IC_LEFT (ic)));
1838 /*-----------------------------------------------------------------*/
1839 /* unsaveRegisters - pop the pushed registers */
1840 /*-----------------------------------------------------------------*/
1842 unsaveRegisters (iCode * ic)
1846 /* find the registers in use at this time
1847 and push them away to safety */
1848 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1851 if (options.useXstack)
1853 emitcode ("mov", "r0,%s", spname);
1854 for (i = ds390_nRegs; i >= 0; i--)
1856 if (bitVectBitValue (rsave, i))
1858 emitcode ("dec", "r0");
1859 emitcode ("movx", "a,@r0");
1861 emitcode ("mov", "b,a");
1863 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1867 emitcode ("mov", "%s,r0", spname);
1868 if (bitVectBitValue (rsave, R0_IDX))
1869 emitcode ("mov", "r0,b");
1872 for (i = ds390_nRegs; i >= 0; i--)
1874 if (bitVectBitValue (rsave, i))
1875 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1881 /*-----------------------------------------------------------------*/
1883 /*-----------------------------------------------------------------*/
1885 pushSide (operand * oper, int size)
1888 _startLazyDPSEvaluation ();
1891 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1892 if (AOP_TYPE (oper) != AOP_REG &&
1893 AOP_TYPE (oper) != AOP_DIR &&
1896 emitcode ("mov", "a,%s", l);
1897 emitcode ("push", "acc");
1900 emitcode ("push", "%s", l);
1902 _endLazyDPSEvaluation ();
1905 /*-----------------------------------------------------------------*/
1906 /* assignResultValue - */
1907 /*-----------------------------------------------------------------*/
1909 assignResultValue (operand * oper)
1912 int size = AOP_SIZE (oper);
1914 _startLazyDPSEvaluation ();
1917 aopPut (AOP (oper), fReturn[offset], offset);
1920 _endLazyDPSEvaluation ();
1924 /*-----------------------------------------------------------------*/
1925 /* genXpush - pushes onto the external stack */
1926 /*-----------------------------------------------------------------*/
1928 genXpush (iCode * ic)
1930 asmop *aop = newAsmop (0);
1932 int size, offset = 0;
1934 D (emitcode (";", "genXpush ");
1937 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1938 r = getFreePtr (ic, &aop, FALSE);
1941 emitcode ("mov", "%s,_spx", r->name);
1943 size = AOP_SIZE (IC_LEFT (ic));
1944 _startLazyDPSEvaluation ();
1948 char *l = aopGet (AOP (IC_LEFT (ic)),
1949 offset++, FALSE, FALSE, TRUE);
1951 emitcode ("movx", "@%s,a", r->name);
1952 emitcode ("inc", "%s", r->name);
1955 _endLazyDPSEvaluation ();
1958 emitcode ("mov", "_spx,%s", r->name);
1960 freeAsmop (NULL, aop, ic, TRUE);
1961 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1964 /*-----------------------------------------------------------------*/
1965 /* genIpush - genrate code for pushing this gets a little complex */
1966 /*-----------------------------------------------------------------*/
1968 genIpush (iCode * ic)
1970 int size, offset = 0;
1973 D (emitcode (";", "genIpush ");
1976 /* if this is not a parm push : ie. it is spill push
1977 and spill push is always done on the local stack */
1981 /* and the item is spilt then do nothing */
1982 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1985 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1986 size = AOP_SIZE (IC_LEFT (ic));
1987 /* push it on the stack */
1988 _startLazyDPSEvaluation ();
1991 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1997 emitcode ("push", "%s", l);
1999 _endLazyDPSEvaluation ();
2003 /* this is a paramter push: in this case we call
2004 the routine to find the call and save those
2005 registers that need to be saved */
2008 /* if use external stack then call the external
2009 stack pushing routine */
2010 if (options.useXstack)
2016 /* then do the push */
2017 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2019 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2020 size = AOP_SIZE (IC_LEFT (ic));
2022 _startLazyDPSEvaluation ();
2025 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2026 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2027 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2030 emitcode ("mov", "a,%s", l);
2031 emitcode ("push", "acc");
2034 emitcode ("push", "%s", l);
2036 _endLazyDPSEvaluation ();
2038 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2041 /*-----------------------------------------------------------------*/
2042 /* genIpop - recover the registers: can happen only for spilling */
2043 /*-----------------------------------------------------------------*/
2045 genIpop (iCode * ic)
2049 D (emitcode (";", "genIpop ");
2053 /* if the temp was not pushed then */
2054 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2057 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2058 size = AOP_SIZE (IC_LEFT (ic));
2059 offset = (size - 1);
2060 _startLazyDPSEvaluation ();
2063 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2064 FALSE, TRUE, TRUE));
2066 _endLazyDPSEvaluation ();
2068 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2071 /*-----------------------------------------------------------------*/
2072 /* unsaveRBank - restores the resgister bank from stack */
2073 /*-----------------------------------------------------------------*/
2075 unsaveRBank (int bank, iCode * ic, bool popPsw)
2081 if (options.useXstack)
2085 /* Assume r0 is available for use. */
2086 r = ds390_regWithIdx (R0_IDX);;
2091 r = getFreePtr (ic, &aop, FALSE);
2093 emitcode ("mov", "%s,_spx", r->name);
2098 if (options.useXstack)
2100 emitcode ("movx", "a,@%s", r->name);
2101 emitcode ("mov", "psw,a");
2102 emitcode ("dec", "%s", r->name);
2106 emitcode ("pop", "psw");
2110 for (i = (ds390_nRegs - 1); i >= 0; i--)
2112 if (options.useXstack)
2114 emitcode ("movx", "a,@%s", r->name);
2115 emitcode ("mov", "(%s+%d),a",
2116 regs390[i].base, 8 * bank + regs390[i].offset);
2117 emitcode ("dec", "%s", r->name);
2121 emitcode ("pop", "(%s+%d)",
2122 regs390[i].base, 8 * bank + regs390[i].offset);
2125 if (options.useXstack)
2127 emitcode ("mov", "_spx,%s", r->name);
2132 freeAsmop (NULL, aop, ic, TRUE);
2136 /*-----------------------------------------------------------------*/
2137 /* saveRBank - saves an entire register bank on the stack */
2138 /*-----------------------------------------------------------------*/
2140 saveRBank (int bank, iCode * ic, bool pushPsw)
2146 if (options.useXstack)
2150 /* Assume r0 is available for use. */
2151 r = ds390_regWithIdx (R0_IDX);;
2156 r = getFreePtr (ic, &aop, FALSE);
2158 emitcode ("mov", "%s,_spx", r->name);
2161 for (i = 0; i < ds390_nRegs; i++)
2163 if (options.useXstack)
2165 emitcode ("inc", "%s", r->name);
2166 emitcode ("mov", "a,(%s+%d)",
2167 regs390[i].base, 8 * bank + regs390[i].offset);
2168 emitcode ("movx", "@%s,a", r->name);
2171 emitcode ("push", "(%s+%d)",
2172 regs390[i].base, 8 * bank + regs390[i].offset);
2177 if (options.useXstack)
2179 emitcode ("mov", "a,psw");
2180 emitcode ("movx", "@%s,a", r->name);
2181 emitcode ("inc", "%s", r->name);
2182 emitcode ("mov", "_spx,%s", r->name);
2186 emitcode ("push", "psw");
2189 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2194 freeAsmop (NULL, aop, ic, TRUE);
2203 /*-----------------------------------------------------------------*/
2204 /* genCall - generates a call statement */
2205 /*-----------------------------------------------------------------*/
2207 genCall (iCode * ic)
2210 bool restoreBank = FALSE;
2211 bool swapBanks = FALSE;
2213 D (emitcode (";", "genCall "););
2215 /* if we are calling a not _naked function that is not using
2216 the same register bank then we need to save the
2217 destination registers on the stack */
2218 dtype = operandType (IC_LEFT (ic));
2219 if (dtype && !IFFUNC_ISNAKED(dtype) &&
2220 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2221 IFFUNC_ISISR (currFunc->type))
2225 /* This is unexpected; the bank should have been saved in
2228 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2234 /* if caller saves & we have not saved then */
2238 /* if send set is not empty the assign */
2239 /* We've saved all the registers we care about;
2240 * therefore, we may clobber any register not used
2241 * in the calling convention (i.e. anything not in
2248 for (sic = setFirstItem (_G.sendSet); sic;
2249 sic = setNextItem (_G.sendSet))
2251 int size, offset = 0;
2253 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2254 size = AOP_SIZE (IC_LEFT (sic));
2256 _startLazyDPSEvaluation ();
2259 char *l = aopGet (AOP(IC_LEFT(sic)), offset,
2260 FALSE, FALSE, TRUE);
2261 if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size)
2263 emitcode("mov", "%s,%s", regs390[offset].name, l);
2265 else if (strcmp (l, fReturn[offset]))
2267 emitcode ("mov", "%s,%s",
2273 _endLazyDPSEvaluation ();
2274 if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR)
2276 size = AOP_SIZE (IC_LEFT (sic));
2284 emitcode("mov", "%s,%s",
2285 fReturn[size], regs390[size].name);
2288 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2295 emitcode ("mov", "psw,#0x%02x",
2296 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2300 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2301 OP_SYMBOL (IC_LEFT (ic))->rname :
2302 OP_SYMBOL (IC_LEFT (ic))->name));
2306 emitcode ("mov", "psw,#0x%02x",
2307 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2310 /* if we need assign a result value */
2311 if ((IS_ITEMP (IC_RESULT (ic)) &&
2312 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2313 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2314 IS_TRUE_SYMOP (IC_RESULT (ic)))
2316 if (isOperandInFarSpace (IC_RESULT (ic))
2317 && getSize (operandType (IC_RESULT (ic))) <= 2)
2319 int size = getSize (operandType (IC_RESULT (ic)));
2321 /* Special case for 1 or 2 byte return in far space. */
2325 emitcode ("mov", "b,%s", fReturn[1]);
2328 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2329 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2333 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2335 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2340 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2343 assignResultValue (IC_RESULT (ic));
2345 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2349 /* adjust the stack for parameters if
2354 if (ic->parmBytes > 3)
2356 emitcode ("mov", "a,%s", spname);
2357 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2358 emitcode ("mov", "%s,a", spname);
2361 for (i = 0; i < ic->parmBytes; i++)
2362 emitcode ("dec", "%s", spname);
2365 /* if we hade saved some registers then unsave them */
2366 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2367 unsaveRegisters (ic);
2369 /* if register bank was saved then pop them */
2371 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2374 /*-----------------------------------------------------------------*/
2375 /* genPcall - generates a call by pointer statement */
2376 /*-----------------------------------------------------------------*/
2378 genPcall (iCode * ic)
2381 symbol *rlbl = newiTempLabel (NULL);
2382 bool restoreBank=FALSE;
2384 D (emitcode (";", "genPcall ");
2388 /* if caller saves & we have not saved then */
2392 /* if we are calling a function that is not using
2393 the same register bank then we need to save the
2394 destination registers on the stack */
2395 dtype = operandType (IC_LEFT (ic));
2396 if (dtype && !IFFUNC_ISNAKED(dtype) &&
2397 IFFUNC_ISISR (currFunc->type) &&
2398 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2399 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2403 /* push the return address on to the stack */
2404 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2405 emitcode ("push", "acc");
2406 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2407 emitcode ("push", "acc");
2409 if (options.model == MODEL_FLAT24)
2411 emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2412 emitcode ("push", "acc");
2415 /* now push the calling address */
2416 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2418 pushSide (IC_LEFT (ic), FPTRSIZE);
2420 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2422 /* if send set is not empty the assign */
2427 for (sic = setFirstItem (_G.sendSet); sic;
2428 sic = setNextItem (_G.sendSet))
2430 int size, offset = 0;
2432 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2433 size = AOP_SIZE (IC_LEFT (sic));
2434 _startLazyDPSEvaluation ();
2437 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2438 FALSE, FALSE, TRUE);
2439 if (strcmp (l, fReturn[offset]))
2441 emitcode ("mov", "%s,%s",
2447 _endLazyDPSEvaluation ();
2448 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2453 emitcode ("ret", "");
2454 emitcode ("", "%05d$:", (rlbl->key + 100));
2457 /* if we need assign a result value */
2458 if ((IS_ITEMP (IC_RESULT (ic)) &&
2459 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2460 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2461 IS_TRUE_SYMOP (IC_RESULT (ic)))
2465 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2468 assignResultValue (IC_RESULT (ic));
2470 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2473 /* adjust the stack for parameters if
2478 if (ic->parmBytes > 3)
2480 emitcode ("mov", "a,%s", spname);
2481 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2482 emitcode ("mov", "%s,a", spname);
2485 for (i = 0; i < ic->parmBytes; i++)
2486 emitcode ("dec", "%s", spname);
2490 /* if register bank was saved then unsave them */
2492 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2494 /* if we hade saved some registers then
2496 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2497 unsaveRegisters (ic);
2501 /*-----------------------------------------------------------------*/
2502 /* resultRemat - result is rematerializable */
2503 /*-----------------------------------------------------------------*/
2505 resultRemat (iCode * ic)
2507 if (SKIP_IC (ic) || ic->op == IFX)
2510 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2512 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2513 if (sym->remat && !POINTER_SET (ic))
2520 #if defined(__BORLANDC__) || defined(_MSC_VER)
2521 #define STRCASECMP stricmp
2523 #define STRCASECMP strcasecmp
2526 /*-----------------------------------------------------------------*/
2527 /* inExcludeList - return 1 if the string is in exclude Reg list */
2528 /*-----------------------------------------------------------------*/
2530 inExcludeList (char *s)
2534 if (options.excludeRegs[i] &&
2535 STRCASECMP (options.excludeRegs[i], "none") == 0)
2538 for (i = 0; options.excludeRegs[i]; i++)
2540 if (options.excludeRegs[i] &&
2541 STRCASECMP (s, options.excludeRegs[i]) == 0)
2547 /*-----------------------------------------------------------------*/
2548 /* genFunction - generated code for function entry */
2549 /*-----------------------------------------------------------------*/
2551 genFunction (iCode * ic)
2555 bool switchedPSW = FALSE;
2557 D (emitcode (";", "genFunction "););
2560 /* create the function header */
2561 emitcode (";", "-----------------------------------------");
2562 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2563 emitcode (";", "-----------------------------------------");
2565 emitcode ("", "%s:", sym->rname);
2566 ftype = operandType (IC_LEFT (ic));
2568 if (IFFUNC_ISNAKED(ftype))
2570 emitcode(";", "naked function: no prologue.");
2574 /* if critical function then turn interrupts off */
2575 if (IFFUNC_ISCRITICAL (ftype))
2576 emitcode ("clr", "ea");
2578 /* here we need to generate the equates for the
2579 register bank if required */
2580 if (FUNC_REGBANK (ftype) != rbank)
2584 rbank = FUNC_REGBANK (ftype);
2585 for (i = 0; i < ds390_nRegs; i++)
2587 if (strcmp (regs390[i].base, "0") == 0)
2588 emitcode ("", "%s = 0x%02x",
2590 8 * rbank + regs390[i].offset);
2592 emitcode ("", "%s = %s + 0x%02x",
2595 8 * rbank + regs390[i].offset);
2599 /* if this is an interrupt service routine then
2600 save acc, b, dpl, dph */
2601 if (IFFUNC_ISISR (sym->type))
2604 if (!inExcludeList ("acc"))
2605 emitcode ("push", "acc");
2606 if (!inExcludeList ("b"))
2607 emitcode ("push", "b");
2608 if (!inExcludeList ("dpl"))
2609 emitcode ("push", "dpl");
2610 if (!inExcludeList ("dph"))
2611 emitcode ("push", "dph");
2612 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2614 emitcode ("push", "dpx");
2615 /* Make sure we're using standard DPTR */
2616 emitcode ("push", "dps");
2617 emitcode ("mov", "dps, #0x00");
2618 if (options.stack10bit)
2620 /* This ISR could conceivably use DPTR2. Better save it. */
2621 emitcode ("push", "dpl1");
2622 emitcode ("push", "dph1");
2623 emitcode ("push", "dpx1");
2624 emitcode ("push", DP2_RESULT_REG);
2627 /* if this isr has no bank i.e. is going to
2628 run with bank 0 , then we need to save more
2630 if (!FUNC_REGBANK (sym->type))
2633 /* if this function does not call any other
2634 function then we can be economical and
2635 save only those registers that are used */
2636 if (!IFFUNC_HASFCALL(sym->type))
2640 /* if any registers used */
2643 /* save the registers used */
2644 for (i = 0; i < sym->regsUsed->size; i++)
2646 if (bitVectBitValue (sym->regsUsed, i) ||
2647 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2648 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2655 /* this function has a function call cannot
2656 determines register usage so we will have to push the
2658 saveRBank (0, ic, FALSE);
2663 /* This ISR uses a non-zero bank.
2665 * We assume that the bank is available for our
2668 * However, if this ISR calls a function which uses some
2669 * other bank, we must save that bank entirely.
2671 unsigned long banksToSave = 0;
2673 if (IFFUNC_HASFCALL(sym->type))
2676 #define MAX_REGISTER_BANKS 4
2681 for (i = ic; i; i = i->next)
2683 if (i->op == ENDFUNCTION)
2685 /* we got to the end OK. */
2693 dtype = operandType (IC_LEFT(i));
2695 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2697 /* Mark this bank for saving. */
2698 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2700 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2704 banksToSave |= (1 << FUNC_REGBANK(dtype));
2707 /* And note that we don't need to do it in
2715 /* This is a mess; we have no idea what
2716 * register bank the called function might
2719 * The only thing I can think of to do is
2720 * throw a warning and hope.
2722 werror(W_FUNCPTR_IN_USING_ISR);
2726 if (banksToSave && options.useXstack)
2728 /* Since we aren't passing it an ic,
2729 * saveRBank will assume r0 is available to abuse.
2731 * So switch to our (trashable) bank now, so
2732 * the caller's R0 isn't trashed.
2734 emitcode ("push", "psw");
2735 emitcode ("mov", "psw,#0x%02x",
2736 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2740 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2742 if (banksToSave & (1 << ix))
2744 saveRBank(ix, NULL, FALSE);
2748 // jwk: this needs a closer look
2749 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2754 /* if callee-save to be used for this function
2755 then save the registers being used in this function */
2756 if (IFFUNC_CALLEESAVES(sym->type))
2760 /* if any registers used */
2763 /* save the registers used */
2764 for (i = 0; i < sym->regsUsed->size; i++)
2766 if (bitVectBitValue (sym->regsUsed, i) ||
2767 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2769 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2777 /* set the register bank to the desired value */
2778 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2781 emitcode ("push", "psw");
2782 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2785 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2788 if (options.useXstack)
2790 emitcode ("mov", "r0,%s", spname);
2791 emitcode ("mov", "a,_bp");
2792 emitcode ("movx", "@r0,a");
2793 emitcode ("inc", "%s", spname);
2797 /* set up the stack */
2798 emitcode ("push", "_bp"); /* save the callers stack */
2800 emitcode ("mov", "_bp,%s", spname);
2803 /* adjust the stack for the function */
2809 werror (W_STACK_OVERFLOW, sym->name);
2811 if (i > 3 && sym->recvSize < 4)
2814 emitcode ("mov", "a,sp");
2815 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2816 emitcode ("mov", "sp,a");
2821 emitcode ("inc", "sp");
2827 emitcode ("mov", "a,_spx");
2828 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2829 emitcode ("mov", "_spx,a");
2834 /*-----------------------------------------------------------------*/
2835 /* genEndFunction - generates epilogue for functions */
2836 /*-----------------------------------------------------------------*/
2838 genEndFunction (iCode * ic)
2840 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2842 D (emitcode (";", "genEndFunction "););
2844 if (IFFUNC_ISNAKED(sym->type))
2846 emitcode(";", "naked function: no epilogue.");
2850 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2852 emitcode ("mov", "%s,_bp", spname);
2855 /* if use external stack but some variables were
2856 added to the local stack then decrement the
2858 if (options.useXstack && sym->stack)
2860 emitcode ("mov", "a,sp");
2861 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2862 emitcode ("mov", "sp,a");
2866 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2868 if (options.useXstack)
2870 emitcode ("mov", "r0,%s", spname);
2871 emitcode ("movx", "a,@r0");
2872 emitcode ("mov", "_bp,a");
2873 emitcode ("dec", "%s", spname);
2877 emitcode ("pop", "_bp");
2881 /* restore the register bank */
2882 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2884 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
2885 || !options.useXstack)
2887 /* Special case of ISR using non-zero bank with useXstack
2890 emitcode ("pop", "psw");
2894 if (IFFUNC_ISISR (sym->type))
2897 /* now we need to restore the registers */
2898 /* if this isr has no bank i.e. is going to
2899 run with bank 0 , then we need to save more
2901 if (!FUNC_REGBANK (sym->type))
2903 /* if this function does not call any other
2904 function then we can be economical and
2905 save only those registers that are used */
2906 if (!IFFUNC_HASFCALL(sym->type))
2910 /* if any registers used */
2913 /* save the registers used */
2914 for (i = sym->regsUsed->size; i >= 0; i--)
2916 if (bitVectBitValue (sym->regsUsed, i) ||
2917 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2918 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2925 /* this function has a function call cannot
2926 determines register usage so we will have to pop the
2928 unsaveRBank (0, ic, FALSE);
2933 /* This ISR uses a non-zero bank.
2935 * Restore any register banks saved by genFunction
2938 // jwk: this needs a closer look
2939 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2942 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2944 if (savedBanks & (1 << ix))
2946 unsaveRBank(ix, NULL, FALSE);
2950 if (options.useXstack)
2952 /* Restore bank AFTER calling unsaveRBank,
2953 * since it can trash r0.
2955 emitcode ("pop", "psw");
2959 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2961 if (options.stack10bit)
2963 emitcode ("pop", DP2_RESULT_REG);
2964 emitcode ("pop", "dpx1");
2965 emitcode ("pop", "dph1");
2966 emitcode ("pop", "dpl1");
2968 emitcode ("pop", "dps");
2969 emitcode ("pop", "dpx");
2971 if (!inExcludeList ("dph"))
2972 emitcode ("pop", "dph");
2973 if (!inExcludeList ("dpl"))
2974 emitcode ("pop", "dpl");
2975 if (!inExcludeList ("b"))
2976 emitcode ("pop", "b");
2977 if (!inExcludeList ("acc"))
2978 emitcode ("pop", "acc");
2980 if (IFFUNC_ISCRITICAL (sym->type))
2981 emitcode ("setb", "ea");
2983 /* if debug then send end of function */
2984 if (options.debug && currFunc) {
2986 emitcode ("", "C$%s$%d$%d$%d ==.",
2987 FileBaseName (ic->filename), currFunc->lastLine,
2988 ic->level, ic->block);
2989 if (IS_STATIC (currFunc->etype))
2990 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2992 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2996 emitcode ("reti", "");
3000 if (IFFUNC_ISCRITICAL (sym->type))
3001 emitcode ("setb", "ea");
3003 if (IFFUNC_CALLEESAVES(sym->type))
3007 /* if any registers used */
3010 /* save the registers used */
3011 for (i = sym->regsUsed->size; i >= 0; i--)
3013 if (bitVectBitValue (sym->regsUsed, i) ||
3014 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3015 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3021 /* if debug then send end of function */
3022 if (options.debug && currFunc)
3025 emitcode ("", "C$%s$%d$%d$%d ==.",
3026 FileBaseName (ic->filename), currFunc->lastLine,
3027 ic->level, ic->block);
3028 if (IS_STATIC (currFunc->etype))
3029 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3031 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3035 emitcode ("ret", "");
3040 /*-----------------------------------------------------------------*/
3041 /* genRet - generate code for return statement */
3042 /*-----------------------------------------------------------------*/
3046 int size, offset = 0, pushed = 0;
3048 D (emitcode (";", "genRet ");
3051 /* if we have no return value then
3052 just generate the "ret" */
3056 /* we have something to return then
3057 move the return value into place */
3058 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
3059 size = AOP_SIZE (IC_LEFT (ic));
3061 _startLazyDPSEvaluation ();
3065 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3067 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3068 FALSE, TRUE, FALSE);
3069 emitcode ("push", "%s", l);
3074 /* Since A is the last element of fReturn,
3075 * is is OK to clobber it in the aopGet.
3077 l = aopGet (AOP (IC_LEFT (ic)), offset,
3078 FALSE, FALSE, TRUE);
3079 if (strcmp (fReturn[offset], l))
3080 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3083 _endLazyDPSEvaluation ();
3090 if (strcmp (fReturn[pushed], "a"))
3091 emitcode ("pop", fReturn[pushed]);
3093 emitcode ("pop", "acc");
3096 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3099 /* generate a jump to the return label
3100 if the next is not the return statement */
3101 if (!(ic->next && ic->next->op == LABEL &&
3102 IC_LABEL (ic->next) == returnLabel))
3104 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3108 /*-----------------------------------------------------------------*/
3109 /* genLabel - generates a label */
3110 /*-----------------------------------------------------------------*/
3112 genLabel (iCode * ic)
3114 /* special case never generate */
3115 if (IC_LABEL (ic) == entryLabel)
3118 D (emitcode (";", "genLabel ");
3121 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3124 /*-----------------------------------------------------------------*/
3125 /* genGoto - generates a ljmp */
3126 /*-----------------------------------------------------------------*/
3128 genGoto (iCode * ic)
3130 D (emitcode (";", "genGoto ");
3132 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3135 /*-----------------------------------------------------------------*/
3136 /* findLabelBackwards: walks back through the iCode chain looking */
3137 /* for the given label. Returns number of iCode instructions */
3138 /* between that label and given ic. */
3139 /* Returns zero if label not found. */
3140 /*-----------------------------------------------------------------*/
3142 findLabelBackwards (iCode * ic, int key)
3151 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3153 /* printf("findLabelBackwards = %d\n", count); */
3161 /*-----------------------------------------------------------------*/
3162 /* genPlusIncr :- does addition with increment if possible */
3163 /*-----------------------------------------------------------------*/
3165 genPlusIncr (iCode * ic)
3167 unsigned int icount;
3168 unsigned int size = getDataSize (IC_RESULT (ic));
3170 /* will try to generate an increment */
3171 /* if the right side is not a literal
3173 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3176 /* if the literal value of the right hand side
3177 is greater than 4 then it is not worth it */
3178 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3181 /* if increment 16 bits in register */
3183 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3184 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3185 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3193 /* If the next instruction is a goto and the goto target
3194 * is <= 5 instructions previous to this, we can generate
3195 * jumps straight to that target.
3197 if (ic->next && ic->next->op == GOTO
3198 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3201 emitcode (";", "tail increment optimized (range %d)", labelRange);
3202 tlbl = IC_LABEL (ic->next);
3207 tlbl = newiTempLabel (NULL);
3210 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3211 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3212 IS_AOP_PREG (IC_RESULT (ic)))
3213 emitcode ("cjne", "%s,#0x00,%05d$"
3214 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3218 emitcode ("clr", "a");
3219 emitcode ("cjne", "a,%s,%05d$"
3220 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3224 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3227 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3228 IS_AOP_PREG (IC_RESULT (ic)))
3229 emitcode ("cjne", "%s,#0x00,%05d$"
3230 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3233 emitcode ("cjne", "a,%s,%05d$"
3234 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3237 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3241 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3242 IS_AOP_PREG (IC_RESULT (ic)))
3243 emitcode ("cjne", "%s,#0x00,%05d$"
3244 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3248 emitcode ("cjne", "a,%s,%05d$"
3249 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3252 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3257 emitcode ("", "%05d$:", tlbl->key + 100);
3262 /* if the sizes are greater than 1 then we cannot */
3263 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3264 AOP_SIZE (IC_LEFT (ic)) > 1)
3267 /* we can if the aops of the left & result match or
3268 if they are in registers and the registers are the
3271 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3272 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3273 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3278 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3279 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3280 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3285 _startLazyDPSEvaluation ();
3288 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3290 _endLazyDPSEvaluation ();
3299 /*-----------------------------------------------------------------*/
3300 /* outBitAcc - output a bit in acc */
3301 /*-----------------------------------------------------------------*/
3303 outBitAcc (operand * result)
3305 symbol *tlbl = newiTempLabel (NULL);
3306 /* if the result is a bit */
3307 if (AOP_TYPE (result) == AOP_CRY)
3309 aopPut (AOP (result), "a", 0);
3313 emitcode ("jz", "%05d$", tlbl->key + 100);
3314 emitcode ("mov", "a,%s", one);
3315 emitcode ("", "%05d$:", tlbl->key + 100);
3320 /*-----------------------------------------------------------------*/
3321 /* genPlusBits - generates code for addition of two bits */
3322 /*-----------------------------------------------------------------*/
3324 genPlusBits (iCode * ic)
3326 D (emitcode (";", "genPlusBits ");
3328 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3330 symbol *lbl = newiTempLabel (NULL);
3331 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3332 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3333 emitcode ("cpl", "c");
3334 emitcode ("", "%05d$:", (lbl->key + 100));
3335 outBitC (IC_RESULT (ic));
3339 emitcode ("clr", "a");
3340 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3341 emitcode ("rlc", "a");
3342 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3343 emitcode ("addc", "a,#0x00");
3344 outAcc (IC_RESULT (ic));
3349 adjustArithmeticResult (iCode * ic)
3351 if (opIsGptr (IC_RESULT (ic)) &&
3352 opIsGptr (IC_LEFT (ic)) &&
3353 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3355 aopPut (AOP (IC_RESULT (ic)),
3356 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3360 if (opIsGptr (IC_RESULT (ic)) &&
3361 opIsGptr (IC_RIGHT (ic)) &&
3362 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3364 aopPut (AOP (IC_RESULT (ic)),
3365 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3369 if (opIsGptr (IC_RESULT (ic)) &&
3370 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3371 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3372 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3373 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3376 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3377 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3381 #if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
3382 // Please don't bring it back without a really good reason.
3383 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3384 // (because all three operands are in far space).
3385 #define AOP_OP_3(ic) \
3386 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3387 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3388 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3389 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3390 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3391 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3393 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3395 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3399 // Macro to aopOp all three operands of an ic. If this cannot be done,
3400 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3401 // will be set TRUE. The caller must then handle the case specially, noting
3402 // that the IC_RESULT operand is not aopOp'd.
3403 #define AOP_OP_3_NOFATAL(ic, rc) \
3404 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3405 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3406 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3407 isOperandInFarSpace(IC_RESULT(ic))) \
3409 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3414 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3415 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3417 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3418 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3420 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3422 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3426 // aopOp the left & right operands of an ic.
3427 #define AOP_OP_2(ic) \
3428 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3429 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3431 // convienience macro.
3432 #define AOP_SET_LOCALS(ic) \
3433 left = IC_LEFT(ic); \
3434 right = IC_RIGHT(ic); \
3435 result = IC_RESULT(ic);
3438 // Given an integer value of pushedSize bytes on the stack,
3439 // adjust it to be resultSize bytes, either by discarding
3440 // the most significant bytes or by zero-padding.
3442 // On exit from this macro, pushedSize will have been adjusted to
3443 // equal resultSize, and ACC may be trashed.
3444 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3445 /* If the pushed data is bigger than the result, \
3446 * simply discard unused bytes. Icky, but works. \
3448 while (pushedSize > resultSize) \
3450 D (emitcode (";", "discarding unused result byte."););\
3451 emitcode ("pop", "acc"); \
3454 if (pushedSize < resultSize) \
3456 emitcode ("clr", "a"); \
3457 /* Conversly, we haven't pushed enough here. \
3458 * just zero-pad, and all is well. \
3460 while (pushedSize < resultSize) \
3462 emitcode("push", "acc"); \
3466 assert(pushedSize == resultSize);
3468 /*-----------------------------------------------------------------*/
3469 /* genPlus - generates code for addition */
3470 /*-----------------------------------------------------------------*/
3472 genPlus (iCode * ic)
3474 int size, offset = 0;
3475 bool pushResult = FALSE;
3478 D (emitcode (";", "genPlus "););
3480 /* special cases :- */
3482 AOP_OP_3_NOFATAL (ic, pushResult);
3485 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3490 /* if literal, literal on the right or
3491 if left requires ACC or right is already
3493 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3494 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3495 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3497 operand *t = IC_RIGHT (ic);
3498 IC_RIGHT (ic) = IC_LEFT (ic);
3500 emitcode (";", "Swapped plus args.");
3503 /* if both left & right are in bit
3505 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3506 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3512 /* if left in bit space & right literal */
3513 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3514 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3516 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3517 /* if result in bit space */
3518 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3520 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3521 emitcode ("cpl", "c");
3522 outBitC (IC_RESULT (ic));
3526 size = getDataSize (IC_RESULT (ic));
3527 _startLazyDPSEvaluation ();
3530 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3531 emitcode ("addc", "a,#00");
3532 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3534 _endLazyDPSEvaluation ();
3539 /* if I can do an increment instead
3540 of add then GOOD for ME */
3541 if (genPlusIncr (ic) == TRUE)
3543 emitcode (";", "did genPlusIncr");
3548 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3550 _startLazyDPSEvaluation ();
3553 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3555 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3557 emitcode ("add", "a,%s",
3558 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3560 emitcode ("addc", "a,%s",
3561 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3565 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3567 /* right is going to use ACC or we would have taken the
3570 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3572 D(emitcode(";", "+ AOP_ACC special case."););
3573 emitcode("xch", "a, %s", DP2_RESULT_REG);
3575 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3578 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3581 emitcode("add", "a, %s", DP2_RESULT_REG);
3585 emitcode ("add", "a,%s",
3586 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3591 emitcode ("addc", "a,%s",
3592 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3597 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3601 emitcode ("push", "acc");
3605 _endLazyDPSEvaluation ();
3609 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3611 size = getDataSize (IC_LEFT (ic));
3612 rSize = getDataSize (IC_RESULT (ic));
3614 ADJUST_PUSHED_RESULT(size, rSize);
3616 _startLazyDPSEvaluation ();
3619 emitcode ("pop", "acc");
3620 aopPut (AOP (IC_RESULT (ic)), "a", size);
3622 _endLazyDPSEvaluation ();
3625 adjustArithmeticResult (ic);
3628 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3629 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3630 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3633 /*-----------------------------------------------------------------*/
3634 /* genMinusDec :- does subtraction with deccrement if possible */
3635 /*-----------------------------------------------------------------*/
3637 genMinusDec (iCode * ic)
3639 unsigned int icount;
3640 unsigned int size = getDataSize (IC_RESULT (ic));
3642 /* will try to generate an increment */
3643 /* if the right side is not a literal
3645 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3648 /* if the literal value of the right hand side
3649 is greater than 4 then it is not worth it */
3650 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3653 /* if decrement 16 bits in register */
3654 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3655 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3656 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3664 /* If the next instruction is a goto and the goto target
3665 * is <= 5 instructions previous to this, we can generate
3666 * jumps straight to that target.
3668 if (ic->next && ic->next->op == GOTO
3669 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3672 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3673 tlbl = IC_LABEL (ic->next);
3678 tlbl = newiTempLabel (NULL);
3682 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3683 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3684 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3685 IS_AOP_PREG (IC_RESULT (ic)))
3686 emitcode ("cjne", "%s,#0xff,%05d$"
3687 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3691 emitcode ("mov", "a,#0xff");
3692 emitcode ("cjne", "a,%s,%05d$"
3693 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3696 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3699 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3700 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3701 IS_AOP_PREG (IC_RESULT (ic)))
3702 emitcode ("cjne", "%s,#0xff,%05d$"
3703 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3707 emitcode ("cjne", "a,%s,%05d$"
3708 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3711 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3715 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3716 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3717 IS_AOP_PREG (IC_RESULT (ic)))
3718 emitcode ("cjne", "%s,#0xff,%05d$"
3719 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3723 emitcode ("cjne", "a,%s,%05d$"
3724 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3727 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3731 emitcode ("", "%05d$:", tlbl->key + 100);
3736 /* if the sizes are greater than 1 then we cannot */
3737 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3738 AOP_SIZE (IC_LEFT (ic)) > 1)
3741 /* we can if the aops of the left & result match or
3742 if they are in registers and the registers are the
3745 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3746 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3747 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3750 _startLazyDPSEvaluation ();
3753 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3755 _endLazyDPSEvaluation ();
3763 /*-----------------------------------------------------------------*/
3764 /* addSign - complete with sign */
3765 /*-----------------------------------------------------------------*/
3767 addSign (operand * result, int offset, int sign)
3769 int size = (getDataSize (result) - offset);
3772 _startLazyDPSEvaluation();
3775 emitcode ("rlc", "a");
3776 emitcode ("subb", "a,acc");
3779 aopPut (AOP (result), "a", offset++);
3786 aopPut (AOP (result), zero, offset++);
3789 _endLazyDPSEvaluation();
3793 /*-----------------------------------------------------------------*/
3794 /* genMinusBits - generates code for subtraction of two bits */
3795 /*-----------------------------------------------------------------*/
3797 genMinusBits (iCode * ic)
3799 symbol *lbl = newiTempLabel (NULL);
3801 D (emitcode (";", "genMinusBits "););
3803 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3805 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3806 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3807 emitcode ("cpl", "c");
3808 emitcode ("", "%05d$:", (lbl->key + 100));
3809 outBitC (IC_RESULT (ic));
3813 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3814 emitcode ("subb", "a,acc");
3815 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3816 emitcode ("inc", "a");
3817 emitcode ("", "%05d$:", (lbl->key + 100));
3818 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3819 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3823 /*-----------------------------------------------------------------*/
3824 /* genMinus - generates code for subtraction */
3825 /*-----------------------------------------------------------------*/
3827 genMinus (iCode * ic)
3829 int size, offset = 0;
3831 unsigned long lit = 0L;
3832 bool pushResult = FALSE;
3834 D (emitcode (";", "genMinus "););
3836 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3837 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3838 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3839 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3845 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3847 /* special cases :- */
3848 /* if both left & right are in bit space */
3849 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3850 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3856 /* if I can do an decrement instead
3857 of subtract then GOOD for ME */
3858 if (genMinusDec (ic) == TRUE)
3863 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3865 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3871 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3876 /* if literal, add a,#-lit, else normal subb */
3877 _startLazyDPSEvaluation ();
3880 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3881 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3882 emitcode ("subb", "a,%s",
3883 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3886 /* first add without previous c */
3888 if (!size && lit==-1) {
3889 emitcode ("dec", "a");
3891 emitcode ("add", "a,#0x%02x",
3892 (unsigned int) (lit & 0x0FFL));
3895 emitcode ("addc", "a,#0x%02x",
3896 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3902 emitcode ("push", "acc");
3906 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3910 _endLazyDPSEvaluation ();
3914 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3916 size = getDataSize (IC_LEFT (ic));
3917 rSize = getDataSize (IC_RESULT (ic));
3919 ADJUST_PUSHED_RESULT(size, rSize);
3921 _startLazyDPSEvaluation ();
3924 emitcode ("pop", "acc");
3925 aopPut (AOP (IC_RESULT (ic)), "a", size);
3927 _endLazyDPSEvaluation ();
3930 adjustArithmeticResult (ic);
3933 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3934 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3935 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3939 /*-----------------------------------------------------------------*/
3940 /* genMultbits :- multiplication of bits */
3941 /*-----------------------------------------------------------------*/
3943 genMultbits (operand * left,
3948 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3949 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3950 aopOp(result, ic, TRUE, FALSE);
3955 /*-----------------------------------------------------------------*/
3956 /* genMultOneByte : 8*8=8/16 bit multiplication */
3957 /*-----------------------------------------------------------------*/
3959 genMultOneByte (operand * left,
3964 sym_link *opetype = operandType (result);
3968 /* (if two literals: the value is computed before) */
3969 /* if one literal, literal on the right */
3970 if (AOP_TYPE (left) == AOP_LIT)
3975 emitcode (";", "swapped left and right");
3978 if (SPEC_USIGN(opetype)
3979 // ignore the sign of left and right, what else can we do?
3980 || (SPEC_USIGN(operandType(left)) &&
3981 SPEC_USIGN(operandType(right)))) {
3982 // just an unsigned 8*8=8/16 multiply
3983 //emitcode (";","unsigned");
3984 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3985 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3986 emitcode ("mul", "ab");
3989 aopOp(result, ic, TRUE, FALSE);
3991 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
3993 // this should never happen
3994 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3995 AOP_SIZE(result), __FILE__, lineno);
3999 aopPut (AOP (result), "a", 0);
4001 if (AOP_SIZE(result)==2)
4003 aopPut (AOP (result), "b", 1);
4008 // we have to do a signed multiply
4010 emitcode (";", "signed");
4011 emitcode ("clr", "F0"); // reset sign flag
4012 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4014 lbl=newiTempLabel(NULL);
4015 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
4016 // left side is negative, 8-bit two's complement, this fails for -128
4017 emitcode ("setb", "F0"); // set sign flag
4018 emitcode ("cpl", "a");
4019 emitcode ("inc", "a");
4021 emitcode ("", "%05d$:", lbl->key+100);
4024 if (AOP_TYPE(right)==AOP_LIT) {
4025 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4026 /* AND literal negative */
4027 if ((int) val < 0) {
4028 emitcode ("cpl", "F0"); // complement sign flag
4029 emitcode ("mov", "b,#0x%02x", -val);
4031 emitcode ("mov", "b,#0x%02x", val);
4034 lbl=newiTempLabel(NULL);
4035 emitcode ("mov", "b,a");
4036 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4037 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
4038 // right side is negative, 8-bit two's complement
4039 emitcode ("cpl", "F0"); // complement sign flag
4040 emitcode ("cpl", "a");
4041 emitcode ("inc", "a");
4042 emitcode ("", "%05d$:", lbl->key+100);
4044 emitcode ("mul", "ab");
4047 aopOp(result, ic, TRUE, FALSE);
4049 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4051 // this should never happen
4052 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4053 AOP_SIZE(result), __FILE__, lineno);
4057 lbl=newiTempLabel(NULL);
4058 emitcode ("jnb", "F0,%05d$", lbl->key+100);
4059 // only ONE op was negative, we have to do a 8/16-bit two's complement
4060 emitcode ("cpl", "a"); // lsb
4061 if (AOP_SIZE(result)==1) {
4062 emitcode ("inc", "a");
4064 emitcode ("add", "a,#1");
4065 emitcode ("xch", "a,b");
4066 emitcode ("cpl", "a"); // msb
4067 emitcode ("addc", "a,#0");
4068 emitcode ("xch", "a,b");
4071 emitcode ("", "%05d$:", lbl->key+100);
4072 aopPut (AOP (result), "a", 0);
4074 if (AOP_SIZE(result)==2) {
4075 aopPut (AOP (result), "b", 1);
4079 /*-----------------------------------------------------------------*/
4080 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4081 /*-----------------------------------------------------------------*/
4082 static void genMultTwoByte (operand *left, operand *right,
4083 operand *result, iCode *ic)
4085 sym_link *retype = getSpec(operandType(right));
4086 sym_link *letype = getSpec(operandType(left));
4087 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4090 if (AOP_TYPE (left) == AOP_LIT) {
4095 /* save EA bit in F1 */
4096 lbl = newiTempLabel(NULL);
4097 emitcode ("setb","F1");
4098 emitcode ("jbc","EA,%05d$",lbl->key+100);
4099 emitcode ("clr","F1");
4100 emitcode("","%05d$:",lbl->key+100);
4102 /* load up MB with right */
4104 emitcode("clr","F0");
4105 if (AOP_TYPE(right) == AOP_LIT) {
4106 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4108 emitcode("setb","F0");
4111 emitcode ("mov","mb,#0x%02x",val & 0xff);
4112 emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4114 lbl = newiTempLabel(NULL);
4115 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4116 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4117 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4118 emitcode ("xch", "a,b");
4119 emitcode ("cpl","a");
4120 emitcode ("add", "a,#1");
4121 emitcode ("xch", "a,b");
4122 emitcode ("cpl", "a"); // msb
4123 emitcode ("addc", "a,#0");
4124 emitcode ("setb","F0");
4125 emitcode ("","%05d$:",lbl->key+100);
4126 emitcode ("mov","mb,b");
4127 emitcode ("mov","mb,a");
4130 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4131 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4133 /* load up MA with left */
4135 lbl = newiTempLabel(NULL);
4136 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4137 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4138 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4139 emitcode ("xch", "a,b");
4140 emitcode ("cpl","a");
4141 emitcode ("add", "a,#1");
4142 emitcode ("xch", "a,b");
4143 emitcode ("cpl", "a"); // msb
4144 emitcode ("addc","a,#0");
4145 emitcode ("jbc","F0,%05d$",lbl->key+100);
4146 emitcode ("setb","F0");
4147 emitcode ("","%05d$:",lbl->key+100);
4148 emitcode ("mov","ma,b");
4149 emitcode ("mov","ma,a");
4151 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4152 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4154 /* wait for multiplication to finish */
4155 lbl = newiTempLabel(NULL);
4156 emitcode("","%05d$:", lbl->key+100);
4157 emitcode("mov","a,mcnt1");
4158 emitcode("anl","a,#0x80");
4159 emitcode("jnz","%05d$",lbl->key+100);
4161 freeAsmop (left, NULL, ic, TRUE);
4162 freeAsmop (right, NULL, ic,TRUE);
4163 aopOp(result, ic, TRUE, FALSE);
4165 /* if unsigned then simple */
4167 emitcode ("mov","a,ma");
4168 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4169 emitcode ("mov","a,ma");
4170 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4171 aopPut(AOP(result),"ma",1);
4172 aopPut(AOP(result),"ma",0);
4174 emitcode("push","ma");
4175 emitcode("push","ma");
4176 emitcode("push","ma");
4178 /* negate result if needed */
4179 lbl = newiTempLabel(NULL);
4180 emitcode("jnb","F0,%05d$",lbl->key+100);
4181 emitcode("cpl","a");
4182 emitcode("add","a,#1");
4183 emitcode("","%05d$:", lbl->key+100);
4184 if (AOP_TYPE(result) == AOP_ACC)
4186 D(emitcode(";", "ACC special case."););
4187 /* We know result is the only live aop, and
4188 * it's obviously not a DPTR2, so AP is available.
4190 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4194 aopPut(AOP(result),"a",0);
4197 emitcode("pop","acc");
4198 lbl = newiTempLabel(NULL);
4199 emitcode("jnb","F0,%05d$",lbl->key+100);
4200 emitcode("cpl","a");
4201 emitcode("addc","a,#0");
4202 emitcode("","%05d$:", lbl->key+100);
4203 aopPut(AOP(result),"a",1);
4204 emitcode("pop","acc");
4205 if (AOP_SIZE(result) >= 3) {
4206 lbl = newiTempLabel(NULL);
4207 emitcode("jnb","F0,%05d$",lbl->key+100);
4208 emitcode("cpl","a");
4209 emitcode("addc","a,#0");
4210 emitcode("","%05d$:", lbl->key+100);
4211 aopPut(AOP(result),"a",2);
4213 emitcode("pop","acc");
4214 if (AOP_SIZE(result) >= 4) {
4215 lbl = newiTempLabel(NULL);
4216 emitcode("jnb","F0,%05d$",lbl->key+100);
4217 emitcode("cpl","a");
4218 emitcode("addc","a,#0");
4219 emitcode("","%05d$:", lbl->key+100);
4220 aopPut(AOP(result),"a",3);
4222 if (AOP_TYPE(result) == AOP_ACC)
4224 /* We stashed the result away above. */
4225 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4229 freeAsmop (result, NULL, ic, TRUE);
4231 /* restore EA bit in F1 */
4232 lbl = newiTempLabel(NULL);
4233 emitcode ("jnb","F1,%05d$",lbl->key+100);
4234 emitcode ("setb","EA");
4235 emitcode("","%05d$:",lbl->key+100);
4239 /*-----------------------------------------------------------------*/
4240 /* genMult - generates code for multiplication */
4241 /*-----------------------------------------------------------------*/
4243 genMult (iCode * ic)
4245 operand *left = IC_LEFT (ic);
4246 operand *right = IC_RIGHT (ic);
4247 operand *result = IC_RESULT (ic);
4249 D (emitcode (";", "genMult "););
4251 /* assign the amsops */
4254 /* special cases first */
4256 if (AOP_TYPE (left) == AOP_CRY &&
4257 AOP_TYPE (right) == AOP_CRY)
4259 genMultbits (left, right, result, ic);
4263 /* if both are of size == 1 */
4264 if (AOP_SIZE (left) == 1 &&
4265 AOP_SIZE (right) == 1)
4267 genMultOneByte (left, right, result, ic);
4271 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4272 /* use the ds390 ARITHMETIC accel UNIT */
4273 genMultTwoByte (left, right, result, ic);
4276 /* should have been converted to function call */
4280 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4281 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4282 freeAsmop (result, NULL, ic, TRUE);
4285 /*-----------------------------------------------------------------*/
4286 /* genDivbits :- division of bits */
4287 /*-----------------------------------------------------------------*/
4289 genDivbits (operand * left,
4297 /* the result must be bit */
4298 LOAD_AB_FOR_DIV (left, right, l);
4299 emitcode ("div", "ab");
4300 emitcode ("rrc", "a");
4301 aopOp(result, ic, TRUE, FALSE);
4303 aopPut (AOP (result), "c", 0);
4306 /*-----------------------------------------------------------------*/
4307 /* genDivOneByte : 8 bit division */
4308 /*-----------------------------------------------------------------*/
4310 genDivOneByte (operand * left,
4315 sym_link *opetype = operandType (result);
4321 /* signed or unsigned */
4322 if (SPEC_USIGN (opetype))
4324 /* unsigned is easy */
4325 LOAD_AB_FOR_DIV (left, right, l);
4326 emitcode ("div", "ab");
4329 aopOp(result, ic, TRUE, FALSE);
4330 aopPut (AOP (result), "a", 0);
4333 size = AOP_SIZE (result) - 1;
4337 aopPut (AOP (result), zero, offset++);
4342 /* signed is a little bit more difficult */
4344 /* save the signs of the operands */
4345 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4347 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4348 emitcode ("push", "acc"); /* save it on the stack */
4350 /* now sign adjust for both left & right */
4351 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4353 lbl = newiTempLabel (NULL);
4354 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4355 emitcode ("cpl", "a");
4356 emitcode ("inc", "a");
4357 emitcode ("", "%05d$:", (lbl->key + 100));
4358 emitcode ("mov", "b,a");
4360 /* sign adjust left side */
4361 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4364 lbl = newiTempLabel (NULL);
4365 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4366 emitcode ("cpl", "a");
4367 emitcode ("inc", "a");
4368 emitcode ("", "%05d$:", (lbl->key + 100));
4370 /* now the division */
4371 emitcode ("nop", "; workaround for DS80C390 div bug.");
4372 emitcode ("div", "ab");
4373 /* we are interested in the lower order
4375 emitcode ("mov", "b,a");
4376 lbl = newiTempLabel (NULL);
4377 emitcode ("pop", "acc");
4378 /* if there was an over flow we don't
4379 adjust the sign of the result */
4380 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4381 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4383 emitcode ("clr", "a");
4384 emitcode ("subb", "a,b");
4385 emitcode ("mov", "b,a");
4386 emitcode ("", "%05d$:", (lbl->key + 100));
4388 /* now we are done */
4390 aopOp(result, ic, TRUE, FALSE);
4392 aopPut (AOP (result), "b", 0);
4394 size = AOP_SIZE (result) - 1;
4398 emitcode ("mov", "c,b.7");
4399 emitcode ("subb", "a,acc");
4403 aopPut (AOP (result), "a", offset++);
4409 /*-----------------------------------------------------------------*/
4410 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4411 /*-----------------------------------------------------------------*/
4412 static void genDivTwoByte (operand *left, operand *right,
4413 operand *result, iCode *ic)
4415 sym_link *retype = getSpec(operandType(right));
4416 sym_link *letype = getSpec(operandType(left));
4417 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4420 /* save EA bit in F1 */
4421 lbl = newiTempLabel(NULL);
4422 emitcode ("setb","F1");
4423 emitcode ("jbc","EA,%05d$",lbl->key+100);
4424 emitcode ("clr","F1");
4425 emitcode("","%05d$:",lbl->key+100);
4427 /* load up MA with left */
4429 emitcode("clr","F0");
4430 lbl = newiTempLabel(NULL);
4431 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4432 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4433 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4434 emitcode ("xch", "a,b");
4435 emitcode ("cpl","a");
4436 emitcode ("add", "a,#1");
4437 emitcode ("xch", "a,b");
4438 emitcode ("cpl", "a"); // msb
4439 emitcode ("addc","a,#0");
4440 emitcode ("setb","F0");
4441 emitcode ("","%05d$:",lbl->key+100);
4442 emitcode ("mov","ma,b");
4443 emitcode ("mov","ma,a");
4445 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4446 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4449 /* load up MB with right */
4451 if (AOP_TYPE(right) == AOP_LIT) {
4452 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4454 lbl = newiTempLabel(NULL);
4455 emitcode ("jbc","F0,%05d$",lbl->key+100);
4456 emitcode("setb","F0");
4457 emitcode ("","%05d$:",lbl->key+100);
4460 emitcode ("mov","mb,#0x%02x",val & 0xff);
4461 emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4463 lbl = newiTempLabel(NULL);
4464 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4465 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4466 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4467 emitcode ("xch", "a,b");
4468 emitcode ("cpl","a");
4469 emitcode ("add", "a,#1");
4470 emitcode ("xch", "a,b");
4471 emitcode ("cpl", "a"); // msb
4472 emitcode ("addc", "a,#0");
4473 emitcode ("jbc","F0,%05d$",lbl->key+100);
4474 emitcode ("setb","F0");
4475 emitcode ("","%05d$:",lbl->key+100);
4476 emitcode ("mov","mb,b");
4477 emitcode ("mov","mb,a");
4480 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4481 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4484 /* wait for multiplication to finish */
4485 lbl = newiTempLabel(NULL);
4486 emitcode("","%05d$:", lbl->key+100);
4487 emitcode("mov","a,mcnt1");
4488 emitcode("anl","a,#0x80");
4489 emitcode("jnz","%05d$",lbl->key+100);
4491 freeAsmop (left, NULL, ic, TRUE);
4492 freeAsmop (right, NULL, ic,TRUE);
4493 aopOp(result, ic, TRUE, FALSE);
4495 /* if unsigned then simple */
4497 aopPut(AOP(result),"ma",1);
4498 aopPut(AOP(result),"ma",0);
4500 emitcode("push","ma");
4502 /* negate result if needed */
4503 lbl = newiTempLabel(NULL);
4504 emitcode("jnb","F0,%05d$",lbl->key+100);
4505 emitcode("cpl","a");
4506 emitcode("add","a,#1");
4507 emitcode("","%05d$:", lbl->key+100);
4508 aopPut(AOP(result),"a",0);
4509 emitcode("pop","acc");
4510 lbl = newiTempLabel(NULL);
4511 emitcode("jnb","F0,%05d$",lbl->key+100);
4512 emitcode("cpl","a");
4513 emitcode("addc","a,#0");
4514 emitcode("","%05d$:", lbl->key+100);
4515 aopPut(AOP(result),"a",1);
4517 freeAsmop (result, NULL, ic, TRUE);
4518 /* restore EA bit in F1 */
4519 lbl = newiTempLabel(NULL);
4520 emitcode ("jnb","F1,%05d$",lbl->key+100);
4521 emitcode ("setb","EA");
4522 emitcode("","%05d$:",lbl->key+100);
4526 /*-----------------------------------------------------------------*/
4527 /* genDiv - generates code for division */
4528 /*-----------------------------------------------------------------*/
4532 operand *left = IC_LEFT (ic);
4533 operand *right = IC_RIGHT (ic);
4534 operand *result = IC_RESULT (ic);
4536 D (emitcode (";", "genDiv "););
4538 /* assign the amsops */
4541 /* special cases first */
4543 if (AOP_TYPE (left) == AOP_CRY &&
4544 AOP_TYPE (right) == AOP_CRY)
4546 genDivbits (left, right, result, ic);
4550 /* if both are of size == 1 */
4551 if (AOP_SIZE (left) == 1 &&
4552 AOP_SIZE (right) == 1)
4554 genDivOneByte (left, right, result, ic);
4558 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4559 /* use the ds390 ARITHMETIC accel UNIT */
4560 genDivTwoByte (left, right, result, ic);
4563 /* should have been converted to function call */
4566 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4567 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4568 freeAsmop (result, NULL, ic, TRUE);
4571 /*-----------------------------------------------------------------*/
4572 /* genModbits :- modulus of bits */
4573 /*-----------------------------------------------------------------*/
4575 genModbits (operand * left,
4583 /* the result must be bit */
4584 LOAD_AB_FOR_DIV (left, right, l);
4585 emitcode ("div", "ab");
4586 emitcode ("mov", "a,b");
4587 emitcode ("rrc", "a");
4588 aopOp(result, ic, TRUE, FALSE);
4589 aopPut (AOP (result), "c", 0);
4592 /*-----------------------------------------------------------------*/
4593 /* genModOneByte : 8 bit modulus */
4594 /*-----------------------------------------------------------------*/
4596 genModOneByte (operand * left,
4601 sym_link *opetype = operandType (result);
4605 /* signed or unsigned */
4606 if (SPEC_USIGN (opetype))
4608 /* unsigned is easy */
4609 LOAD_AB_FOR_DIV (left, right, l);
4610 emitcode ("div", "ab");
4611 aopOp(result, ic, TRUE, FALSE);
4612 aopPut (AOP (result), "b", 0);
4616 /* signed is a little bit more difficult */
4618 /* save the signs of the operands */
4619 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4622 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4623 emitcode ("push", "acc"); /* save it on the stack */
4625 /* now sign adjust for both left & right */
4626 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4629 lbl = newiTempLabel (NULL);
4630 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4631 emitcode ("cpl", "a");
4632 emitcode ("inc", "a");
4633 emitcode ("", "%05d$:", (lbl->key + 100));
4634 emitcode ("mov", "b,a");
4636 /* sign adjust left side */
4637 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4640 lbl = newiTempLabel (NULL);
4641 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4642 emitcode ("cpl", "a");
4643 emitcode ("inc", "a");
4644 emitcode ("", "%05d$:", (lbl->key + 100));
4646 /* now the multiplication */
4647 emitcode ("nop", "; workaround for DS80C390 div bug.");
4648 emitcode ("div", "ab");
4649 /* we are interested in the lower order
4651 lbl = newiTempLabel (NULL);
4652 emitcode ("pop", "acc");
4653 /* if there was an over flow we don't
4654 adjust the sign of the result */
4655 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4656 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4658 emitcode ("clr", "a");
4659 emitcode ("subb", "a,b");
4660 emitcode ("mov", "b,a");
4661 emitcode ("", "%05d$:", (lbl->key + 100));
4663 /* now we are done */
4664 aopOp(result, ic, TRUE, FALSE);
4665 aopPut (AOP (result), "b", 0);
4669 /*-----------------------------------------------------------------*/
4670 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
4671 /*-----------------------------------------------------------------*/
4672 static void genModTwoByte (operand *left, operand *right,
4673 operand *result, iCode *ic)
4675 sym_link *retype = getSpec(operandType(right));
4676 sym_link *letype = getSpec(operandType(left));
4677 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4680 /* load up MA with left */
4681 /* save EA bit in F1 */
4682 lbl = newiTempLabel(NULL);
4683 emitcode ("setb","F1");
4684 emitcode ("jbc","EA,%05d$",lbl->key+100);
4685 emitcode ("clr","F1");
4686 emitcode("","%05d$:",lbl->key+100);
4689 lbl = newiTempLabel(NULL);
4690 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4691 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4692 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4693 emitcode ("xch", "a,b");
4694 emitcode ("cpl","a");
4695 emitcode ("add", "a,#1");
4696 emitcode ("xch", "a,b");
4697 emitcode ("cpl", "a"); // msb
4698 emitcode ("addc","a,#0");
4699 emitcode ("","%05d$:",lbl->key+100);
4700 emitcode ("mov","ma,b");
4701 emitcode ("mov","ma,a");
4703 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4704 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4707 /* load up MB with right */
4709 if (AOP_TYPE(right) == AOP_LIT) {
4710 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4714 emitcode ("mov","mb,#0x%02x",val & 0xff);
4715 emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4717 lbl = newiTempLabel(NULL);
4718 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4719 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4720 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4721 emitcode ("xch", "a,b");
4722 emitcode ("cpl","a");
4723 emitcode ("add", "a,#1");
4724 emitcode ("xch", "a,b");
4725 emitcode ("cpl", "a"); // msb
4726 emitcode ("addc", "a,#0");
4727 emitcode ("","%05d$:",lbl->key+100);
4728 emitcode ("mov","mb,b");
4729 emitcode ("mov","mb,a");
4732 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4733 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4736 /* wait for multiplication to finish */
4737 lbl = newiTempLabel(NULL);
4738 emitcode("","%05d$:", lbl->key+100);
4739 emitcode("mov","a,mcnt1");
4740 emitcode("anl","a,#0x80");
4741 emitcode("jnz","%05d$",lbl->key+100);
4743 freeAsmop (left, NULL, ic, TRUE);
4744 freeAsmop (right, NULL, ic,TRUE);
4745 aopOp(result, ic, TRUE, FALSE);
4747 aopPut(AOP(result),"mb",1);
4748 aopPut(AOP(result),"mb",0);
4749 freeAsmop (result, NULL, ic, TRUE);
4751 /* restore EA bit in F1 */
4752 lbl = newiTempLabel(NULL);
4753 emitcode ("jnb","F1,%05d$",lbl->key+100);
4754 emitcode ("setb","EA");
4755 emitcode("","%05d$:",lbl->key+100);
4759 /*-----------------------------------------------------------------*/
4760 /* genMod - generates code for division */
4761 /*-----------------------------------------------------------------*/
4765 operand *left = IC_LEFT (ic);
4766 operand *right = IC_RIGHT (ic);
4767 operand *result = IC_RESULT (ic);
4769 D (emitcode (";", "genMod "); );
4771 /* assign the amsops */
4774 /* special cases first */
4776 if (AOP_TYPE (left) == AOP_CRY &&
4777 AOP_TYPE (right) == AOP_CRY)
4779 genModbits (left, right, result, ic);
4783 /* if both are of size == 1 */
4784 if (AOP_SIZE (left) == 1 &&
4785 AOP_SIZE (right) == 1)
4787 genModOneByte (left, right, result, ic);
4791 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4792 /* use the ds390 ARITHMETIC accel UNIT */
4793 genModTwoByte (left, right, result, ic);
4797 /* should have been converted to function call */
4801 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4802 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4803 freeAsmop (result, NULL, ic, TRUE);
4806 /*-----------------------------------------------------------------*/
4807 /* genIfxJump :- will create a jump depending on the ifx */
4808 /*-----------------------------------------------------------------*/
4810 genIfxJump (iCode * ic, char *jval)
4813 symbol *tlbl = newiTempLabel (NULL);
4816 D (emitcode (";", "genIfxJump ");
4819 /* if true label then we jump if condition
4823 jlbl = IC_TRUE (ic);
4824 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4825 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4829 /* false label is present */
4830 jlbl = IC_FALSE (ic);
4831 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4832 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4834 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4835 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4837 emitcode (inst, "%05d$", tlbl->key + 100);
4838 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4839 emitcode ("", "%05d$:", tlbl->key + 100);
4841 /* mark the icode as generated */
4845 /*-----------------------------------------------------------------*/
4846 /* genCmp :- greater or less than comparison */
4847 /*-----------------------------------------------------------------*/
4849 genCmp (operand * left, operand * right,
4850 iCode * ic, iCode * ifx, int sign)
4852 int size, offset = 0;
4853 unsigned long lit = 0L;
4856 D (emitcode (";", "genCmp");
4859 result = IC_RESULT (ic);
4861 /* if left & right are bit variables */
4862 if (AOP_TYPE (left) == AOP_CRY &&
4863 AOP_TYPE (right) == AOP_CRY)
4865 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4866 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4870 /* subtract right from left if at the
4871 end the carry flag is set then we know that
4872 left is greater than right */
4873 size = max (AOP_SIZE (left), AOP_SIZE (right));
4875 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4876 if ((size == 1) && !sign &&
4877 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4879 symbol *lbl = newiTempLabel (NULL);
4880 emitcode ("cjne", "%s,%s,%05d$",
4881 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4882 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4884 emitcode ("", "%05d$:", lbl->key + 100);
4888 if (AOP_TYPE (right) == AOP_LIT)
4890 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4891 /* optimize if(x < 0) or if(x >= 0) */
4900 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4902 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4903 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4905 aopOp (result, ic, FALSE, FALSE);
4907 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4909 freeAsmop (result, NULL, ic, TRUE);
4910 genIfxJump (ifx, "acc.7");
4915 emitcode ("rlc", "a");
4917 goto release_freedLR;
4925 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4926 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4927 emitcode (";", "genCmp #2");
4928 if (sign && (size == 0))
4930 emitcode (";", "genCmp #3");
4931 emitcode ("xrl", "a,#0x80");
4932 if (AOP_TYPE (right) == AOP_LIT)
4934 unsigned long lit = (unsigned long)
4935 floatFromVal (AOP (right)->aopu.aop_lit);
4936 emitcode (";", "genCmp #3.1");
4937 emitcode ("subb", "a,#0x%02x",
4938 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4942 emitcode (";", "genCmp #3.2");
4943 if (AOP_NEEDSACC (right))
4945 emitcode ("push", "acc");
4947 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4948 FALSE, FALSE, FALSE));
4949 emitcode ("xrl", "b,#0x80");
4950 if (AOP_NEEDSACC (right))
4952 emitcode ("pop", "acc");
4954 emitcode ("subb", "a,b");
4961 emitcode (";", "genCmp #4");
4962 if (AOP_NEEDSACC (right))
4965 emitcode (";", "genCmp #4.1");
4966 emitcode ("xch", "a, b");
4967 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4968 emitcode ("xch", "a, b");
4973 emitcode (";", "genCmp #4.2");
4974 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4977 emitcode ("subb", "a,%s", s);
4984 /* Don't need the left & right operands any more; do need the result. */
4985 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4986 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4988 aopOp (result, ic, FALSE, FALSE);
4992 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4998 /* if the result is used in the next
4999 ifx conditional branch then generate
5000 code a little differently */
5003 genIfxJump (ifx, "c");
5009 /* leave the result in acc */
5011 freeAsmop (result, NULL, ic, TRUE);
5014 /*-----------------------------------------------------------------*/
5015 /* genCmpGt :- greater than comparison */
5016 /*-----------------------------------------------------------------*/
5018 genCmpGt (iCode * ic, iCode * ifx)
5020 operand *left, *right;
5021 sym_link *letype, *retype;
5024 D (emitcode (";", "genCmpGt ");
5027 left = IC_LEFT (ic);
5028 right = IC_RIGHT (ic);
5030 letype = getSpec (operandType (left));
5031 retype = getSpec (operandType (right));
5032 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5034 /* assign the left & right amsops */
5037 genCmp (right, left, ic, ifx, sign);
5040 /*-----------------------------------------------------------------*/
5041 /* genCmpLt - less than comparisons */
5042 /*-----------------------------------------------------------------*/
5044 genCmpLt (iCode * ic, iCode * ifx)
5046 operand *left, *right;
5047 sym_link *letype, *retype;
5050 D (emitcode (";", "genCmpLt "););
5052 left = IC_LEFT (ic);
5053 right = IC_RIGHT (ic);
5055 letype = getSpec (operandType (left));
5056 retype = getSpec (operandType (right));
5057 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5059 /* assign the left & right amsops */
5062 genCmp (left, right, ic, ifx, sign);
5065 /*-----------------------------------------------------------------*/
5066 /* gencjneshort - compare and jump if not equal */
5067 /*-----------------------------------------------------------------*/
5069 gencjneshort (operand * left, operand * right, symbol * lbl)
5071 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5073 unsigned long lit = 0L;
5075 D (emitcode (";", "gencjneshort");
5078 /* if the left side is a literal or
5079 if the right is in a pointer register and left
5081 if ((AOP_TYPE (left) == AOP_LIT) ||
5082 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5089 if (AOP_TYPE (right) == AOP_LIT)
5090 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5092 if (opIsGptr (left) || opIsGptr (right))
5094 /* We are comparing a generic pointer to something.
5095 * Exclude the generic type byte from the comparison.
5098 D (emitcode (";", "cjneshort: generic ptr special case.");
5103 /* if the right side is a literal then anything goes */
5104 if (AOP_TYPE (right) == AOP_LIT &&
5105 AOP_TYPE (left) != AOP_DIR)
5109 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5111 emitcode ("cjne", "a,%s,%05d$",
5112 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5118 /* if the right side is in a register or in direct space or
5119 if the left is a pointer register & right is not */
5120 else if (AOP_TYPE (right) == AOP_REG ||
5121 AOP_TYPE (right) == AOP_DIR ||
5122 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5123 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5127 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5128 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5129 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5130 emitcode ("jnz", "%05d$", lbl->key + 100);
5132 emitcode ("cjne", "a,%s,%05d$",
5133 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5140 /* right is a pointer reg need both a & b */
5143 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5144 if (strcmp (l, "b"))
5145 emitcode ("mov", "b,%s", l);
5146 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5147 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5153 /*-----------------------------------------------------------------*/
5154 /* gencjne - compare and jump if not equal */
5155 /*-----------------------------------------------------------------*/
5157 gencjne (operand * left, operand * right, symbol * lbl)
5159 symbol *tlbl = newiTempLabel (NULL);
5161 D (emitcode (";", "gencjne");
5164 gencjneshort (left, right, lbl);
5166 emitcode ("mov", "a,%s", one);
5167 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5168 emitcode ("", "%05d$:", lbl->key + 100);
5169 emitcode ("clr", "a");
5170 emitcode ("", "%05d$:", tlbl->key + 100);
5173 /*-----------------------------------------------------------------*/
5174 /* genCmpEq - generates code for equal to */
5175 /*-----------------------------------------------------------------*/
5177 genCmpEq (iCode * ic, iCode * ifx)
5179 operand *left, *right, *result;
5181 D (emitcode (";", "genCmpEq ");
5185 AOP_SET_LOCALS (ic);
5187 /* if literal, literal on the right or
5188 if the right is in a pointer register and left
5190 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5191 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5193 operand *t = IC_RIGHT (ic);
5194 IC_RIGHT (ic) = IC_LEFT (ic);
5198 if (ifx && /* !AOP_SIZE(result) */
5199 OP_SYMBOL (result) &&
5200 OP_SYMBOL (result)->regType == REG_CND)
5203 /* if they are both bit variables */
5204 if (AOP_TYPE (left) == AOP_CRY &&
5205 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5207 if (AOP_TYPE (right) == AOP_LIT)
5209 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5212 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5213 emitcode ("cpl", "c");
5217 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5221 emitcode ("clr", "c");
5223 /* AOP_TYPE(right) == AOP_CRY */
5227 symbol *lbl = newiTempLabel (NULL);
5228 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5229 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5230 emitcode ("cpl", "c");
5231 emitcode ("", "%05d$:", (lbl->key + 100));
5233 /* if true label then we jump if condition
5235 tlbl = newiTempLabel (NULL);
5238 emitcode ("jnc", "%05d$", tlbl->key + 100);
5239 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5243 emitcode ("jc", "%05d$", tlbl->key + 100);
5244 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5246 emitcode ("", "%05d$:", tlbl->key + 100);
5250 tlbl = newiTempLabel (NULL);
5251 gencjneshort (left, right, tlbl);
5254 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5255 emitcode ("", "%05d$:", tlbl->key + 100);
5259 symbol *lbl = newiTempLabel (NULL);
5260 emitcode ("sjmp", "%05d$", lbl->key + 100);
5261 emitcode ("", "%05d$:", tlbl->key + 100);
5262 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5263 emitcode ("", "%05d$:", lbl->key + 100);
5266 /* mark the icode as generated */
5269 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5270 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5274 /* if they are both bit variables */
5275 if (AOP_TYPE (left) == AOP_CRY &&
5276 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5278 if (AOP_TYPE (right) == AOP_LIT)
5280 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5283 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5284 emitcode ("cpl", "c");
5288 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5292 emitcode ("clr", "c");
5294 /* AOP_TYPE(right) == AOP_CRY */
5298 symbol *lbl = newiTempLabel (NULL);
5299 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5300 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5301 emitcode ("cpl", "c");
5302 emitcode ("", "%05d$:", (lbl->key + 100));
5305 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5306 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5308 aopOp (result, ic, TRUE, FALSE);
5311 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5318 genIfxJump (ifx, "c");
5321 /* if the result is used in an arithmetic operation
5322 then put the result in place */
5327 gencjne (left, right, newiTempLabel (NULL));
5329 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5330 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5332 aopOp (result, ic, TRUE, FALSE);
5334 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5336 aopPut (AOP (result), "a", 0);
5341 genIfxJump (ifx, "a");
5344 /* if the result is used in an arithmetic operation
5345 then put the result in place */
5346 if (AOP_TYPE (result) != AOP_CRY)
5348 /* leave the result in acc */
5352 freeAsmop (result, NULL, ic, TRUE);
5355 /*-----------------------------------------------------------------*/
5356 /* ifxForOp - returns the icode containing the ifx for operand */
5357 /*-----------------------------------------------------------------*/
5359 ifxForOp (operand * op, iCode * ic)
5361 /* if true symbol then needs to be assigned */
5362 if (IS_TRUE_SYMOP (op))
5365 /* if this has register type condition and
5366 the next instruction is ifx with the same operand
5367 and live to of the operand is upto the ifx only then */
5369 ic->next->op == IFX &&
5370 IC_COND (ic->next)->key == op->key &&
5371 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5376 /*-----------------------------------------------------------------*/
5377 /* hasInc - operand is incremented before any other use */
5378 /*-----------------------------------------------------------------*/
5380 hasInc (operand *op, iCode *ic)
5382 sym_link *type = operandType(op);
5383 sym_link *retype = getSpec (type);
5384 iCode *lic = ic->next;
5387 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5388 if (!IS_SYMOP(op)) return NULL;
5390 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5391 isize = getSize(type->next);
5393 /* if operand of the form op = op + <sizeof *op> */
5394 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5395 isOperandEqual(IC_RESULT(lic),op) &&
5396 isOperandLiteral(IC_RIGHT(lic)) &&
5397 operandLitValue(IC_RIGHT(lic)) == isize) {
5400 /* if the operand used or deffed */
5401 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5409 /*-----------------------------------------------------------------*/
5410 /* genAndOp - for && operation */
5411 /*-----------------------------------------------------------------*/
5413 genAndOp (iCode * ic)
5415 operand *left, *right, *result;
5418 D (emitcode (";", "genAndOp "););
5420 /* note here that && operations that are in an
5421 if statement are taken away by backPatchLabels
5422 only those used in arthmetic operations remain */
5424 AOP_SET_LOCALS (ic);
5426 /* if both are bit variables */
5427 if (AOP_TYPE (left) == AOP_CRY &&
5428 AOP_TYPE (right) == AOP_CRY)
5430 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5431 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5432 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5433 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5435 aopOp (result,ic,FALSE, FALSE);
5440 tlbl = newiTempLabel (NULL);
5442 emitcode ("jz", "%05d$", tlbl->key + 100);
5444 emitcode ("", "%05d$:", tlbl->key + 100);
5445 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5446 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5448 aopOp (result,ic,FALSE, FALSE);
5451 freeAsmop (result, NULL, ic, TRUE);
5455 /*-----------------------------------------------------------------*/
5456 /* genOrOp - for || operation */
5457 /*-----------------------------------------------------------------*/
5459 genOrOp (iCode * ic)
5461 operand *left, *right, *result;
5464 D (emitcode (";", "genOrOp "););
5466 /* note here that || operations that are in an
5467 if statement are taken away by backPatchLabels
5468 only those used in arthmetic operations remain */
5470 AOP_SET_LOCALS (ic);
5472 /* if both are bit variables */
5473 if (AOP_TYPE (left) == AOP_CRY &&
5474 AOP_TYPE (right) == AOP_CRY)
5476 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5477 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5478 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5479 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5481 aopOp (result,ic,FALSE, FALSE);
5487 tlbl = newiTempLabel (NULL);
5489 emitcode ("jnz", "%05d$", tlbl->key + 100);
5491 emitcode ("", "%05d$:", tlbl->key + 100);
5492 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5493 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5495 aopOp (result,ic,FALSE, FALSE);
5500 freeAsmop (result, NULL, ic, TRUE);
5503 /*-----------------------------------------------------------------*/
5504 /* isLiteralBit - test if lit == 2^n */
5505 /*-----------------------------------------------------------------*/
5507 isLiteralBit (unsigned long lit)
5509 unsigned long pw[32] =
5510 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5511 0x100L, 0x200L, 0x400L, 0x800L,
5512 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5513 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5514 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5515 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5516 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5519 for (idx = 0; idx < 32; idx++)
5525 /*-----------------------------------------------------------------*/
5526 /* continueIfTrue - */
5527 /*-----------------------------------------------------------------*/
5529 continueIfTrue (iCode * ic)
5532 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5536 /*-----------------------------------------------------------------*/
5538 /*-----------------------------------------------------------------*/
5540 jumpIfTrue (iCode * ic)
5543 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5547 /*-----------------------------------------------------------------*/
5548 /* jmpTrueOrFalse - */
5549 /*-----------------------------------------------------------------*/
5551 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5553 // ugly but optimized by peephole
5556 symbol *nlbl = newiTempLabel (NULL);
5557 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5558 emitcode ("", "%05d$:", tlbl->key + 100);
5559 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5560 emitcode ("", "%05d$:", nlbl->key + 100);
5564 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5565 emitcode ("", "%05d$:", tlbl->key + 100);
5570 // Generate code to perform a bit-wise logic operation
5571 // on two operands in far space (assumed to already have been
5572 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5573 // in far space. This requires pushing the result on the stack
5574 // then popping it into the result.
5576 genFarFarLogicOp(iCode *ic, char *logicOp)
5578 int size, resultSize, compSize;
5582 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5583 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5584 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5586 _startLazyDPSEvaluation();
5587 for (size = compSize; (size--); offset++)
5589 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5590 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5591 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5593 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5594 emitcode ("push", "acc");
5596 _endLazyDPSEvaluation();
5598 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5599 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5600 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5602 resultSize = AOP_SIZE(IC_RESULT(ic));
5604 ADJUST_PUSHED_RESULT(compSize, resultSize);
5606 _startLazyDPSEvaluation();
5609 emitcode ("pop", "acc");
5610 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5612 _endLazyDPSEvaluation();
5613 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5617 /*-----------------------------------------------------------------*/
5618 /* genAnd - code for and */
5619 /*-----------------------------------------------------------------*/
5621 genAnd (iCode * ic, iCode * ifx)
5623 operand *left, *right, *result;
5624 int size, offset = 0;
5625 unsigned long lit = 0L;
5630 D (emitcode (";", "genAnd "););
5632 AOP_OP_3_NOFATAL (ic, pushResult);
5633 AOP_SET_LOCALS (ic);
5637 genFarFarLogicOp(ic, "anl");
5642 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5644 AOP_TYPE (left), AOP_TYPE (right));
5645 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5647 AOP_SIZE (left), AOP_SIZE (right));
5650 /* if left is a literal & right is not then exchange them */
5651 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5652 #ifdef LOGIC_OPS_BROKEN
5653 || AOP_NEEDSACC (left)
5657 operand *tmp = right;
5662 /* if result = right then exchange them */
5663 if (sameRegs (AOP (result), AOP (right)))
5665 operand *tmp = right;
5670 /* if right is bit then exchange them */
5671 if (AOP_TYPE (right) == AOP_CRY &&
5672 AOP_TYPE (left) != AOP_CRY)
5674 operand *tmp = right;
5678 if (AOP_TYPE (right) == AOP_LIT)
5679 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5681 size = AOP_SIZE (result);
5684 // result = bit & yy;
5685 if (AOP_TYPE (left) == AOP_CRY)
5687 // c = bit & literal;
5688 if (AOP_TYPE (right) == AOP_LIT)
5692 if (size && sameRegs (AOP (result), AOP (left)))
5695 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5700 if (size && (AOP_TYPE (result) == AOP_CRY))
5702 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5705 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5710 emitcode ("clr", "c");
5715 if (AOP_TYPE (right) == AOP_CRY)
5718 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5719 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5724 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5726 emitcode ("rrc", "a");
5727 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5735 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5736 genIfxJump (ifx, "c");
5740 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5741 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5742 if ((AOP_TYPE (right) == AOP_LIT) &&
5743 (AOP_TYPE (result) == AOP_CRY) &&
5744 (AOP_TYPE (left) != AOP_CRY))
5746 int posbit = isLiteralBit (lit);
5751 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5754 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5760 sprintf (buffer, "acc.%d", posbit & 0x07);
5761 genIfxJump (ifx, buffer);
5768 symbol *tlbl = newiTempLabel (NULL);
5769 int sizel = AOP_SIZE (left);
5771 emitcode ("setb", "c");
5774 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5776 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5778 if ((posbit = isLiteralBit (bytelit)) != 0)
5779 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5782 if (bytelit != 0x0FFL)
5783 emitcode ("anl", "a,%s",
5784 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5785 emitcode ("jnz", "%05d$", tlbl->key + 100);
5790 // bit = left & literal
5793 emitcode ("clr", "c");
5794 emitcode ("", "%05d$:", tlbl->key + 100);
5796 // if(left & literal)
5800 jmpTrueOrFalse (ifx, tlbl);
5808 /* if left is same as result */
5809 if (sameRegs (AOP (result), AOP (left)))
5811 for (; size--; offset++)
5813 if (AOP_TYPE (right) == AOP_LIT)
5815 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5817 else if (bytelit == 0)
5818 aopPut (AOP (result), zero, offset);
5819 else if (IS_AOP_PREG (result))
5821 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5822 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5823 aopPut (AOP (result), "a", offset);
5826 emitcode ("anl", "%s,%s",
5827 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5828 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5832 if (AOP_TYPE (left) == AOP_ACC)
5833 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5836 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5837 if (IS_AOP_PREG (result))
5839 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5840 aopPut (AOP (result), "a", offset);
5844 emitcode ("anl", "%s,a",
5845 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5852 // left & result in different registers
5853 if (AOP_TYPE (result) == AOP_CRY)
5856 // if(size), result in bit
5857 // if(!size && ifx), conditional oper: if(left & right)
5858 symbol *tlbl = newiTempLabel (NULL);
5859 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5861 emitcode ("setb", "c");
5864 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5865 emitcode ("anl", "a,%s",
5866 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5868 if (AOP_TYPE(left)==AOP_ACC) {
5869 emitcode("mov", "b,a");
5870 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5871 emitcode("anl", "a,b");
5873 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5874 emitcode ("anl", "a,%s",
5875 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5878 emitcode ("jnz", "%05d$", tlbl->key + 100);
5884 emitcode ("", "%05d$:", tlbl->key + 100);
5888 jmpTrueOrFalse (ifx, tlbl);
5892 for (; (size--); offset++)
5895 // result = left & right
5896 if (AOP_TYPE (right) == AOP_LIT)
5898 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5900 aopPut (AOP (result),
5901 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5905 else if (bytelit == 0)
5907 aopPut (AOP (result), zero, offset);
5910 D (emitcode (";", "better literal AND."););
5911 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5912 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5913 FALSE, FALSE, FALSE));
5918 // faster than result <- left, anl result,right
5919 // and better if result is SFR
5920 if (AOP_TYPE (left) == AOP_ACC)
5922 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5923 FALSE, FALSE, FALSE));
5927 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
5928 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
5930 emitcode("mov", "b,a");
5934 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5935 emitcode ("anl", "a,%s", rOp);
5938 aopPut (AOP (result), "a", offset);
5944 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5945 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5946 freeAsmop (result, NULL, ic, TRUE);
5950 /*-----------------------------------------------------------------*/
5951 /* genOr - code for or */
5952 /*-----------------------------------------------------------------*/
5954 genOr (iCode * ic, iCode * ifx)
5956 operand *left, *right, *result;
5957 int size, offset = 0;
5958 unsigned long lit = 0L;
5961 D (emitcode (";", "genOr "););
5963 AOP_OP_3_NOFATAL (ic, pushResult);
5964 AOP_SET_LOCALS (ic);
5968 genFarFarLogicOp(ic, "orl");
5974 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5976 AOP_TYPE (left), AOP_TYPE (right));
5977 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5979 AOP_SIZE (left), AOP_SIZE (right));
5982 /* if left is a literal & right is not then exchange them */
5983 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5984 #ifdef LOGIC_OPS_BROKEN
5985 || AOP_NEEDSACC (left) // I think this is a net loss now.
5989 operand *tmp = right;
5994 /* if result = right then exchange them */
5995 if (sameRegs (AOP (result), AOP (right)))
5997 operand *tmp = right;
6002 /* if right is bit then exchange them */
6003 if (AOP_TYPE (right) == AOP_CRY &&
6004 AOP_TYPE (left) != AOP_CRY)
6006 operand *tmp = right;
6010 if (AOP_TYPE (right) == AOP_LIT)
6011 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6013 size = AOP_SIZE (result);
6017 if (AOP_TYPE (left) == AOP_CRY)
6019 if (AOP_TYPE (right) == AOP_LIT)
6021 // c = bit & literal;
6024 // lit != 0 => result = 1
6025 if (AOP_TYPE (result) == AOP_CRY)
6028 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6030 continueIfTrue (ifx);
6033 emitcode ("setb", "c");
6037 // lit == 0 => result = left
6038 if (size && sameRegs (AOP (result), AOP (left)))
6040 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6045 if (AOP_TYPE (right) == AOP_CRY)
6048 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6049 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6054 symbol *tlbl = newiTempLabel (NULL);
6055 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6056 emitcode ("setb", "c");
6057 emitcode ("jb", "%s,%05d$",
6058 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6060 emitcode ("jnz", "%05d$", tlbl->key + 100);
6061 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6063 jmpTrueOrFalse (ifx, tlbl);
6069 emitcode ("", "%05d$:", tlbl->key + 100);
6078 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6079 genIfxJump (ifx, "c");
6083 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6084 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6085 if ((AOP_TYPE (right) == AOP_LIT) &&
6086 (AOP_TYPE (result) == AOP_CRY) &&
6087 (AOP_TYPE (left) != AOP_CRY))
6093 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6095 continueIfTrue (ifx);
6100 // lit = 0, result = boolean(left)
6102 emitcode ("setb", "c");
6106 symbol *tlbl = newiTempLabel (NULL);
6107 emitcode ("jnz", "%05d$", tlbl->key + 100);
6109 emitcode ("", "%05d$:", tlbl->key + 100);
6113 genIfxJump (ifx, "a");
6121 /* if left is same as result */
6122 if (sameRegs (AOP (result), AOP (left)))
6124 for (; size--; offset++)
6126 if (AOP_TYPE (right) == AOP_LIT)
6128 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6134 if (IS_AOP_PREG (left))
6136 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6137 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6138 aopPut (AOP (result), "a", offset);
6142 emitcode ("orl", "%s,%s",
6143 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6144 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6150 if (AOP_TYPE (left) == AOP_ACC)
6152 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6156 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6157 if (IS_AOP_PREG (left))
6159 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6160 aopPut (AOP (result), "a", offset);
6164 emitcode ("orl", "%s,a",
6165 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6173 // left & result in different registers
6174 if (AOP_TYPE (result) == AOP_CRY)
6177 // if(size), result in bit
6178 // if(!size && ifx), conditional oper: if(left | right)
6179 symbol *tlbl = newiTempLabel (NULL);
6180 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6182 emitcode ("setb", "c");
6185 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6186 emitcode ("orl", "a,%s",
6187 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6189 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6190 emitcode ("orl", "a,%s",
6191 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6193 emitcode ("jnz", "%05d$", tlbl->key + 100);
6199 emitcode ("", "%05d$:", tlbl->key + 100);
6203 jmpTrueOrFalse (ifx, tlbl);
6207 _startLazyDPSEvaluation();
6208 for (; (size--); offset++)
6211 // result = left & right
6212 if (AOP_TYPE (right) == AOP_LIT)
6214 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6216 aopPut (AOP (result),
6217 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6221 D (emitcode (";", "better literal OR."););
6222 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6223 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6224 FALSE, FALSE, FALSE));
6229 // faster than result <- left, anl result,right
6230 // and better if result is SFR
6231 if (AOP_TYPE (left) == AOP_ACC)
6233 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6234 FALSE, FALSE, FALSE));
6238 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6240 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6242 emitcode("mov", "b,a");
6246 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6247 emitcode ("orl", "a,%s", rOp);
6250 aopPut (AOP (result), "a", offset);
6252 _endLazyDPSEvaluation();
6257 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6258 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6259 freeAsmop (result, NULL, ic, TRUE);
6262 /*-----------------------------------------------------------------*/
6263 /* genXor - code for xclusive or */
6264 /*-----------------------------------------------------------------*/
6266 genXor (iCode * ic, iCode * ifx)
6268 operand *left, *right, *result;
6269 int size, offset = 0;
6270 unsigned long lit = 0L;
6273 D (emitcode (";", "genXor "););
6275 AOP_OP_3_NOFATAL (ic, pushResult);
6276 AOP_SET_LOCALS (ic);
6280 genFarFarLogicOp(ic, "xrl");
6285 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6287 AOP_TYPE (left), AOP_TYPE (right));
6288 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6290 AOP_SIZE (left), AOP_SIZE (right));
6293 /* if left is a literal & right is not ||
6294 if left needs acc & right does not */
6295 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6296 #ifdef LOGIC_OPS_BROKEN
6297 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6301 operand *tmp = right;
6306 /* if result = right then exchange them */
6307 if (sameRegs (AOP (result), AOP (right)))
6309 operand *tmp = right;
6314 /* if right is bit then exchange them */
6315 if (AOP_TYPE (right) == AOP_CRY &&
6316 AOP_TYPE (left) != AOP_CRY)
6318 operand *tmp = right;
6322 if (AOP_TYPE (right) == AOP_LIT)
6323 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6325 size = AOP_SIZE (result);
6329 if (AOP_TYPE (left) == AOP_CRY)
6331 if (AOP_TYPE (right) == AOP_LIT)
6333 // c = bit & literal;
6336 // lit>>1 != 0 => result = 1
6337 if (AOP_TYPE (result) == AOP_CRY)
6340 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6342 continueIfTrue (ifx);
6345 emitcode ("setb", "c");
6352 // lit == 0, result = left
6353 if (size && sameRegs (AOP (result), AOP (left)))
6355 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6359 // lit == 1, result = not(left)
6360 if (size && sameRegs (AOP (result), AOP (left)))
6362 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6367 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6368 emitcode ("cpl", "c");
6377 symbol *tlbl = newiTempLabel (NULL);
6378 if (AOP_TYPE (right) == AOP_CRY)
6381 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6385 int sizer = AOP_SIZE (right);
6387 // if val>>1 != 0, result = 1
6388 emitcode ("setb", "c");
6391 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6393 // test the msb of the lsb
6394 emitcode ("anl", "a,#0xfe");
6395 emitcode ("jnz", "%05d$", tlbl->key + 100);
6399 emitcode ("rrc", "a");
6401 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6402 emitcode ("cpl", "c");
6403 emitcode ("", "%05d$:", (tlbl->key + 100));
6410 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6411 genIfxJump (ifx, "c");
6415 if (sameRegs (AOP (result), AOP (left)))
6417 /* if left is same as result */
6418 for (; size--; offset++)
6420 if (AOP_TYPE (right) == AOP_LIT)
6422 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6424 else if (IS_AOP_PREG (left))
6426 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6427 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6428 aopPut (AOP (result), "a", offset);
6431 emitcode ("xrl", "%s,%s",
6432 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6433 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6437 if (AOP_TYPE (left) == AOP_ACC)
6438 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6441 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6442 if (IS_AOP_PREG (left))
6444 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6445 aopPut (AOP (result), "a", offset);
6448 emitcode ("xrl", "%s,a",
6449 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6456 // left & result in different registers
6457 if (AOP_TYPE (result) == AOP_CRY)
6460 // if(size), result in bit
6461 // if(!size && ifx), conditional oper: if(left ^ right)
6462 symbol *tlbl = newiTempLabel (NULL);
6463 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6465 emitcode ("setb", "c");
6468 if ((AOP_TYPE (right) == AOP_LIT) &&
6469 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6471 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6475 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6476 emitcode ("xrl", "a,%s",
6477 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6479 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6480 emitcode ("xrl", "a,%s",
6481 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6484 emitcode ("jnz", "%05d$", tlbl->key + 100);
6490 emitcode ("", "%05d$:", tlbl->key + 100);
6494 jmpTrueOrFalse (ifx, tlbl);
6497 for (; (size--); offset++)
6500 // result = left & right
6501 if (AOP_TYPE (right) == AOP_LIT)
6503 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6505 aopPut (AOP (result),
6506 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6510 D (emitcode (";", "better literal XOR.");
6512 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6513 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6514 FALSE, FALSE, FALSE));
6518 // faster than result <- left, anl result,right
6519 // and better if result is SFR
6520 if (AOP_TYPE (left) == AOP_ACC)
6522 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6523 FALSE, FALSE, FALSE));
6527 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6528 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6530 emitcode("mov", "b,a");
6534 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6535 emitcode ("xrl", "a,%s", rOp);
6538 aopPut (AOP (result), "a", offset);
6543 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6544 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6545 freeAsmop (result, NULL, ic, TRUE);
6548 /*-----------------------------------------------------------------*/
6549 /* genInline - write the inline code out */
6550 /*-----------------------------------------------------------------*/
6552 genInline (iCode * ic)
6554 char *buffer, *bp, *bp1;
6556 D (emitcode (";", "genInline ");
6559 _G.inLine += (!options.asmpeep);
6561 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6562 strcpy (buffer, IC_INLINE (ic));
6564 /* emit each line as a code */
6589 /* emitcode("",buffer); */
6590 _G.inLine -= (!options.asmpeep);
6593 /*-----------------------------------------------------------------*/
6594 /* genRRC - rotate right with carry */
6595 /*-----------------------------------------------------------------*/
6599 operand *left, *result;
6600 int size, offset = 0;
6603 D (emitcode (";", "genRRC ");
6606 /* rotate right with carry */
6607 left = IC_LEFT (ic);
6608 result = IC_RESULT (ic);
6609 aopOp (left, ic, FALSE, FALSE);
6610 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6612 /* move it to the result */
6613 size = AOP_SIZE (result);
6617 _startLazyDPSEvaluation ();
6620 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6622 emitcode ("rrc", "a");
6623 if (AOP_SIZE (result) > 1)
6624 aopPut (AOP (result), "a", offset--);
6626 _endLazyDPSEvaluation ();
6628 /* now we need to put the carry into the
6629 highest order byte of the result */
6630 if (AOP_SIZE (result) > 1)
6632 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6635 emitcode ("mov", "acc.7,c");
6636 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6637 freeAsmop (left, NULL, ic, TRUE);
6638 freeAsmop (result, NULL, ic, TRUE);
6641 /*-----------------------------------------------------------------*/
6642 /* genRLC - generate code for rotate left with carry */
6643 /*-----------------------------------------------------------------*/
6647 operand *left, *result;
6648 int size, offset = 0;
6651 D (emitcode (";", "genRLC ");
6654 /* rotate right with carry */
6655 left = IC_LEFT (ic);
6656 result = IC_RESULT (ic);
6657 aopOp (left, ic, FALSE, FALSE);
6658 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6660 /* move it to the result */
6661 size = AOP_SIZE (result);
6665 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6667 emitcode ("add", "a,acc");
6668 if (AOP_SIZE (result) > 1)
6670 aopPut (AOP (result), "a", offset++);
6673 _startLazyDPSEvaluation ();
6676 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6678 emitcode ("rlc", "a");
6679 if (AOP_SIZE (result) > 1)
6680 aopPut (AOP (result), "a", offset++);
6682 _endLazyDPSEvaluation ();
6684 /* now we need to put the carry into the
6685 highest order byte of the result */
6686 if (AOP_SIZE (result) > 1)
6688 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6691 emitcode ("mov", "acc.0,c");
6692 aopPut (AOP (result), "a", 0);
6693 freeAsmop (left, NULL, ic, TRUE);
6694 freeAsmop (result, NULL, ic, TRUE);
6697 /*-----------------------------------------------------------------*/
6698 /* genGetHbit - generates code get highest order bit */
6699 /*-----------------------------------------------------------------*/
6701 genGetHbit (iCode * ic)
6703 operand *left, *result;
6704 left = IC_LEFT (ic);
6705 result = IC_RESULT (ic);
6706 aopOp (left, ic, FALSE, FALSE);
6707 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6709 D (emitcode (";", "genGetHbit ");
6712 /* get the highest order byte into a */
6713 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6714 if (AOP_TYPE (result) == AOP_CRY)
6716 emitcode ("rlc", "a");
6721 emitcode ("rl", "a");
6722 emitcode ("anl", "a,#0x01");
6727 freeAsmop (left, NULL, ic, TRUE);
6728 freeAsmop (result, NULL, ic, TRUE);
6731 /*-----------------------------------------------------------------*/
6732 /* AccRol - rotate left accumulator by known count */
6733 /*-----------------------------------------------------------------*/
6735 AccRol (int shCount)
6737 shCount &= 0x0007; // shCount : 0..7
6744 emitcode ("rl", "a");
6747 emitcode ("rl", "a");
6748 emitcode ("rl", "a");
6751 emitcode ("swap", "a");
6752 emitcode ("rr", "a");
6755 emitcode ("swap", "a");
6758 emitcode ("swap", "a");
6759 emitcode ("rl", "a");
6762 emitcode ("rr", "a");
6763 emitcode ("rr", "a");
6766 emitcode ("rr", "a");
6771 /*-----------------------------------------------------------------*/
6772 /* AccLsh - left shift accumulator by known count */
6773 /*-----------------------------------------------------------------*/
6775 AccLsh (int shCount)
6780 emitcode ("add", "a,acc");
6781 else if (shCount == 2)
6783 emitcode ("add", "a,acc");
6784 emitcode ("add", "a,acc");
6788 /* rotate left accumulator */
6790 /* and kill the lower order bits */
6791 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6796 /*-----------------------------------------------------------------*/
6797 /* AccRsh - right shift accumulator by known count */
6798 /*-----------------------------------------------------------------*/
6800 AccRsh (int shCount)
6807 emitcode ("rrc", "a");
6811 /* rotate right accumulator */
6812 AccRol (8 - shCount);
6813 /* and kill the higher order bits */
6814 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6819 #ifdef BETTER_LITERAL_SHIFT
6820 /*-----------------------------------------------------------------*/
6821 /* AccSRsh - signed right shift accumulator by known count */
6822 /*-----------------------------------------------------------------*/
6824 AccSRsh (int shCount)
6831 emitcode ("mov", "c,acc.7");
6832 emitcode ("rrc", "a");
6834 else if (shCount == 2)
6836 emitcode ("mov", "c,acc.7");
6837 emitcode ("rrc", "a");
6838 emitcode ("mov", "c,acc.7");
6839 emitcode ("rrc", "a");
6843 tlbl = newiTempLabel (NULL);
6844 /* rotate right accumulator */
6845 AccRol (8 - shCount);
6846 /* and kill the higher order bits */
6847 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6848 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6849 emitcode ("orl", "a,#0x%02x",
6850 (unsigned char) ~SRMask[shCount]);
6851 emitcode ("", "%05d$:", tlbl->key + 100);
6857 #ifdef BETTER_LITERAL_SHIFT
6858 /*-----------------------------------------------------------------*/
6859 /* shiftR1Left2Result - shift right one byte from left to result */
6860 /*-----------------------------------------------------------------*/
6862 shiftR1Left2Result (operand * left, int offl,
6863 operand * result, int offr,
6864 int shCount, int sign)
6866 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6867 /* shift right accumulator */
6872 aopPut (AOP (result), "a", offr);
6876 #ifdef BETTER_LITERAL_SHIFT
6877 /*-----------------------------------------------------------------*/
6878 /* shiftL1Left2Result - shift left one byte from left to result */
6879 /*-----------------------------------------------------------------*/
6881 shiftL1Left2Result (operand * left, int offl,
6882 operand * result, int offr, int shCount)
6884 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6885 /* shift left accumulator */
6887 aopPut (AOP (result), "a", offr);
6891 #ifdef BETTER_LITERAL_SHIFT
6892 /*-----------------------------------------------------------------*/
6893 /* movLeft2Result - move byte from left to result */
6894 /*-----------------------------------------------------------------*/
6896 movLeft2Result (operand * left, int offl,
6897 operand * result, int offr, int sign)
6900 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6902 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6904 if (*l == '@' && (IS_AOP_PREG (result)))
6906 emitcode ("mov", "a,%s", l);
6907 aopPut (AOP (result), "a", offr);
6913 aopPut (AOP (result), l, offr);
6917 /* MSB sign in acc.7 ! */
6918 if (getDataSize (left) == offl + 1)
6920 emitcode ("mov", "a,%s", l);
6921 aopPut (AOP (result), "a", offr);
6929 #ifdef BETTER_LITERAL_SHIFT
6930 /*-----------------------------------------------------------------*/
6931 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6932 /*-----------------------------------------------------------------*/
6936 emitcode ("rrc", "a");
6937 emitcode ("xch", "a,%s", x);
6938 emitcode ("rrc", "a");
6939 emitcode ("xch", "a,%s", x);
6943 #ifdef BETTER_LITERAL_SHIFT
6945 /*-----------------------------------------------------------------*/
6946 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6947 /*-----------------------------------------------------------------*/
6951 emitcode ("xch", "a,%s", x);
6952 emitcode ("rlc", "a");
6953 emitcode ("xch", "a,%s", x);
6954 emitcode ("rlc", "a");
6958 #ifdef BETTER_LITERAL_SHIFT
6959 /*-----------------------------------------------------------------*/
6960 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6961 /*-----------------------------------------------------------------*/
6965 emitcode ("xch", "a,%s", x);
6966 emitcode ("add", "a,acc");
6967 emitcode ("xch", "a,%s", x);
6968 emitcode ("rlc", "a");
6972 #ifdef BETTER_LITERAL_SHIFT
6973 /*-----------------------------------------------------------------*/
6974 /* AccAXLsh - left shift a:x by known count (0..7) */
6975 /*-----------------------------------------------------------------*/
6977 AccAXLsh (char *x, int shCount)
6992 case 5: // AAAAABBB:CCCCCDDD
6994 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6996 emitcode ("anl", "a,#0x%02x",
6997 SLMask[shCount]); // BBB00000:CCCCCDDD
6999 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7001 AccRol (shCount); // DDDCCCCC:BBB00000
7003 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7005 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7007 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7009 emitcode ("anl", "a,#0x%02x",
7010 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7012 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7014 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7017 case 6: // AAAAAABB:CCCCCCDD
7018 emitcode ("anl", "a,#0x%02x",
7019 SRMask[shCount]); // 000000BB:CCCCCCDD
7020 emitcode ("mov", "c,acc.0"); // c = B
7021 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7023 AccAXRrl1 (x); // BCCCCCCD:D000000B
7024 AccAXRrl1 (x); // BBCCCCCC:DD000000
7026 emitcode("rrc","a");
7027 emitcode("xch","a,%s", x);
7028 emitcode("rrc","a");
7029 emitcode("mov","c,acc.0"); //<< get correct bit
7030 emitcode("xch","a,%s", x);
7032 emitcode("rrc","a");
7033 emitcode("xch","a,%s", x);
7034 emitcode("rrc","a");
7035 emitcode("xch","a,%s", x);
7038 case 7: // a:x <<= 7
7040 emitcode ("anl", "a,#0x%02x",
7041 SRMask[shCount]); // 0000000B:CCCCCCCD
7043 emitcode ("mov", "c,acc.0"); // c = B
7045 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7047 AccAXRrl1 (x); // BCCCCCCC:D0000000
7056 #ifdef BETTER_LITERAL_SHIFT
7058 /*-----------------------------------------------------------------*/
7059 /* AccAXRsh - right shift a:x known count (0..7) */
7060 /*-----------------------------------------------------------------*/
7062 AccAXRsh (char *x, int shCount)
7070 AccAXRrl1 (x); // 0->a:x
7075 AccAXRrl1 (x); // 0->a:x
7078 AccAXRrl1 (x); // 0->a:x
7083 case 5: // AAAAABBB:CCCCCDDD = a:x
7085 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7087 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7089 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7091 emitcode ("anl", "a,#0x%02x",
7092 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7094 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7096 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7098 emitcode ("anl", "a,#0x%02x",
7099 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7101 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7103 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7105 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7108 case 6: // AABBBBBB:CCDDDDDD
7110 emitcode ("mov", "c,acc.7");
7111 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7113 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7115 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7117 emitcode ("anl", "a,#0x%02x",
7118 SRMask[shCount]); // 000000AA:BBBBBBCC
7121 case 7: // ABBBBBBB:CDDDDDDD
7123 emitcode ("mov", "c,acc.7"); // c = A
7125 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7127 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7129 emitcode ("anl", "a,#0x%02x",
7130 SRMask[shCount]); // 0000000A:BBBBBBBC
7139 #ifdef BETTER_LITERAL_SHIFT
7140 /*-----------------------------------------------------------------*/
7141 /* AccAXRshS - right shift signed a:x known count (0..7) */
7142 /*-----------------------------------------------------------------*/
7144 AccAXRshS (char *x, int shCount)
7152 emitcode ("mov", "c,acc.7");
7153 AccAXRrl1 (x); // s->a:x
7157 emitcode ("mov", "c,acc.7");
7158 AccAXRrl1 (x); // s->a:x
7160 emitcode ("mov", "c,acc.7");
7161 AccAXRrl1 (x); // s->a:x
7166 case 5: // AAAAABBB:CCCCCDDD = a:x
7168 tlbl = newiTempLabel (NULL);
7169 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7171 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7173 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7175 emitcode ("anl", "a,#0x%02x",
7176 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7178 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7180 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7182 emitcode ("anl", "a,#0x%02x",
7183 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7185 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7187 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7189 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7191 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7192 emitcode ("orl", "a,#0x%02x",
7193 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7195 emitcode ("", "%05d$:", tlbl->key + 100);
7196 break; // SSSSAAAA:BBBCCCCC
7198 case 6: // AABBBBBB:CCDDDDDD
7200 tlbl = newiTempLabel (NULL);
7201 emitcode ("mov", "c,acc.7");
7202 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7204 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7206 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7208 emitcode ("anl", "a,#0x%02x",
7209 SRMask[shCount]); // 000000AA:BBBBBBCC
7211 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7212 emitcode ("orl", "a,#0x%02x",
7213 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7215 emitcode ("", "%05d$:", tlbl->key + 100);
7217 case 7: // ABBBBBBB:CDDDDDDD
7219 tlbl = newiTempLabel (NULL);
7220 emitcode ("mov", "c,acc.7"); // c = A
7222 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7224 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7226 emitcode ("anl", "a,#0x%02x",
7227 SRMask[shCount]); // 0000000A:BBBBBBBC
7229 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7230 emitcode ("orl", "a,#0x%02x",
7231 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7233 emitcode ("", "%05d$:", tlbl->key + 100);
7241 #ifdef BETTER_LITERAL_SHIFT
7243 _loadLeftIntoAx(char **lsb,
7249 // Get the initial value from left into a pair of registers.
7250 // MSB must be in A, LSB can be any register.
7252 // If the result is held in registers, it is an optimization
7253 // if the LSB can be held in the register which will hold the,
7254 // result LSB since this saves us from having to copy it into
7255 // the result following AccAXLsh.
7257 // If the result is addressed indirectly, this is not a gain.
7258 if (AOP_NEEDSACC(result))
7262 _startLazyDPSEvaluation();
7263 if (AOP_TYPE(left) == AOP_DPTR2)
7266 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7267 // get LSB in DP2_RESULT_REG.
7268 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7269 assert(!strcmp(leftByte, DP2_RESULT_REG));
7273 // get LSB into DP2_RESULT_REG
7274 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7275 if (strcmp(leftByte, DP2_RESULT_REG))
7278 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7281 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7282 assert(strcmp(leftByte, DP2_RESULT_REG));
7285 _endLazyDPSEvaluation();
7286 *lsb = DP2_RESULT_REG;
7290 if (sameRegs (AOP (result), AOP (left)) &&
7291 ((offl + MSB16) == offr))
7293 /* don't crash result[offr] */
7294 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7295 emitcode ("xch", "a,%s",
7296 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7300 movLeft2Result (left, offl, result, offr, 0);
7301 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7303 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7304 assert(strcmp(*lsb,"a"));
7309 _storeAxResults(char *lsb,
7313 _startLazyDPSEvaluation();
7314 if (AOP_NEEDSACC(result))
7316 /* We have to explicitly update the result LSB.
7318 emitcode("xch","a,%s", lsb);
7319 aopPut(AOP(result), "a", offr);
7320 emitcode("mov","a,%s", lsb);
7322 if (getDataSize (result) > 1)
7324 aopPut (AOP (result), "a", offr + MSB16);
7326 _endLazyDPSEvaluation();
7329 /*-----------------------------------------------------------------*/
7330 /* shiftL2Left2Result - shift left two bytes from left to result */
7331 /*-----------------------------------------------------------------*/
7333 shiftL2Left2Result (operand * left, int offl,
7334 operand * result, int offr, int shCount)
7338 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7340 AccAXLsh (lsb, shCount);
7342 _storeAxResults(lsb, result, offr);
7346 #ifdef BETTER_LITERAL_SHIFT
7347 /*-----------------------------------------------------------------*/
7348 /* shiftR2Left2Result - shift right two bytes from left to result */
7349 /*-----------------------------------------------------------------*/
7351 shiftR2Left2Result (operand * left, int offl,
7352 operand * result, int offr,
7353 int shCount, int sign)
7357 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7359 /* a:x >> shCount (x = lsb(result)) */
7362 AccAXRshS(lsb, shCount);
7366 AccAXRsh(lsb, shCount);
7369 _storeAxResults(lsb, result, offr);
7375 /*-----------------------------------------------------------------*/
7376 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7377 /*-----------------------------------------------------------------*/
7379 shiftLLeftOrResult (operand * left, int offl,
7380 operand * result, int offr, int shCount)
7382 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7383 /* shift left accumulator */
7385 /* or with result */
7386 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7387 /* back to result */
7388 aopPut (AOP (result), "a", offr);
7394 /*-----------------------------------------------------------------*/
7395 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7396 /*-----------------------------------------------------------------*/
7398 shiftRLeftOrResult (operand * left, int offl,
7399 operand * result, int offr, int shCount)
7401 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7402 /* shift right accumulator */
7404 /* or with result */
7405 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7406 /* back to result */
7407 aopPut (AOP (result), "a", offr);
7411 #ifdef BETTER_LITERAL_SHIFT
7412 /*-----------------------------------------------------------------*/
7413 /* genlshOne - left shift a one byte quantity by known count */
7414 /*-----------------------------------------------------------------*/
7416 genlshOne (operand * result, operand * left, int shCount)
7418 D (emitcode (";", "genlshOne "););
7419 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7423 #ifdef BETTER_LITERAL_SHIFT
7424 /*-----------------------------------------------------------------*/
7425 /* genlshTwo - left shift two bytes by known amount != 0 */
7426 /*-----------------------------------------------------------------*/
7428 genlshTwo (operand * result, operand * left, int shCount)
7432 D (emitcode (";", "genlshTwo "););
7434 size = getDataSize (result);
7436 /* if shCount >= 8 */
7441 _startLazyDPSEvaluation();
7447 _endLazyDPSEvaluation();
7448 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7449 aopPut (AOP (result), zero, LSB);
7453 movLeft2Result (left, LSB, result, MSB16, 0);
7454 aopPut (AOP (result), zero, LSB);
7455 _endLazyDPSEvaluation();
7460 aopPut (AOP (result), zero, LSB);
7461 _endLazyDPSEvaluation();
7465 /* 1 <= shCount <= 7 */
7470 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7474 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7482 /*-----------------------------------------------------------------*/
7483 /* shiftLLong - shift left one long from left to result */
7484 /* offl = LSB or MSB16 */
7485 /*-----------------------------------------------------------------*/
7487 shiftLLong (operand * left, operand * result, int offr)
7490 int size = AOP_SIZE (result);
7492 if (size >= LSB + offr)
7494 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7496 emitcode ("add", "a,acc");
7497 if (sameRegs (AOP (left), AOP (result)) &&
7498 size >= MSB16 + offr && offr != LSB)
7499 emitcode ("xch", "a,%s",
7500 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7502 aopPut (AOP (result), "a", LSB + offr);
7505 if (size >= MSB16 + offr)
7507 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7509 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7512 emitcode ("rlc", "a");
7513 if (sameRegs (AOP (left), AOP (result)) &&
7514 size >= MSB24 + offr && offr != LSB)
7515 emitcode ("xch", "a,%s",
7516 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7518 aopPut (AOP (result), "a", MSB16 + offr);
7521 if (size >= MSB24 + offr)
7523 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7525 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7528 emitcode ("rlc", "a");
7529 if (sameRegs (AOP (left), AOP (result)) &&
7530 size >= MSB32 + offr && offr != LSB)
7531 emitcode ("xch", "a,%s",
7532 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7534 aopPut (AOP (result), "a", MSB24 + offr);
7537 if (size > MSB32 + offr)
7539 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7541 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7544 emitcode ("rlc", "a");
7545 aopPut (AOP (result), "a", MSB32 + offr);
7548 aopPut (AOP (result), zero, LSB);
7554 /*-----------------------------------------------------------------*/
7555 /* genlshFour - shift four byte by a known amount != 0 */
7556 /*-----------------------------------------------------------------*/
7558 genlshFour (operand * result, operand * left, int shCount)
7562 D (emitcode (";", "genlshFour ");
7565 size = AOP_SIZE (result);
7567 /* if shifting more that 3 bytes */
7572 /* lowest order of left goes to the highest
7573 order of the destination */
7574 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7576 movLeft2Result (left, LSB, result, MSB32, 0);
7577 aopPut (AOP (result), zero, LSB);
7578 aopPut (AOP (result), zero, MSB16);
7579 aopPut (AOP (result), zero, MSB24);
7583 /* more than two bytes */
7584 else if (shCount >= 16)
7586 /* lower order two bytes goes to higher order two bytes */
7588 /* if some more remaining */
7590 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7593 movLeft2Result (left, MSB16, result, MSB32, 0);
7594 movLeft2Result (left, LSB, result, MSB24, 0);
7596 aopPut (AOP (result), zero, MSB16);
7597 aopPut (AOP (result), zero, LSB);
7601 /* if more than 1 byte */
7602 else if (shCount >= 8)
7604 /* lower order three bytes goes to higher order three bytes */
7609 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7611 movLeft2Result (left, LSB, result, MSB16, 0);
7617 movLeft2Result (left, MSB24, result, MSB32, 0);
7618 movLeft2Result (left, MSB16, result, MSB24, 0);
7619 movLeft2Result (left, LSB, result, MSB16, 0);
7620 aopPut (AOP (result), zero, LSB);
7622 else if (shCount == 1)
7623 shiftLLong (left, result, MSB16);
7626 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7627 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7628 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7629 aopPut (AOP (result), zero, LSB);
7634 /* 1 <= shCount <= 7 */
7635 else if (shCount <= 2)
7637 shiftLLong (left, result, LSB);
7639 shiftLLong (result, result, LSB);
7641 /* 3 <= shCount <= 7, optimize */
7644 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7645 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7646 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7651 #ifdef BETTER_LITERAL_SHIFT
7652 /*-----------------------------------------------------------------*/
7653 /* genLeftShiftLiteral - left shifting by known count */
7654 /*-----------------------------------------------------------------*/
7656 genLeftShiftLiteral (operand * left,
7661 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7664 size = getSize (operandType (result));
7666 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7668 /* We only handle certain easy cases so far. */
7670 && (shCount < (size * 8))
7674 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7678 freeAsmop (right, NULL, ic, TRUE);
7680 aopOp(left, ic, FALSE, FALSE);
7681 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7684 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7686 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7687 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7689 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7692 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7694 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7695 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7697 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7703 emitcode ("; shift left ", "result %d, left %d", size,
7707 /* I suppose that the left size >= result size */
7710 _startLazyDPSEvaluation();
7713 movLeft2Result (left, size, result, size, 0);
7715 _endLazyDPSEvaluation();
7717 else if (shCount >= (size * 8))
7719 _startLazyDPSEvaluation();
7722 aopPut (AOP (result), zero, size);
7724 _endLazyDPSEvaluation();
7731 genlshOne (result, left, shCount);
7735 genlshTwo (result, left, shCount);
7739 genlshFour (result, left, shCount);
7743 fprintf(stderr, "*** ack! mystery literal shift!\n");
7747 freeAsmop (left, NULL, ic, TRUE);
7748 freeAsmop (result, NULL, ic, TRUE);
7753 /*-----------------------------------------------------------------*/
7754 /* genLeftShift - generates code for left shifting */
7755 /*-----------------------------------------------------------------*/
7757 genLeftShift (iCode * ic)
7759 operand *left, *right, *result;
7762 symbol *tlbl, *tlbl1;
7764 D (emitcode (";", "genLeftShift "););
7766 right = IC_RIGHT (ic);
7767 left = IC_LEFT (ic);
7768 result = IC_RESULT (ic);
7770 aopOp (right, ic, FALSE, FALSE);
7773 #ifdef BETTER_LITERAL_SHIFT
7774 /* if the shift count is known then do it
7775 as efficiently as possible */
7776 if (AOP_TYPE (right) == AOP_LIT)
7778 if (genLeftShiftLiteral (left, right, result, ic))
7785 /* shift count is unknown then we have to form
7786 a loop get the loop count in B : Note: we take
7787 only the lower order byte since shifting
7788 more that 32 bits make no sense anyway, ( the
7789 largest size of an object can be only 32 bits ) */
7791 if (AOP_TYPE (right) == AOP_LIT)
7793 /* Really should be handled by genLeftShiftLiteral,
7794 * but since I'm too lazy to fix that today, at least we can make
7795 * some small improvement.
7797 emitcode("mov", "b,#0x%02x",
7798 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7802 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7803 emitcode ("inc", "b");
7805 freeAsmop (right, NULL, ic, TRUE);
7806 aopOp (left, ic, FALSE, FALSE);
7807 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7809 /* now move the left to the result if they are not the
7811 if (!sameRegs (AOP (left), AOP (result)) &&
7812 AOP_SIZE (result) > 1)
7815 size = AOP_SIZE (result);
7817 _startLazyDPSEvaluation ();
7820 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7821 if (*l == '@' && (IS_AOP_PREG (result)))
7824 emitcode ("mov", "a,%s", l);
7825 aopPut (AOP (result), "a", offset);
7828 aopPut (AOP (result), l, offset);
7831 _endLazyDPSEvaluation ();
7834 tlbl = newiTempLabel (NULL);
7835 size = AOP_SIZE (result);
7837 tlbl1 = newiTempLabel (NULL);
7839 /* if it is only one byte then */
7842 symbol *tlbl1 = newiTempLabel (NULL);
7844 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7846 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7847 emitcode ("", "%05d$:", tlbl->key + 100);
7848 emitcode ("add", "a,acc");
7849 emitcode ("", "%05d$:", tlbl1->key + 100);
7850 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7851 aopPut (AOP (result), "a", 0);
7855 reAdjustPreg (AOP (result));
7857 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7858 emitcode ("", "%05d$:", tlbl->key + 100);
7859 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7861 emitcode ("add", "a,acc");
7862 aopPut (AOP (result), "a", offset++);
7863 _startLazyDPSEvaluation ();
7866 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7868 emitcode ("rlc", "a");
7869 aopPut (AOP (result), "a", offset++);
7871 _endLazyDPSEvaluation ();
7872 reAdjustPreg (AOP (result));
7874 emitcode ("", "%05d$:", tlbl1->key + 100);
7875 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7877 freeAsmop (left, NULL, ic, TRUE);
7878 freeAsmop (result, NULL, ic, TRUE);
7881 #ifdef BETTER_LITERAL_SHIFT
7882 /*-----------------------------------------------------------------*/
7883 /* genrshOne - right shift a one byte quantity by known count */
7884 /*-----------------------------------------------------------------*/
7886 genrshOne (operand * result, operand * left,
7887 int shCount, int sign)
7889 D (emitcode (";", "genrshOne"););
7890 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7894 #ifdef BETTER_LITERAL_SHIFT
7895 /*-----------------------------------------------------------------*/
7896 /* genrshTwo - right shift two bytes by known amount != 0 */
7897 /*-----------------------------------------------------------------*/
7899 genrshTwo (operand * result, operand * left,
7900 int shCount, int sign)
7902 D (emitcode (";", "genrshTwo"););
7904 /* if shCount >= 8 */
7908 _startLazyDPSEvaluation();
7911 shiftR1Left2Result (left, MSB16, result, LSB,
7916 movLeft2Result (left, MSB16, result, LSB, sign);
7918 addSign (result, MSB16, sign);
7919 _endLazyDPSEvaluation();
7922 /* 1 <= shCount <= 7 */
7925 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7932 /*-----------------------------------------------------------------*/
7933 /* shiftRLong - shift right one long from left to result */
7934 /* offl = LSB or MSB16 */
7935 /*-----------------------------------------------------------------*/
7937 shiftRLong (operand * left, int offl,
7938 operand * result, int sign)
7940 int isSameRegs=sameRegs(AOP(left),AOP(result));
7942 if (isSameRegs && offl>1) {
7943 // we are in big trouble, but this shouldn't happen
7944 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7947 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7952 emitcode ("rlc", "a");
7953 emitcode ("subb", "a,acc");
7954 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7956 aopPut (AOP(result), zero, MSB32);
7961 emitcode ("clr", "c");
7963 emitcode ("mov", "c,acc.7");
7966 emitcode ("rrc", "a");
7968 if (isSameRegs && offl==MSB16) {
7969 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7971 aopPut (AOP (result), "a", MSB32);
7972 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7975 emitcode ("rrc", "a");
7976 if (isSameRegs && offl==1) {
7977 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7979 aopPut (AOP (result), "a", MSB24);
7980 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7982 emitcode ("rrc", "a");
7983 aopPut (AOP (result), "a", MSB16 - offl);
7987 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7988 emitcode ("rrc", "a");
7989 aopPut (AOP (result), "a", LSB);
7996 /*-----------------------------------------------------------------*/
7997 /* genrshFour - shift four byte by a known amount != 0 */
7998 /*-----------------------------------------------------------------*/
8000 genrshFour (operand * result, operand * left,
8001 int shCount, int sign)
8003 D (emitcode (";", "genrshFour");
8006 /* if shifting more that 3 bytes */
8011 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8013 movLeft2Result (left, MSB32, result, LSB, sign);
8014 addSign (result, MSB16, sign);
8016 else if (shCount >= 16)
8020 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8023 movLeft2Result (left, MSB24, result, LSB, 0);
8024 movLeft2Result (left, MSB32, result, MSB16, sign);
8026 addSign (result, MSB24, sign);
8028 else if (shCount >= 8)
8032 shiftRLong (left, MSB16, result, sign);
8033 else if (shCount == 0)
8035 movLeft2Result (left, MSB16, result, LSB, 0);
8036 movLeft2Result (left, MSB24, result, MSB16, 0);
8037 movLeft2Result (left, MSB32, result, MSB24, sign);
8038 addSign (result, MSB32, sign);
8042 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8043 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8044 /* the last shift is signed */
8045 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8046 addSign (result, MSB32, sign);
8050 { /* 1 <= shCount <= 7 */
8053 shiftRLong (left, LSB, result, sign);
8055 shiftRLong (result, LSB, result, sign);
8059 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8060 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8061 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8067 #ifdef BETTER_LITERAL_SHIFT
8068 /*-----------------------------------------------------------------*/
8069 /* genRightShiftLiteral - right shifting by known count */
8070 /*-----------------------------------------------------------------*/
8072 genRightShiftLiteral (operand * left,
8078 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8081 size = getSize (operandType (result));
8083 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8085 /* We only handle certain easy cases so far. */
8087 && (shCount < (size * 8))
8091 D(emitcode (";", "genRightShiftLiteral wimping out"););
8095 freeAsmop (right, NULL, ic, TRUE);
8097 aopOp (left, ic, FALSE, FALSE);
8098 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8101 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8105 /* test the LEFT size !!! */
8107 /* I suppose that the left size >= result size */
8110 size = getDataSize (result);
8111 _startLazyDPSEvaluation();
8114 movLeft2Result (left, size, result, size, 0);
8116 _endLazyDPSEvaluation();
8118 else if (shCount >= (size * 8))
8122 /* get sign in acc.7 */
8123 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8125 addSign (result, LSB, sign);
8132 genrshOne (result, left, shCount, sign);
8136 genrshTwo (result, left, shCount, sign);
8140 genrshFour (result, left, shCount, sign);
8147 freeAsmop (left, NULL, ic, TRUE);
8148 freeAsmop (result, NULL, ic, TRUE);
8154 /*-----------------------------------------------------------------*/
8155 /* genSignedRightShift - right shift of signed number */
8156 /*-----------------------------------------------------------------*/
8158 genSignedRightShift (iCode * ic)
8160 operand *right, *left, *result;
8163 symbol *tlbl, *tlbl1;
8165 D (emitcode (";", "genSignedRightShift "););
8167 /* we do it the hard way put the shift count in b
8168 and loop thru preserving the sign */
8170 right = IC_RIGHT (ic);
8171 left = IC_LEFT (ic);
8172 result = IC_RESULT (ic);
8174 aopOp (right, ic, FALSE, FALSE);
8176 #ifdef BETTER_LITERAL_SHIFT
8177 if (AOP_TYPE (right) == AOP_LIT)
8179 if (genRightShiftLiteral (left, right, result, ic, 1))
8185 /* shift count is unknown then we have to form
8186 a loop get the loop count in B : Note: we take
8187 only the lower order byte since shifting
8188 more that 32 bits make no sense anyway, ( the
8189 largest size of an object can be only 32 bits ) */
8191 if (AOP_TYPE (right) == AOP_LIT)
8193 /* Really should be handled by genRightShiftLiteral,
8194 * but since I'm too lazy to fix that today, at least we can make
8195 * some small improvement.
8197 emitcode("mov", "b,#0x%02x",
8198 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8202 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8203 emitcode ("inc", "b");
8205 freeAsmop (right, NULL, ic, TRUE);
8206 aopOp (left, ic, FALSE, FALSE);
8207 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8209 /* now move the left to the result if they are not the
8211 if (!sameRegs (AOP (left), AOP (result)) &&
8212 AOP_SIZE (result) > 1)
8215 size = AOP_SIZE (result);
8217 _startLazyDPSEvaluation ();
8220 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8221 if (*l == '@' && IS_AOP_PREG (result))
8224 emitcode ("mov", "a,%s", l);
8225 aopPut (AOP (result), "a", offset);
8228 aopPut (AOP (result), l, offset);
8231 _endLazyDPSEvaluation ();
8234 /* mov the highest order bit to OVR */
8235 tlbl = newiTempLabel (NULL);
8236 tlbl1 = newiTempLabel (NULL);
8238 size = AOP_SIZE (result);
8240 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8241 emitcode ("rlc", "a");
8242 emitcode ("mov", "ov,c");
8243 /* if it is only one byte then */
8246 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8248 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8249 emitcode ("", "%05d$:", tlbl->key + 100);
8250 emitcode ("mov", "c,ov");
8251 emitcode ("rrc", "a");
8252 emitcode ("", "%05d$:", tlbl1->key + 100);
8253 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8254 aopPut (AOP (result), "a", 0);
8258 reAdjustPreg (AOP (result));
8259 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8260 emitcode ("", "%05d$:", tlbl->key + 100);
8261 emitcode ("mov", "c,ov");
8262 _startLazyDPSEvaluation ();
8265 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8267 emitcode ("rrc", "a");
8268 aopPut (AOP (result), "a", offset--);
8270 _endLazyDPSEvaluation ();
8271 reAdjustPreg (AOP (result));
8272 emitcode ("", "%05d$:", tlbl1->key + 100);
8273 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8276 freeAsmop (left, NULL, ic, TRUE);
8277 freeAsmop (result, NULL, ic, TRUE);
8280 /*-----------------------------------------------------------------*/
8281 /* genRightShift - generate code for right shifting */
8282 /*-----------------------------------------------------------------*/
8284 genRightShift (iCode * ic)
8286 operand *right, *left, *result;
8290 symbol *tlbl, *tlbl1;
8292 D (emitcode (";", "genRightShift "););
8294 /* if signed then we do it the hard way preserve the
8295 sign bit moving it inwards */
8296 retype = getSpec (operandType (IC_RESULT (ic)));
8298 if (!SPEC_USIGN (retype))
8300 genSignedRightShift (ic);
8304 /* signed & unsigned types are treated the same : i.e. the
8305 signed is NOT propagated inwards : quoting from the
8306 ANSI - standard : "for E1 >> E2, is equivalent to division
8307 by 2**E2 if unsigned or if it has a non-negative value,
8308 otherwise the result is implementation defined ", MY definition
8309 is that the sign does not get propagated */
8311 right = IC_RIGHT (ic);
8312 left = IC_LEFT (ic);
8313 result = IC_RESULT (ic);
8315 aopOp (right, ic, FALSE, FALSE);
8317 #ifdef BETTER_LITERAL_SHIFT
8318 /* if the shift count is known then do it
8319 as efficiently as possible */
8320 if (AOP_TYPE (right) == AOP_LIT)
8322 if (genRightShiftLiteral (left, right, result, ic, 0))
8329 /* shift count is unknown then we have to form
8330 a loop get the loop count in B : Note: we take
8331 only the lower order byte since shifting
8332 more that 32 bits make no sense anyway, ( the
8333 largest size of an object can be only 32 bits ) */
8335 if (AOP_TYPE (right) == AOP_LIT)
8337 /* Really should be handled by genRightShiftLiteral,
8338 * but since I'm too lazy to fix that today, at least we can make
8339 * some small improvement.
8341 emitcode("mov", "b,#0x%02x",
8342 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8346 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8347 emitcode ("inc", "b");
8349 freeAsmop (right, NULL, ic, TRUE);
8350 aopOp (left, ic, FALSE, FALSE);
8351 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8353 /* now move the left to the result if they are not the
8355 if (!sameRegs (AOP (left), AOP (result)) &&
8356 AOP_SIZE (result) > 1)
8359 size = AOP_SIZE (result);
8361 _startLazyDPSEvaluation ();
8364 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8365 if (*l == '@' && IS_AOP_PREG (result))
8368 emitcode ("mov", "a,%s", l);
8369 aopPut (AOP (result), "a", offset);
8372 aopPut (AOP (result), l, offset);
8375 _endLazyDPSEvaluation ();
8378 tlbl = newiTempLabel (NULL);
8379 tlbl1 = newiTempLabel (NULL);
8380 size = AOP_SIZE (result);
8383 /* if it is only one byte then */
8386 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8388 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8389 emitcode ("", "%05d$:", tlbl->key + 100);
8391 emitcode ("rrc", "a");
8392 emitcode ("", "%05d$:", tlbl1->key + 100);
8393 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8394 aopPut (AOP (result), "a", 0);
8398 reAdjustPreg (AOP (result));
8399 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8400 emitcode ("", "%05d$:", tlbl->key + 100);
8402 _startLazyDPSEvaluation ();
8405 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8407 emitcode ("rrc", "a");
8408 aopPut (AOP (result), "a", offset--);
8410 _endLazyDPSEvaluation ();
8411 reAdjustPreg (AOP (result));
8413 emitcode ("", "%05d$:", tlbl1->key + 100);
8414 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8417 freeAsmop (left, NULL, ic, TRUE);
8418 freeAsmop (result, NULL, ic, TRUE);
8421 /*-----------------------------------------------------------------*/
8422 /* genUnpackBits - generates code for unpacking bits */
8423 /*-----------------------------------------------------------------*/
8425 genUnpackBits (operand * result, char *rname, int ptype)
8432 D (emitcode (";", "genUnpackBits ");
8435 etype = getSpec (operandType (result));
8437 /* read the first byte */
8443 emitcode ("mov", "a,@%s", rname);
8447 emitcode ("movx", "a,@%s", rname);
8451 emitcode ("movx", "a,@dptr");
8455 emitcode ("clr", "a");
8456 emitcode ("movc", "a,@a+dptr");
8460 emitcode ("lcall", "__gptrget");
8464 /* if we have bitdisplacement then it fits */
8465 /* into this byte completely or if length is */
8466 /* less than a byte */
8467 if ((shCnt = SPEC_BSTR (etype)) ||
8468 (SPEC_BLEN (etype) <= 8))
8471 /* shift right acc */
8474 emitcode ("anl", "a,#0x%02x",
8475 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8476 aopPut (AOP (result), "a", offset);
8480 /* bit field did not fit in a byte */
8481 rlen = SPEC_BLEN (etype) - 8;
8482 aopPut (AOP (result), "a", offset++);
8491 emitcode ("inc", "%s", rname);
8492 emitcode ("mov", "a,@%s", rname);
8496 emitcode ("inc", "%s", rname);
8497 emitcode ("movx", "a,@%s", rname);
8501 emitcode ("inc", "dptr");
8502 emitcode ("movx", "a,@dptr");
8506 emitcode ("clr", "a");
8507 emitcode ("inc", "dptr");
8508 emitcode ("movc", "a,@a+dptr");
8512 emitcode ("inc", "dptr");
8513 emitcode ("lcall", "__gptrget");
8518 /* if we are done */
8522 aopPut (AOP (result), "a", offset++);
8528 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
8529 aopPut (AOP (result), "a", offset);
8536 /*-----------------------------------------------------------------*/
8537 /* genDataPointerGet - generates code when ptr offset is known */
8538 /*-----------------------------------------------------------------*/
8540 genDataPointerGet (operand * left,
8546 int size, offset = 0;
8547 aopOp (result, ic, TRUE, FALSE);
8549 /* get the string representation of the name */
8550 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8551 size = AOP_SIZE (result);
8552 _startLazyDPSEvaluation ();
8556 sprintf (buffer, "(%s + %d)", l + 1, offset);
8558 sprintf (buffer, "%s", l + 1);
8559 aopPut (AOP (result), buffer, offset++);
8561 _endLazyDPSEvaluation ();
8563 freeAsmop (left, NULL, ic, TRUE);
8564 freeAsmop (result, NULL, ic, TRUE);
8567 /*-----------------------------------------------------------------*/
8568 /* genNearPointerGet - emitcode for near pointer fetch */
8569 /*-----------------------------------------------------------------*/
8571 genNearPointerGet (operand * left,
8579 sym_link *rtype, *retype, *letype;
8580 sym_link *ltype = operandType (left);
8583 rtype = operandType (result);
8584 retype = getSpec (rtype);
8585 letype = getSpec (ltype);
8587 aopOp (left, ic, FALSE, FALSE);
8589 /* if left is rematerialisable and
8590 result is not bit variable type and
8591 the left is pointer to data space i.e
8592 lower 128 bytes of space */
8593 if (AOP_TYPE (left) == AOP_IMMD &&
8594 !IS_BITVAR (retype) &&
8595 !IS_BITVAR (letype) &&
8596 DCL_TYPE (ltype) == POINTER)
8598 genDataPointerGet (left, result, ic);
8602 /* if the value is already in a pointer register
8603 then don't need anything more */
8604 if (!AOP_INPREG (AOP (left)))
8606 /* otherwise get a free pointer register */
8608 preg = getFreePtr (ic, &aop, FALSE);
8609 emitcode ("mov", "%s,%s",
8611 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8615 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8617 freeAsmop (left, NULL, ic, TRUE);
8618 aopOp (result, ic, FALSE, FALSE);
8620 /* if bitfield then unpack the bits */
8621 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8622 genUnpackBits (result, rname, POINTER);
8625 /* we have can just get the values */
8626 int size = AOP_SIZE (result);
8631 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8634 emitcode ("mov", "a,@%s", rname);
8635 aopPut (AOP (result), "a", offset);
8639 sprintf (buffer, "@%s", rname);
8640 aopPut (AOP (result), buffer, offset);
8644 emitcode ("inc", "%s", rname);
8648 /* now some housekeeping stuff */
8651 /* we had to allocate for this iCode */
8652 if (pi) { /* post increment present */
8653 aopPut(AOP ( left ),rname,0);
8655 freeAsmop (NULL, aop, ic, TRUE);
8659 /* we did not allocate which means left
8660 already in a pointer register, then
8661 if size > 0 && this could be used again
8662 we have to point it back to where it
8664 if (AOP_SIZE (result) > 1 &&
8665 !OP_SYMBOL (left)->remat &&
8666 (OP_SYMBOL (left)->liveTo > ic->seq ||
8670 int size = AOP_SIZE (result) - 1;
8672 emitcode ("dec", "%s", rname);
8677 freeAsmop (result, NULL, ic, TRUE);
8678 if (pi) pi->generated = 1;
8681 /*-----------------------------------------------------------------*/
8682 /* genPagedPointerGet - emitcode for paged pointer fetch */
8683 /*-----------------------------------------------------------------*/
8685 genPagedPointerGet (operand * left,
8693 sym_link *rtype, *retype, *letype;
8695 rtype = operandType (result);
8696 retype = getSpec (rtype);
8697 letype = getSpec (operandType (left));
8698 aopOp (left, ic, FALSE, FALSE);
8700 /* if the value is already in a pointer register
8701 then don't need anything more */
8702 if (!AOP_INPREG (AOP (left)))
8704 /* otherwise get a free pointer register */
8706 preg = getFreePtr (ic, &aop, FALSE);
8707 emitcode ("mov", "%s,%s",
8709 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8713 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8715 freeAsmop (left, NULL, ic, TRUE);
8716 aopOp (result, ic, FALSE, FALSE);
8718 /* if bitfield then unpack the bits */
8719 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8720 genUnpackBits (result, rname, PPOINTER);
8723 /* we have can just get the values */
8724 int size = AOP_SIZE (result);
8730 emitcode ("movx", "a,@%s", rname);
8731 aopPut (AOP (result), "a", offset);
8736 emitcode ("inc", "%s", rname);
8740 /* now some housekeeping stuff */
8743 /* we had to allocate for this iCode */
8744 if (pi) aopPut ( AOP (left), rname, 0);
8745 freeAsmop (NULL, aop, ic, TRUE);
8749 /* we did not allocate which means left
8750 already in a pointer register, then
8751 if size > 0 && this could be used again
8752 we have to point it back to where it
8754 if (AOP_SIZE (result) > 1 &&
8755 !OP_SYMBOL (left)->remat &&
8756 (OP_SYMBOL (left)->liveTo > ic->seq ||
8760 int size = AOP_SIZE (result) - 1;
8762 emitcode ("dec", "%s", rname);
8767 freeAsmop (result, NULL, ic, TRUE);
8768 if (pi) pi->generated = 1;
8771 /*-----------------------------------------------------------------*/
8772 /* genFarPointerGet - gget value from far space */
8773 /*-----------------------------------------------------------------*/
8775 genFarPointerGet (operand * left,
8776 operand * result, iCode * ic, iCode *pi)
8779 sym_link *retype = getSpec (operandType (result));
8780 sym_link *letype = getSpec (operandType (left));
8781 D (emitcode (";", "genFarPointerGet");
8784 aopOp (left, ic, FALSE, FALSE);
8786 /* if the operand is already in dptr
8787 then we do nothing else we move the value to dptr */
8788 if (AOP_TYPE (left) != AOP_STR)
8790 /* if this is remateriazable */
8791 if (AOP_TYPE (left) == AOP_IMMD)
8793 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8797 /* we need to get it byte by byte */
8798 _startLazyDPSEvaluation ();
8799 if (AOP_TYPE (left) != AOP_DPTR)
8801 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8802 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8803 if (options.model == MODEL_FLAT24)
8804 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8808 /* We need to generate a load to DPTR indirect through DPTR. */
8809 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8811 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8812 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8813 if (options.model == MODEL_FLAT24)
8814 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8815 emitcode ("pop", "dph");
8816 emitcode ("pop", "dpl");
8818 _endLazyDPSEvaluation ();
8821 /* so dptr know contains the address */
8822 freeAsmop (left, NULL, ic, TRUE);
8823 aopOp (result, ic, FALSE, TRUE);
8825 /* if bit then unpack */
8826 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8827 genUnpackBits (result, "dptr", FPOINTER);
8830 size = AOP_SIZE (result);
8833 _startLazyDPSEvaluation ();
8840 emitcode ("movx", "a,@dptr");
8842 emitcode ("inc", "dptr");
8844 aopPut (AOP (result), "a", offset++);
8846 _endLazyDPSEvaluation ();
8848 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
8849 aopPut ( AOP (left), "dpl", 0);
8850 aopPut ( AOP (left), "dph", 1);
8851 if (options.model == MODEL_FLAT24)
8852 aopPut ( AOP (left), "dpx", 2);
8856 freeAsmop (result, NULL, ic, TRUE);
8859 /*-----------------------------------------------------------------*/
8860 /* emitcodePointerGet - gget value from code space */
8861 /*-----------------------------------------------------------------*/
8863 emitcodePointerGet (operand * left,
8864 operand * result, iCode * ic, iCode *pi)
8867 sym_link *retype = getSpec (operandType (result));
8869 aopOp (left, ic, FALSE, FALSE);
8871 /* if the operand is already in dptr
8872 then we do nothing else we move the value to dptr */
8873 if (AOP_TYPE (left) != AOP_STR)
8875 /* if this is remateriazable */
8876 if (AOP_TYPE (left) == AOP_IMMD)
8878 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8881 { /* we need to get it byte by byte */
8882 _startLazyDPSEvaluation ();
8883 if (AOP_TYPE (left) != AOP_DPTR)
8885 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8886 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8887 if (options.model == MODEL_FLAT24)
8888 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8892 /* We need to generate a load to DPTR indirect through DPTR. */
8893 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8895 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8896 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8897 if (options.model == MODEL_FLAT24)
8898 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8899 emitcode ("pop", "dph");
8900 emitcode ("pop", "dpl");
8902 _endLazyDPSEvaluation ();
8905 /* so dptr know contains the address */
8906 aopOp (result, ic, FALSE, TRUE);
8908 /* if bit then unpack */
8909 if (IS_BITVAR (retype))
8910 genUnpackBits (result, "dptr", CPOINTER);
8913 size = AOP_SIZE (result);
8916 _startLazyDPSEvaluation ();
8922 emitcode ("clr", "a");
8923 emitcode ("movc", "a,@a+dptr");
8925 emitcode ("inc", "dptr");
8926 aopPut (AOP (result), "a", offset++);
8928 _endLazyDPSEvaluation ();
8930 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
8931 aopPut ( AOP (left), "dpl", 0);
8932 aopPut ( AOP (left), "dph", 1);
8933 if (options.model == MODEL_FLAT24)
8934 aopPut ( AOP (left), "dpx", 2);
8938 freeAsmop (left, NULL, ic, TRUE);
8939 freeAsmop (result, NULL, ic, TRUE);
8942 /*-----------------------------------------------------------------*/
8943 /* genGenPointerGet - gget value from generic pointer space */
8944 /*-----------------------------------------------------------------*/
8946 genGenPointerGet (operand * left,
8947 operand * result, iCode * ic, iCode * pi)
8950 sym_link *retype = getSpec (operandType (result));
8951 sym_link *letype = getSpec (operandType (left));
8953 D (emitcode (";", "genGenPointerGet "); );
8955 aopOp (left, ic, FALSE, TRUE);
8957 /* if the operand is already in dptr
8958 then we do nothing else we move the value to dptr */
8959 if (AOP_TYPE (left) != AOP_STR)
8961 /* if this is remateriazable */
8962 if (AOP_TYPE (left) == AOP_IMMD)
8964 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8965 if (AOP(left)->aopu.aop_immd.from_cast_remat)
8966 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
8968 emitcode ("mov", "b,#%d", pointerCode (retype));
8971 { /* we need to get it byte by byte */
8972 _startLazyDPSEvaluation ();
8973 if (AOP(left)->type==AOP_DPTR2) {
8975 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8978 emitcode ("mov", "dpl,%s", l);
8979 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8982 emitcode ("mov", "dph,%s", l);
8983 if (options.model == MODEL_FLAT24) {
8984 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8987 emitcode ("mov", "dpx,%s", l);
8988 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8990 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8993 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8994 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8995 if (options.model == MODEL_FLAT24) {
8996 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8997 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8999 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9002 _endLazyDPSEvaluation ();
9005 /* so dptr know contains the address */
9006 aopOp (result, ic, FALSE, TRUE);
9008 /* if bit then unpack */
9009 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9010 genUnpackBits (result, "dptr", GPOINTER);
9013 size = AOP_SIZE (result);
9018 emitcode ("lcall", "__gptrget");
9019 aopPut (AOP (result), "a", offset++);
9021 emitcode ("inc", "dptr");
9025 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
9026 aopPut ( AOP (left), "dpl", 0);
9027 aopPut ( AOP (left), "dph", 1);
9028 if (options.model == MODEL_FLAT24) {
9029 aopPut ( AOP (left), "dpx", 2);
9030 aopPut ( AOP (left), "b", 3);
9031 } else aopPut ( AOP (left), "b", 2);
9034 freeAsmop (left, NULL, ic, TRUE);
9035 freeAsmop (result, NULL, ic, TRUE);
9038 /*-----------------------------------------------------------------*/
9039 /* genPointerGet - generate code for pointer get */
9040 /*-----------------------------------------------------------------*/
9042 genPointerGet (iCode * ic, iCode *pi)
9044 operand *left, *result;
9045 sym_link *type, *etype;
9048 D (emitcode (";", "genPointerGet ");
9051 left = IC_LEFT (ic);
9052 result = IC_RESULT (ic);
9054 /* depending on the type of pointer we need to
9055 move it to the correct pointer register */
9056 type = operandType (left);
9057 etype = getSpec (type);
9058 /* if left is of type of pointer then it is simple */
9059 if (IS_PTR (type) && !IS_FUNC (type->next))
9060 p_type = DCL_TYPE (type);
9063 /* we have to go by the storage class */
9064 p_type = PTR_TYPE (SPEC_OCLS (etype));
9066 /* special case when cast remat */
9067 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9068 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9069 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9070 type = type = operandType (left);
9071 p_type = DCL_TYPE (type);
9073 /* now that we have the pointer type we assign
9074 the pointer values */
9080 genNearPointerGet (left, result, ic, pi);
9084 genPagedPointerGet (left, result, ic, pi);
9088 genFarPointerGet (left, result, ic, pi);
9092 emitcodePointerGet (left, result, ic, pi);
9096 genGenPointerGet (left, result, ic, pi);
9102 /*-----------------------------------------------------------------*/
9103 /* genPackBits - generates code for packed bit storage */
9104 /*-----------------------------------------------------------------*/
9106 genPackBits (sym_link * etype,
9108 char *rname, int p_type)
9116 blen = SPEC_BLEN (etype);
9117 bstr = SPEC_BSTR (etype);
9119 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9122 /* if the bit lenth is less than or */
9123 /* it exactly fits a byte then */
9124 if (SPEC_BLEN (etype) <= 8)
9126 shCount = SPEC_BSTR (etype);
9128 /* shift left acc */
9131 if (SPEC_BLEN (etype) < 8)
9132 { /* if smaller than a byte */
9138 emitcode ("mov", "b,a");
9139 emitcode ("mov", "a,@%s", rname);
9143 emitcode ("mov", "b,a");
9144 emitcode ("movx", "a,@dptr");
9148 emitcode ("push", "b");
9149 emitcode ("push", "acc");
9150 emitcode ("lcall", "__gptrget");
9151 emitcode ("pop", "b");
9155 emitcode ("anl", "a,#0x%02x", (unsigned char)
9156 ((unsigned char) (0xFF << (blen + bstr)) |
9157 (unsigned char) (0xFF >> (8 - bstr))));
9158 emitcode ("orl", "a,b");
9159 if (p_type == GPOINTER)
9160 emitcode ("pop", "b");
9167 emitcode ("mov", "@%s,a", rname);
9171 emitcode ("movx", "@dptr,a");
9175 emitcode ("lcall", "__gptrput");
9180 if (SPEC_BLEN (etype) <= 8)
9183 emitcode ("inc", "%s", rname);
9184 rLen = SPEC_BLEN (etype);
9186 /* now generate for lengths greater than one byte */
9190 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9202 emitcode ("mov", "@%s,a", rname);
9205 emitcode ("mov", "@%s,%s", rname, l);
9210 emitcode ("movx", "@dptr,a");
9215 emitcode ("lcall", "__gptrput");
9218 emitcode ("inc", "%s", rname);
9223 /* last last was not complete */
9226 /* save the byte & read byte */
9230 emitcode ("mov", "b,a");
9231 emitcode ("mov", "a,@%s", rname);
9235 emitcode ("mov", "b,a");
9236 emitcode ("movx", "a,@dptr");
9240 emitcode ("push", "b");
9241 emitcode ("push", "acc");
9242 emitcode ("lcall", "__gptrget");
9243 emitcode ("pop", "b");
9247 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
9248 emitcode ("orl", "a,b");
9251 if (p_type == GPOINTER)
9252 emitcode ("pop", "b");
9258 emitcode ("mov", "@%s,a", rname);
9262 emitcode ("movx", "@dptr,a");
9266 emitcode ("lcall", "__gptrput");
9270 /*-----------------------------------------------------------------*/
9271 /* genDataPointerSet - remat pointer to data space */
9272 /*-----------------------------------------------------------------*/
9274 genDataPointerSet (operand * right,
9278 int size, offset = 0;
9279 char *l, buffer[256];
9281 aopOp (right, ic, FALSE, FALSE);
9283 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9284 size = AOP_SIZE (right);
9288 sprintf (buffer, "(%s + %d)", l + 1, offset);
9290 sprintf (buffer, "%s", l + 1);
9291 emitcode ("mov", "%s,%s", buffer,
9292 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9295 freeAsmop (right, NULL, ic, TRUE);
9296 freeAsmop (result, NULL, ic, TRUE);
9299 /*-----------------------------------------------------------------*/
9300 /* genNearPointerSet - emitcode for near pointer put */
9301 /*-----------------------------------------------------------------*/
9303 genNearPointerSet (operand * right,
9310 sym_link *retype, *letype;
9311 sym_link *ptype = operandType (result);
9313 retype = getSpec (operandType (right));
9314 letype = getSpec (ptype);
9316 aopOp (result, ic, FALSE, FALSE);
9318 /* if the result is rematerializable &
9319 in data space & not a bit variable */
9320 if (AOP_TYPE (result) == AOP_IMMD &&
9321 DCL_TYPE (ptype) == POINTER &&
9322 !IS_BITVAR (retype) &&
9323 !IS_BITVAR (letype))
9325 genDataPointerSet (right, result, ic);
9329 /* if the value is already in a pointer register
9330 then don't need anything more */
9331 if (!AOP_INPREG (AOP (result)))
9333 /* otherwise get a free pointer register */
9335 preg = getFreePtr (ic, &aop, FALSE);
9336 emitcode ("mov", "%s,%s",
9338 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9342 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9344 freeAsmop (result, NULL, ic, TRUE);
9345 aopOp (right, ic, FALSE, FALSE);
9347 /* if bitfield then unpack the bits */
9348 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9349 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9352 /* we have can just get the values */
9353 int size = AOP_SIZE (right);
9358 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9362 emitcode ("mov", "@%s,a", rname);
9365 emitcode ("mov", "@%s,%s", rname, l);
9367 emitcode ("inc", "%s", rname);
9372 /* now some housekeeping stuff */
9375 /* we had to allocate for this iCode */
9376 freeAsmop (NULL, aop, ic, TRUE);
9380 /* we did not allocate which means left
9381 already in a pointer register, then
9382 if size > 0 && this could be used again
9383 we have to point it back to where it
9385 if (AOP_SIZE (right) > 1 &&
9386 !OP_SYMBOL (result)->remat &&
9387 (OP_SYMBOL (result)->liveTo > ic->seq ||
9390 int size = AOP_SIZE (right) - 1;
9392 emitcode ("dec", "%s", rname);
9397 freeAsmop (right, NULL, ic, TRUE);
9402 /*-----------------------------------------------------------------*/
9403 /* genPagedPointerSet - emitcode for Paged pointer put */
9404 /*-----------------------------------------------------------------*/
9406 genPagedPointerSet (operand * right,
9413 sym_link *retype, *letype;
9415 retype = getSpec (operandType (right));
9416 letype = getSpec (operandType (result));
9418 aopOp (result, ic, FALSE, FALSE);
9420 /* if the value is already in a pointer register
9421 then don't need anything more */
9422 if (!AOP_INPREG (AOP (result)))
9424 /* otherwise get a free pointer register */
9426 preg = getFreePtr (ic, &aop, FALSE);
9427 emitcode ("mov", "%s,%s",
9429 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9433 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9435 freeAsmop (result, NULL, ic, TRUE);
9436 aopOp (right, ic, FALSE, FALSE);
9438 /* if bitfield then unpack the bits */
9439 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9440 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9443 /* we have can just get the values */
9444 int size = AOP_SIZE (right);
9449 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9452 emitcode ("movx", "@%s,a", rname);
9455 emitcode ("inc", "%s", rname);
9461 /* now some housekeeping stuff */
9464 /* we had to allocate for this iCode */
9465 freeAsmop (NULL, aop, ic, TRUE);
9469 /* we did not allocate which means left
9470 already in a pointer register, then
9471 if size > 0 && this could be used again
9472 we have to point it back to where it
9474 if (AOP_SIZE (right) > 1 &&
9475 !OP_SYMBOL (result)->remat &&
9476 (OP_SYMBOL (result)->liveTo > ic->seq ||
9479 int size = AOP_SIZE (right) - 1;
9481 emitcode ("dec", "%s", rname);
9486 freeAsmop (right, NULL, ic, TRUE);
9491 /*-----------------------------------------------------------------*/
9492 /* genFarPointerSet - set value from far space */
9493 /*-----------------------------------------------------------------*/
9495 genFarPointerSet (operand * right,
9496 operand * result, iCode * ic)
9499 sym_link *retype = getSpec (operandType (right));
9500 sym_link *letype = getSpec (operandType (result));
9502 aopOp (result, ic, FALSE, FALSE);
9504 /* if the operand is already in dptr
9505 then we do nothing else we move the value to dptr */
9506 if (AOP_TYPE (result) != AOP_STR)
9508 /* if this is remateriazable */
9509 if (AOP_TYPE (result) == AOP_IMMD)
9510 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9513 /* we need to get it byte by byte */
9514 _startLazyDPSEvaluation ();
9515 if (AOP_TYPE (result) != AOP_DPTR)
9517 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9518 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9519 if (options.model == MODEL_FLAT24)
9520 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9524 /* We need to generate a load to DPTR indirect through DPTR. */
9525 D (emitcode (";", "genFarPointerSet -- indirection special case.");
9527 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9528 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9529 if (options.model == MODEL_FLAT24)
9530 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9531 emitcode ("pop", "dph");
9532 emitcode ("pop", "dpl");
9534 _endLazyDPSEvaluation ();
9537 /* so dptr know contains the address */
9538 freeAsmop (result, NULL, ic, TRUE);
9539 aopOp (right, ic, FALSE, TRUE);
9541 /* if bit then unpack */
9542 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9543 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9546 size = AOP_SIZE (right);
9549 _startLazyDPSEvaluation ();
9552 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9558 emitcode ("movx", "@dptr,a");
9560 emitcode ("inc", "dptr");
9562 _endLazyDPSEvaluation ();
9565 freeAsmop (right, NULL, ic, TRUE);
9568 /*-----------------------------------------------------------------*/
9569 /* genGenPointerSet - set value from generic pointer space */
9570 /*-----------------------------------------------------------------*/
9572 genGenPointerSet (operand * right,
9573 operand * result, iCode * ic)
9576 sym_link *retype = getSpec (operandType (right));
9577 sym_link *letype = getSpec (operandType (result));
9579 aopOp (result, ic, FALSE, TRUE);
9581 /* if the operand is already in dptr
9582 then we do nothing else we move the value to dptr */
9583 if (AOP_TYPE (result) != AOP_STR)
9585 _startLazyDPSEvaluation ();
9586 /* if this is remateriazable */
9587 if (AOP_TYPE (result) == AOP_IMMD)
9589 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9590 if (AOP(result)->aopu.aop_immd.from_cast_remat)
9591 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
9593 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9596 { /* we need to get it byte by byte */
9597 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9598 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9599 if (options.model == MODEL_FLAT24) {
9600 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9601 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9603 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9606 _endLazyDPSEvaluation ();
9608 /* so dptr know contains the address */
9609 freeAsmop (result, NULL, ic, TRUE);
9610 aopOp (right, ic, FALSE, TRUE);
9612 /* if bit then unpack */
9613 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9614 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9617 size = AOP_SIZE (right);
9620 _startLazyDPSEvaluation ();
9623 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9629 emitcode ("lcall", "__gptrput");
9631 emitcode ("inc", "dptr");
9633 _endLazyDPSEvaluation ();
9636 freeAsmop (right, NULL, ic, TRUE);
9639 /*-----------------------------------------------------------------*/
9640 /* genPointerSet - stores the value into a pointer location */
9641 /*-----------------------------------------------------------------*/
9643 genPointerSet (iCode * ic, iCode *pi)
9645 operand *right, *result;
9646 sym_link *type, *etype;
9649 D (emitcode (";", "genPointerSet ");
9652 right = IC_RIGHT (ic);
9653 result = IC_RESULT (ic);
9655 /* depending on the type of pointer we need to
9656 move it to the correct pointer register */
9657 type = operandType (result);
9658 etype = getSpec (type);
9659 /* if left is of type of pointer then it is simple */
9660 if (IS_PTR (type) && !IS_FUNC (type->next))
9662 p_type = DCL_TYPE (type);
9666 /* we have to go by the storage class */
9667 p_type = PTR_TYPE (SPEC_OCLS (etype));
9669 /* special case when cast remat */
9670 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9671 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9672 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9673 type = type = operandType (result);
9674 p_type = DCL_TYPE (type);
9677 /* now that we have the pointer type we assign
9678 the pointer values */
9684 genNearPointerSet (right, result, ic);
9688 genPagedPointerSet (right, result, ic);
9692 genFarPointerSet (right, result, ic);
9696 genGenPointerSet (right, result, ic);
9702 /*-----------------------------------------------------------------*/
9703 /* genIfx - generate code for Ifx statement */
9704 /*-----------------------------------------------------------------*/
9706 genIfx (iCode * ic, iCode * popIc)
9708 operand *cond = IC_COND (ic);
9711 D (emitcode (";", "genIfx "););
9713 aopOp (cond, ic, FALSE, FALSE);
9715 /* get the value into acc */
9716 if (AOP_TYPE (cond) != AOP_CRY)
9720 /* the result is now in the accumulator */
9721 freeAsmop (cond, NULL, ic, TRUE);
9723 /* if there was something to be popped then do it */
9727 /* if the condition is a bit variable */
9728 if (isbit && IS_ITEMP (cond) &&
9730 genIfxJump (ic, SPIL_LOC (cond)->rname);
9731 else if (isbit && !IS_ITEMP (cond))
9732 genIfxJump (ic, OP_SYMBOL (cond)->rname);
9734 genIfxJump (ic, "a");
9739 /*-----------------------------------------------------------------*/
9740 /* genAddrOf - generates code for address of */
9741 /*-----------------------------------------------------------------*/
9743 genAddrOf (iCode * ic)
9745 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9748 D (emitcode (";", "genAddrOf ");
9751 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9753 /* if the operand is on the stack then we
9754 need to get the stack offset of this
9758 /* if it has an offset then we need to compute
9762 emitcode ("mov", "a,_bp");
9763 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9764 aopPut (AOP (IC_RESULT (ic)), "a", 0);
9768 /* we can just move _bp */
9769 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9771 /* fill the result with zero */
9772 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9775 if (options.stack10bit && size < (FPTRSIZE - 1))
9778 "*** warning: pointer to stack var truncated.\n");
9785 if (options.stack10bit && offset == 2)
9787 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
9791 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9798 /* object not on stack then we need the name */
9799 size = AOP_SIZE (IC_RESULT (ic));
9804 char s[SDCC_NAME_MAX];
9806 sprintf (s, "#(%s >> %d)",
9810 sprintf (s, "#%s", sym->rname);
9811 aopPut (AOP (IC_RESULT (ic)), s, offset++);
9815 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9819 /*-----------------------------------------------------------------*/
9820 /* genArrayInit - generates code for address of */
9821 /*-----------------------------------------------------------------*/
9823 genArrayInit (iCode * ic)
9827 int elementSize = 0, eIndex;
9828 unsigned val, lastVal;
9830 operand *left=IC_LEFT(ic);
9832 D (emitcode (";", "genArrayInit "););
9834 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
9836 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
9838 // Load immediate value into DPTR.
9839 emitcode("mov", "dptr, %s",
9840 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
9842 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
9845 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9846 "Unexpected operand to genArrayInit.\n");
9849 // a regression because of SDCCcse.c:1.52
9850 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9851 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9852 if (options.model == MODEL_FLAT24)
9853 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9857 type = operandType(IC_LEFT(ic));
9859 if (type && type->next)
9861 elementSize = getSize(type->next);
9865 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9866 "can't determine element size in genArrayInit.\n");
9870 iLoop = IC_ARRAYILIST(ic);
9875 bool firstpass = TRUE;
9877 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
9878 iLoop->count, (int)iLoop->literalValue, elementSize);
9884 symbol *tlbl = NULL;
9886 count = ix > 256 ? 256 : ix;
9890 tlbl = newiTempLabel (NULL);
9891 if (firstpass || (count & 0xff))
9893 emitcode("mov", "b, #0x%x", count & 0xff);
9896 emitcode ("", "%05d$:", tlbl->key + 100);
9901 for (eIndex = 0; eIndex < elementSize; eIndex++)
9903 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
9906 emitcode("mov", "a, #0x%x", val);
9910 emitcode("movx", "@dptr, a");
9911 emitcode("inc", "dptr");
9916 emitcode("djnz", "b, %05d$", tlbl->key + 100);
9922 iLoop = iLoop->next;
9925 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
9928 /*-----------------------------------------------------------------*/
9929 /* genFarFarAssign - assignment when both are in far space */
9930 /*-----------------------------------------------------------------*/
9932 genFarFarAssign (operand * result, operand * right, iCode * ic)
9934 int size = AOP_SIZE (right);
9936 symbol *rSym = NULL;
9940 /* quick & easy case. */
9941 D(emitcode(";","genFarFarAssign (1 byte case)"););
9942 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9943 freeAsmop (right, NULL, ic, FALSE);
9944 /* now assign DPTR to result */
9946 aopOp(result, ic, FALSE, FALSE);
9948 aopPut(AOP(result), "a", 0);
9949 freeAsmop(result, NULL, ic, FALSE);
9953 /* See if we've got an underlying symbol to abuse. */
9954 if (IS_SYMOP(result) && OP_SYMBOL(result))
9956 if (IS_TRUE_SYMOP(result))
9958 rSym = OP_SYMBOL(result);
9960 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9962 rSym = OP_SYMBOL(result)->usl.spillLoc;
9966 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9968 /* We can use the '390 auto-toggle feature to good effect here. */
9970 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
9971 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
9972 emitcode ("mov", "dptr,#%s", rSym->rname);
9973 /* DP2 = result, DP1 = right, DP1 is current. */
9976 emitcode("movx", "a,@dptr");
9977 emitcode("movx", "@dptr,a");
9980 emitcode("inc", "dptr");
9981 emitcode("inc", "dptr");
9984 emitcode("mov", "dps, #0");
9985 freeAsmop (right, NULL, ic, FALSE);
9987 some alternative code for processors without auto-toggle
9988 no time to test now, so later well put in...kpb
9989 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
9990 emitcode("mov", "dps, #0x01"); /* Select DPTR2. */
9991 emitcode ("mov", "dptr,#%s", rSym->rname);
9992 /* DP2 = result, DP1 = right, DP1 is current. */
9996 emitcode("movx", "a,@dptr");
9998 emitcode("inc", "dptr");
9999 emitcode("inc", "dps");
10000 emitcode("movx", "@dptr,a");
10002 emitcode("inc", "dptr");
10003 emitcode("inc", "dps");
10005 emitcode("mov", "dps, #0");
10006 freeAsmop (right, NULL, ic, FALSE);
10011 D (emitcode (";", "genFarFarAssign"););
10012 aopOp (result, ic, TRUE, TRUE);
10014 _startLazyDPSEvaluation ();
10018 aopPut (AOP (result),
10019 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10022 _endLazyDPSEvaluation ();
10023 freeAsmop (result, NULL, ic, FALSE);
10024 freeAsmop (right, NULL, ic, FALSE);
10028 /*-----------------------------------------------------------------*/
10029 /* genAssign - generate code for assignment */
10030 /*-----------------------------------------------------------------*/
10032 genAssign (iCode * ic)
10034 operand *result, *right;
10036 unsigned long lit = 0L;
10038 D (emitcode (";", "genAssign ");
10041 result = IC_RESULT (ic);
10042 right = IC_RIGHT (ic);
10044 /* if they are the same */
10045 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10048 aopOp (right, ic, FALSE, FALSE);
10050 emitcode (";", "genAssign: resultIsFar = %s",
10051 isOperandInFarSpace (result) ?
10054 /* special case both in far space */
10055 if ((AOP_TYPE (right) == AOP_DPTR ||
10056 AOP_TYPE (right) == AOP_DPTR2) &&
10057 /* IS_TRUE_SYMOP(result) && */
10058 isOperandInFarSpace (result))
10060 genFarFarAssign (result, right, ic);
10064 aopOp (result, ic, TRUE, FALSE);
10066 /* if they are the same registers */
10067 if (sameRegs (AOP (right), AOP (result)))
10070 /* if the result is a bit */
10071 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10073 /* if the right size is a literal then
10074 we know what the value is */
10075 if (AOP_TYPE (right) == AOP_LIT)
10077 if (((int) operandLitValue (right)))
10078 aopPut (AOP (result), one, 0);
10080 aopPut (AOP (result), zero, 0);
10084 /* the right is also a bit variable */
10085 if (AOP_TYPE (right) == AOP_CRY)
10087 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10088 aopPut (AOP (result), "c", 0);
10092 /* we need to or */
10094 aopPut (AOP (result), "a", 0);
10098 /* bit variables done */
10100 size = AOP_SIZE (result);
10102 if (AOP_TYPE (right) == AOP_LIT)
10103 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10106 (AOP_TYPE (result) != AOP_REG) &&
10107 (AOP_TYPE (right) == AOP_LIT) &&
10108 !IS_FLOAT (operandType (right)))
10110 _startLazyDPSEvaluation ();
10111 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10113 aopPut (AOP (result),
10114 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10119 /* And now fill the rest with zeros. */
10122 emitcode ("clr", "a");
10126 aopPut (AOP (result), "a", offset++);
10128 _endLazyDPSEvaluation ();
10132 _startLazyDPSEvaluation ();
10135 aopPut (AOP (result),
10136 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10140 _endLazyDPSEvaluation ();
10144 freeAsmop (right, NULL, ic, FALSE);
10145 freeAsmop (result, NULL, ic, TRUE);
10148 /*-----------------------------------------------------------------*/
10149 /* genJumpTab - generates code for jump table */
10150 /*-----------------------------------------------------------------*/
10152 genJumpTab (iCode * ic)
10157 D (emitcode (";", "genJumpTab ");
10160 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10161 /* get the condition into accumulator */
10162 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10164 /* multiply by four! */
10165 emitcode ("add", "a,acc");
10166 emitcode ("add", "a,acc");
10167 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10169 jtab = newiTempLabel (NULL);
10170 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10171 emitcode ("jmp", "@a+dptr");
10172 emitcode ("", "%05d$:", jtab->key + 100);
10173 /* now generate the jump labels */
10174 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10175 jtab = setNextItem (IC_JTLABELS (ic)))
10176 emitcode ("ljmp", "%05d$", jtab->key + 100);
10180 /*-----------------------------------------------------------------*/
10181 /* genCast - gen code for casting */
10182 /*-----------------------------------------------------------------*/
10184 genCast (iCode * ic)
10186 operand *result = IC_RESULT (ic);
10187 sym_link *ctype = operandType (IC_LEFT (ic));
10188 sym_link *rtype = operandType (IC_RIGHT (ic));
10189 operand *right = IC_RIGHT (ic);
10192 D (emitcode (";", "genCast ");
10195 /* if they are equivalent then do nothing */
10196 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10199 aopOp (right, ic, FALSE, FALSE);
10200 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10202 /* if the result is a bit */
10203 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10204 if (IS_BITVAR(OP_SYMBOL(result)->type))
10206 /* if the right size is a literal then
10207 we know what the value is */
10208 if (AOP_TYPE (right) == AOP_LIT)
10210 if (((int) operandLitValue (right)))
10211 aopPut (AOP (result), one, 0);
10213 aopPut (AOP (result), zero, 0);
10218 /* the right is also a bit variable */
10219 if (AOP_TYPE (right) == AOP_CRY)
10221 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10222 aopPut (AOP (result), "c", 0);
10226 /* we need to or */
10228 aopPut (AOP (result), "a", 0);
10232 /* if they are the same size : or less */
10233 if (AOP_SIZE (result) <= AOP_SIZE (right))
10236 /* if they are in the same place */
10237 if (sameRegs (AOP (right), AOP (result)))
10240 /* if they in different places then copy */
10241 size = AOP_SIZE (result);
10243 _startLazyDPSEvaluation ();
10246 aopPut (AOP (result),
10247 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10251 _endLazyDPSEvaluation ();
10256 /* if the result is of type pointer */
10257 if (IS_PTR (ctype))
10261 sym_link *type = operandType (right);
10263 /* pointer to generic pointer */
10264 if (IS_GENPTR (ctype))
10270 p_type = DCL_TYPE (type);
10274 #if OLD_CAST_BEHAVIOR
10275 /* KV: we are converting a non-pointer type to
10276 * a generic pointer. This (ifdef'd out) code
10277 * says that the resulting generic pointer
10278 * should have the same class as the storage
10279 * location of the non-pointer variable.
10281 * For example, converting an int (which happens
10282 * to be stored in DATA space) to a pointer results
10283 * in a DATA generic pointer; if the original int
10284 * in XDATA space, so will be the resulting pointer.
10286 * I don't like that behavior, and thus this change:
10287 * all such conversions will be forced to XDATA and
10288 * throw a warning. If you want some non-XDATA
10289 * type, or you want to suppress the warning, you
10290 * must go through an intermediate cast, like so:
10292 * char _generic *gp = (char _xdata *)(intVar);
10294 sym_link *etype = getSpec (type);
10296 /* we have to go by the storage class */
10297 if (SPEC_OCLS (etype) != generic)
10299 p_type = PTR_TYPE (SPEC_OCLS (etype));
10304 /* Converting unknown class (i.e. register variable)
10305 * to generic pointer. This is not good, but
10306 * we'll make a guess (and throw a warning).
10309 werror (W_INT_TO_GEN_PTR_CAST);
10313 /* the first two bytes are known */
10314 size = GPTRSIZE - 1;
10316 _startLazyDPSEvaluation ();
10319 aopPut (AOP (result),
10320 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10324 _endLazyDPSEvaluation ();
10326 /* the last byte depending on type */
10344 /* this should never happen */
10345 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10346 "got unknown pointer type");
10349 aopPut (AOP (result), l, GPTRSIZE - 1);
10353 /* just copy the pointers */
10354 size = AOP_SIZE (result);
10356 _startLazyDPSEvaluation ();
10359 aopPut (AOP (result),
10360 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10364 _endLazyDPSEvaluation ();
10368 /* so we now know that the size of destination is greater
10369 than the size of the source */
10370 /* we move to result for the size of source */
10371 size = AOP_SIZE (right);
10373 _startLazyDPSEvaluation ();
10376 aopPut (AOP (result),
10377 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10381 _endLazyDPSEvaluation ();
10383 /* now depending on the sign of the source && destination */
10384 size = AOP_SIZE (result) - AOP_SIZE (right);
10385 /* if unsigned or not an integral type */
10386 /* also, if the source is a bit, we don't need to sign extend, because
10387 * it can't possibly have set the sign bit.
10389 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10393 aopPut (AOP (result), zero, offset++);
10398 /* we need to extend the sign :{ */
10399 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10400 FALSE, FALSE, TRUE);
10402 emitcode ("rlc", "a");
10403 emitcode ("subb", "a,acc");
10405 aopPut (AOP (result), "a", offset++);
10408 /* we are done hurray !!!! */
10411 freeAsmop (right, NULL, ic, TRUE);
10412 freeAsmop (result, NULL, ic, TRUE);
10416 /*-----------------------------------------------------------------*/
10417 /* genDjnz - generate decrement & jump if not zero instrucion */
10418 /*-----------------------------------------------------------------*/
10420 genDjnz (iCode * ic, iCode * ifx)
10422 symbol *lbl, *lbl1;
10426 /* if the if condition has a false label
10427 then we cannot save */
10428 if (IC_FALSE (ifx))
10431 /* if the minus is not of the form
10433 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10434 !IS_OP_LITERAL (IC_RIGHT (ic)))
10437 if (operandLitValue (IC_RIGHT (ic)) != 1)
10440 /* if the size of this greater than one then no
10442 if (getSize (operandType (IC_RESULT (ic))) > 1)
10445 /* otherwise we can save BIG */
10446 D(emitcode(";", "genDjnz"););
10448 lbl = newiTempLabel (NULL);
10449 lbl1 = newiTempLabel (NULL);
10451 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10453 if (AOP_NEEDSACC(IC_RESULT(ic)))
10455 /* If the result is accessed indirectly via
10456 * the accumulator, we must explicitly write
10457 * it back after the decrement.
10459 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10461 if (strcmp(rByte, "a"))
10463 /* Something is hopelessly wrong */
10464 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10465 __FILE__, __LINE__);
10466 /* We can just give up; the generated code will be inefficient,
10467 * but what the hey.
10469 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10472 emitcode ("dec", "%s", rByte);
10473 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10474 emitcode ("jnz", "%05d$", lbl->key + 100);
10476 else if (IS_AOP_PREG (IC_RESULT (ic)))
10478 emitcode ("dec", "%s",
10479 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10480 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10481 emitcode ("jnz", "%05d$", lbl->key + 100);
10485 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10488 emitcode ("sjmp", "%05d$", lbl1->key + 100);
10489 emitcode ("", "%05d$:", lbl->key + 100);
10490 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10491 emitcode ("", "%05d$:", lbl1->key + 100);
10493 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10494 ifx->generated = 1;
10498 /*-----------------------------------------------------------------*/
10499 /* genReceive - generate code for a receive iCode */
10500 /*-----------------------------------------------------------------*/
10502 genReceive (iCode * ic)
10505 D (emitcode (";", "genReceive ");
10508 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10509 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10510 IS_TRUE_SYMOP (IC_RESULT (ic))))
10512 int size = getSize (operandType (IC_RESULT (ic)));
10513 int offset = fReturnSizeDS390 - size;
10516 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10517 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10520 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10521 size = AOP_SIZE (IC_RESULT (ic));
10525 emitcode ("pop", "acc");
10526 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10533 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10535 assignResultValue (IC_RESULT (ic));
10538 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10541 /*-----------------------------------------------------------------*/
10542 /* gen390Code - generate code for Dallas 390 based controllers */
10543 /*-----------------------------------------------------------------*/
10545 gen390Code (iCode * lic)
10550 lineHead = lineCurr = NULL;
10552 if (options.model == MODEL_FLAT24) {
10553 fReturnSizeDS390 = 5;
10554 fReturn = fReturn24;
10556 fReturnSizeDS390 = 4;
10557 fReturn = fReturn16;
10558 options.stack10bit=0;
10562 /* print the allocation information */
10564 printAllocInfo (currFunc, codeOutFile);
10566 /* if debug information required */
10567 if (options.debug && currFunc)
10569 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
10571 if (IS_STATIC (currFunc->etype))
10572 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
10574 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
10577 /* stack pointer name */
10578 if (options.useXstack)
10584 for (ic = lic; ic; ic = ic->next)
10587 if (cln != ic->lineno)
10592 emitcode ("", "C$%s$%d$%d$%d ==.",
10593 FileBaseName (ic->filename), ic->lineno,
10594 ic->level, ic->block);
10597 emitcode (";", "%s %d", ic->filename, ic->lineno);
10600 /* if the result is marked as
10601 spilt and rematerializable or code for
10602 this has already been generated then
10604 if (resultRemat (ic) || ic->generated)
10607 /* depending on the operation */
10627 /* IPOP happens only when trying to restore a
10628 spilt live range, if there is an ifx statement
10629 following this pop then the if statement might
10630 be using some of the registers being popped which
10631 would destory the contents of the register so
10632 we need to check for this condition and handle it */
10634 ic->next->op == IFX &&
10635 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10636 genIfx (ic->next, ic);
10654 genEndFunction (ic);
10674 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10691 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10695 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10702 /* note these two are xlated by algebraic equivalence
10703 during parsing SDCC.y */
10704 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10705 "got '>=' or '<=' shouldn't have come here");
10709 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10721 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10725 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10729 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10753 genRightShift (ic);
10756 case GET_VALUE_AT_ADDRESS:
10757 genPointerGet (ic,hasInc(IC_LEFT(ic),ic));
10761 if (POINTER_SET (ic))
10762 genPointerSet (ic,hasInc(IC_RESULT(ic),ic));
10788 addSet (&_G.sendSet, ic);
10801 /* now we are ready to call the
10802 peep hole optimizer */
10803 if (!options.nopeep)
10804 peepHole (&lineHead);
10806 /* now do the actual printing */
10807 printLine (lineHead, codeOutFile);