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 /* genAndOp - for && operation */
5378 /*-----------------------------------------------------------------*/
5380 genAndOp (iCode * ic)
5382 operand *left, *right, *result;
5385 D (emitcode (";", "genAndOp "););
5387 /* note here that && operations that are in an
5388 if statement are taken away by backPatchLabels
5389 only those used in arthmetic operations remain */
5391 AOP_SET_LOCALS (ic);
5393 /* if both are bit variables */
5394 if (AOP_TYPE (left) == AOP_CRY &&
5395 AOP_TYPE (right) == AOP_CRY)
5397 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5398 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5399 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5400 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5402 aopOp (result,ic,FALSE, FALSE);
5407 tlbl = newiTempLabel (NULL);
5409 emitcode ("jz", "%05d$", tlbl->key + 100);
5411 emitcode ("", "%05d$:", tlbl->key + 100);
5412 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5413 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5415 aopOp (result,ic,FALSE, FALSE);
5418 freeAsmop (result, NULL, ic, TRUE);
5422 /*-----------------------------------------------------------------*/
5423 /* genOrOp - for || operation */
5424 /*-----------------------------------------------------------------*/
5426 genOrOp (iCode * ic)
5428 operand *left, *right, *result;
5431 D (emitcode (";", "genOrOp "););
5433 /* note here that || operations that are in an
5434 if statement are taken away by backPatchLabels
5435 only those used in arthmetic operations remain */
5437 AOP_SET_LOCALS (ic);
5439 /* if both are bit variables */
5440 if (AOP_TYPE (left) == AOP_CRY &&
5441 AOP_TYPE (right) == AOP_CRY)
5443 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5444 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5445 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5446 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5448 aopOp (result,ic,FALSE, FALSE);
5454 tlbl = newiTempLabel (NULL);
5456 emitcode ("jnz", "%05d$", tlbl->key + 100);
5458 emitcode ("", "%05d$:", tlbl->key + 100);
5459 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5460 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5462 aopOp (result,ic,FALSE, FALSE);
5467 freeAsmop (result, NULL, ic, TRUE);
5470 /*-----------------------------------------------------------------*/
5471 /* isLiteralBit - test if lit == 2^n */
5472 /*-----------------------------------------------------------------*/
5474 isLiteralBit (unsigned long lit)
5476 unsigned long pw[32] =
5477 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5478 0x100L, 0x200L, 0x400L, 0x800L,
5479 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5480 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5481 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5482 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5483 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5486 for (idx = 0; idx < 32; idx++)
5492 /*-----------------------------------------------------------------*/
5493 /* continueIfTrue - */
5494 /*-----------------------------------------------------------------*/
5496 continueIfTrue (iCode * ic)
5499 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5503 /*-----------------------------------------------------------------*/
5505 /*-----------------------------------------------------------------*/
5507 jumpIfTrue (iCode * ic)
5510 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5514 /*-----------------------------------------------------------------*/
5515 /* jmpTrueOrFalse - */
5516 /*-----------------------------------------------------------------*/
5518 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5520 // ugly but optimized by peephole
5523 symbol *nlbl = newiTempLabel (NULL);
5524 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5525 emitcode ("", "%05d$:", tlbl->key + 100);
5526 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5527 emitcode ("", "%05d$:", nlbl->key + 100);
5531 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5532 emitcode ("", "%05d$:", tlbl->key + 100);
5537 // Generate code to perform a bit-wise logic operation
5538 // on two operands in far space (assumed to already have been
5539 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5540 // in far space. This requires pushing the result on the stack
5541 // then popping it into the result.
5543 genFarFarLogicOp(iCode *ic, char *logicOp)
5545 int size, resultSize, compSize;
5549 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5550 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5551 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5553 _startLazyDPSEvaluation();
5554 for (size = compSize; (size--); offset++)
5556 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5557 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5558 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5560 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5561 emitcode ("push", "acc");
5563 _endLazyDPSEvaluation();
5565 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5566 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5567 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5569 resultSize = AOP_SIZE(IC_RESULT(ic));
5571 ADJUST_PUSHED_RESULT(compSize, resultSize);
5573 _startLazyDPSEvaluation();
5576 emitcode ("pop", "acc");
5577 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5579 _endLazyDPSEvaluation();
5580 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5584 /*-----------------------------------------------------------------*/
5585 /* genAnd - code for and */
5586 /*-----------------------------------------------------------------*/
5588 genAnd (iCode * ic, iCode * ifx)
5590 operand *left, *right, *result;
5591 int size, offset = 0;
5592 unsigned long lit = 0L;
5597 D (emitcode (";", "genAnd "););
5599 AOP_OP_3_NOFATAL (ic, pushResult);
5600 AOP_SET_LOCALS (ic);
5604 genFarFarLogicOp(ic, "anl");
5609 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5611 AOP_TYPE (left), AOP_TYPE (right));
5612 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5614 AOP_SIZE (left), AOP_SIZE (right));
5617 /* if left is a literal & right is not then exchange them */
5618 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5619 #ifdef LOGIC_OPS_BROKEN
5620 || AOP_NEEDSACC (left)
5624 operand *tmp = right;
5629 /* if result = right then exchange them */
5630 if (sameRegs (AOP (result), AOP (right)))
5632 operand *tmp = right;
5637 /* if right is bit then exchange them */
5638 if (AOP_TYPE (right) == AOP_CRY &&
5639 AOP_TYPE (left) != AOP_CRY)
5641 operand *tmp = right;
5645 if (AOP_TYPE (right) == AOP_LIT)
5646 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5648 size = AOP_SIZE (result);
5651 // result = bit & yy;
5652 if (AOP_TYPE (left) == AOP_CRY)
5654 // c = bit & literal;
5655 if (AOP_TYPE (right) == AOP_LIT)
5659 if (size && sameRegs (AOP (result), AOP (left)))
5662 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5667 if (size && (AOP_TYPE (result) == AOP_CRY))
5669 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5672 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5677 emitcode ("clr", "c");
5682 if (AOP_TYPE (right) == AOP_CRY)
5685 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5686 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5691 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5693 emitcode ("rrc", "a");
5694 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5702 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5703 genIfxJump (ifx, "c");
5707 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5708 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5709 if ((AOP_TYPE (right) == AOP_LIT) &&
5710 (AOP_TYPE (result) == AOP_CRY) &&
5711 (AOP_TYPE (left) != AOP_CRY))
5713 int posbit = isLiteralBit (lit);
5718 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5721 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5727 sprintf (buffer, "acc.%d", posbit & 0x07);
5728 genIfxJump (ifx, buffer);
5735 symbol *tlbl = newiTempLabel (NULL);
5736 int sizel = AOP_SIZE (left);
5738 emitcode ("setb", "c");
5741 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5743 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5745 if ((posbit = isLiteralBit (bytelit)) != 0)
5746 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5749 if (bytelit != 0x0FFL)
5750 emitcode ("anl", "a,%s",
5751 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5752 emitcode ("jnz", "%05d$", tlbl->key + 100);
5757 // bit = left & literal
5760 emitcode ("clr", "c");
5761 emitcode ("", "%05d$:", tlbl->key + 100);
5763 // if(left & literal)
5767 jmpTrueOrFalse (ifx, tlbl);
5775 /* if left is same as result */
5776 if (sameRegs (AOP (result), AOP (left)))
5778 for (; size--; offset++)
5780 if (AOP_TYPE (right) == AOP_LIT)
5782 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5784 else if (bytelit == 0)
5785 aopPut (AOP (result), zero, offset);
5786 else if (IS_AOP_PREG (result))
5788 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5789 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5790 aopPut (AOP (result), "a", offset);
5793 emitcode ("anl", "%s,%s",
5794 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5795 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5799 if (AOP_TYPE (left) == AOP_ACC)
5800 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5803 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5804 if (IS_AOP_PREG (result))
5806 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5807 aopPut (AOP (result), "a", offset);
5811 emitcode ("anl", "%s,a",
5812 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5819 // left & result in different registers
5820 if (AOP_TYPE (result) == AOP_CRY)
5823 // if(size), result in bit
5824 // if(!size && ifx), conditional oper: if(left & right)
5825 symbol *tlbl = newiTempLabel (NULL);
5826 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5828 emitcode ("setb", "c");
5831 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5832 emitcode ("anl", "a,%s",
5833 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5835 if (AOP_TYPE(left)==AOP_ACC) {
5836 emitcode("mov", "b,a");
5837 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5838 emitcode("anl", "a,b");
5840 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5841 emitcode ("anl", "a,%s",
5842 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5845 emitcode ("jnz", "%05d$", tlbl->key + 100);
5851 emitcode ("", "%05d$:", tlbl->key + 100);
5855 jmpTrueOrFalse (ifx, tlbl);
5859 for (; (size--); offset++)
5862 // result = left & right
5863 if (AOP_TYPE (right) == AOP_LIT)
5865 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5867 aopPut (AOP (result),
5868 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5872 else if (bytelit == 0)
5874 aopPut (AOP (result), zero, offset);
5877 D (emitcode (";", "better literal AND."););
5878 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5879 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5880 FALSE, FALSE, FALSE));
5885 // faster than result <- left, anl result,right
5886 // and better if result is SFR
5887 if (AOP_TYPE (left) == AOP_ACC)
5889 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5890 FALSE, FALSE, FALSE));
5894 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
5895 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
5897 emitcode("mov", "b,a");
5901 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5902 emitcode ("anl", "a,%s", rOp);
5905 aopPut (AOP (result), "a", offset);
5911 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5912 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5913 freeAsmop (result, NULL, ic, TRUE);
5917 /*-----------------------------------------------------------------*/
5918 /* genOr - code for or */
5919 /*-----------------------------------------------------------------*/
5921 genOr (iCode * ic, iCode * ifx)
5923 operand *left, *right, *result;
5924 int size, offset = 0;
5925 unsigned long lit = 0L;
5928 D (emitcode (";", "genOr "););
5930 AOP_OP_3_NOFATAL (ic, pushResult);
5931 AOP_SET_LOCALS (ic);
5935 genFarFarLogicOp(ic, "orl");
5941 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5943 AOP_TYPE (left), AOP_TYPE (right));
5944 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5946 AOP_SIZE (left), AOP_SIZE (right));
5949 /* if left is a literal & right is not then exchange them */
5950 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5951 #ifdef LOGIC_OPS_BROKEN
5952 || AOP_NEEDSACC (left) // I think this is a net loss now.
5956 operand *tmp = right;
5961 /* if result = right then exchange them */
5962 if (sameRegs (AOP (result), AOP (right)))
5964 operand *tmp = right;
5969 /* if right is bit then exchange them */
5970 if (AOP_TYPE (right) == AOP_CRY &&
5971 AOP_TYPE (left) != AOP_CRY)
5973 operand *tmp = right;
5977 if (AOP_TYPE (right) == AOP_LIT)
5978 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5980 size = AOP_SIZE (result);
5984 if (AOP_TYPE (left) == AOP_CRY)
5986 if (AOP_TYPE (right) == AOP_LIT)
5988 // c = bit & literal;
5991 // lit != 0 => result = 1
5992 if (AOP_TYPE (result) == AOP_CRY)
5995 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5997 continueIfTrue (ifx);
6000 emitcode ("setb", "c");
6004 // lit == 0 => result = left
6005 if (size && sameRegs (AOP (result), AOP (left)))
6007 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6012 if (AOP_TYPE (right) == AOP_CRY)
6015 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6016 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6021 symbol *tlbl = newiTempLabel (NULL);
6022 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6023 emitcode ("setb", "c");
6024 emitcode ("jb", "%s,%05d$",
6025 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6027 emitcode ("jnz", "%05d$", tlbl->key + 100);
6028 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6030 jmpTrueOrFalse (ifx, tlbl);
6036 emitcode ("", "%05d$:", tlbl->key + 100);
6045 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6046 genIfxJump (ifx, "c");
6050 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6051 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6052 if ((AOP_TYPE (right) == AOP_LIT) &&
6053 (AOP_TYPE (result) == AOP_CRY) &&
6054 (AOP_TYPE (left) != AOP_CRY))
6060 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6062 continueIfTrue (ifx);
6067 // lit = 0, result = boolean(left)
6069 emitcode ("setb", "c");
6073 symbol *tlbl = newiTempLabel (NULL);
6074 emitcode ("jnz", "%05d$", tlbl->key + 100);
6076 emitcode ("", "%05d$:", tlbl->key + 100);
6080 genIfxJump (ifx, "a");
6088 /* if left is same as result */
6089 if (sameRegs (AOP (result), AOP (left)))
6091 for (; size--; offset++)
6093 if (AOP_TYPE (right) == AOP_LIT)
6095 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6101 if (IS_AOP_PREG (left))
6103 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6104 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6105 aopPut (AOP (result), "a", offset);
6109 emitcode ("orl", "%s,%s",
6110 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6111 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6117 if (AOP_TYPE (left) == AOP_ACC)
6119 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6123 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6124 if (IS_AOP_PREG (left))
6126 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6127 aopPut (AOP (result), "a", offset);
6131 emitcode ("orl", "%s,a",
6132 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6140 // left & result in different registers
6141 if (AOP_TYPE (result) == AOP_CRY)
6144 // if(size), result in bit
6145 // if(!size && ifx), conditional oper: if(left | right)
6146 symbol *tlbl = newiTempLabel (NULL);
6147 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6149 emitcode ("setb", "c");
6152 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6153 emitcode ("orl", "a,%s",
6154 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6156 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6157 emitcode ("orl", "a,%s",
6158 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6160 emitcode ("jnz", "%05d$", tlbl->key + 100);
6166 emitcode ("", "%05d$:", tlbl->key + 100);
6170 jmpTrueOrFalse (ifx, tlbl);
6174 _startLazyDPSEvaluation();
6175 for (; (size--); offset++)
6178 // result = left & right
6179 if (AOP_TYPE (right) == AOP_LIT)
6181 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6183 aopPut (AOP (result),
6184 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6188 D (emitcode (";", "better literal OR."););
6189 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6190 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6191 FALSE, FALSE, FALSE));
6196 // faster than result <- left, anl result,right
6197 // and better if result is SFR
6198 if (AOP_TYPE (left) == AOP_ACC)
6200 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6201 FALSE, FALSE, FALSE));
6205 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6207 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6209 emitcode("mov", "b,a");
6213 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6214 emitcode ("orl", "a,%s", rOp);
6217 aopPut (AOP (result), "a", offset);
6219 _endLazyDPSEvaluation();
6224 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6225 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6226 freeAsmop (result, NULL, ic, TRUE);
6229 /*-----------------------------------------------------------------*/
6230 /* genXor - code for xclusive or */
6231 /*-----------------------------------------------------------------*/
6233 genXor (iCode * ic, iCode * ifx)
6235 operand *left, *right, *result;
6236 int size, offset = 0;
6237 unsigned long lit = 0L;
6240 D (emitcode (";", "genXor "););
6242 AOP_OP_3_NOFATAL (ic, pushResult);
6243 AOP_SET_LOCALS (ic);
6247 genFarFarLogicOp(ic, "xrl");
6252 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6254 AOP_TYPE (left), AOP_TYPE (right));
6255 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6257 AOP_SIZE (left), AOP_SIZE (right));
6260 /* if left is a literal & right is not ||
6261 if left needs acc & right does not */
6262 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6263 #ifdef LOGIC_OPS_BROKEN
6264 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6268 operand *tmp = right;
6273 /* if result = right then exchange them */
6274 if (sameRegs (AOP (result), AOP (right)))
6276 operand *tmp = right;
6281 /* if right is bit then exchange them */
6282 if (AOP_TYPE (right) == AOP_CRY &&
6283 AOP_TYPE (left) != AOP_CRY)
6285 operand *tmp = right;
6289 if (AOP_TYPE (right) == AOP_LIT)
6290 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6292 size = AOP_SIZE (result);
6296 if (AOP_TYPE (left) == AOP_CRY)
6298 if (AOP_TYPE (right) == AOP_LIT)
6300 // c = bit & literal;
6303 // lit>>1 != 0 => result = 1
6304 if (AOP_TYPE (result) == AOP_CRY)
6307 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6309 continueIfTrue (ifx);
6312 emitcode ("setb", "c");
6319 // lit == 0, result = left
6320 if (size && sameRegs (AOP (result), AOP (left)))
6322 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6326 // lit == 1, result = not(left)
6327 if (size && sameRegs (AOP (result), AOP (left)))
6329 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6334 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6335 emitcode ("cpl", "c");
6344 symbol *tlbl = newiTempLabel (NULL);
6345 if (AOP_TYPE (right) == AOP_CRY)
6348 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6352 int sizer = AOP_SIZE (right);
6354 // if val>>1 != 0, result = 1
6355 emitcode ("setb", "c");
6358 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6360 // test the msb of the lsb
6361 emitcode ("anl", "a,#0xfe");
6362 emitcode ("jnz", "%05d$", tlbl->key + 100);
6366 emitcode ("rrc", "a");
6368 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6369 emitcode ("cpl", "c");
6370 emitcode ("", "%05d$:", (tlbl->key + 100));
6377 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6378 genIfxJump (ifx, "c");
6382 if (sameRegs (AOP (result), AOP (left)))
6384 /* if left is same as result */
6385 for (; size--; offset++)
6387 if (AOP_TYPE (right) == AOP_LIT)
6389 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6391 else if (IS_AOP_PREG (left))
6393 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6394 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6395 aopPut (AOP (result), "a", offset);
6398 emitcode ("xrl", "%s,%s",
6399 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6400 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6404 if (AOP_TYPE (left) == AOP_ACC)
6405 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6408 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6409 if (IS_AOP_PREG (left))
6411 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6412 aopPut (AOP (result), "a", offset);
6415 emitcode ("xrl", "%s,a",
6416 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6423 // left & result in different registers
6424 if (AOP_TYPE (result) == AOP_CRY)
6427 // if(size), result in bit
6428 // if(!size && ifx), conditional oper: if(left ^ right)
6429 symbol *tlbl = newiTempLabel (NULL);
6430 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6432 emitcode ("setb", "c");
6435 if ((AOP_TYPE (right) == AOP_LIT) &&
6436 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6438 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6442 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6443 emitcode ("xrl", "a,%s",
6444 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6446 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6447 emitcode ("xrl", "a,%s",
6448 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6451 emitcode ("jnz", "%05d$", tlbl->key + 100);
6457 emitcode ("", "%05d$:", tlbl->key + 100);
6461 jmpTrueOrFalse (ifx, tlbl);
6464 for (; (size--); offset++)
6467 // result = left & right
6468 if (AOP_TYPE (right) == AOP_LIT)
6470 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6472 aopPut (AOP (result),
6473 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6477 D (emitcode (";", "better literal XOR.");
6479 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6480 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6481 FALSE, FALSE, FALSE));
6485 // faster than result <- left, anl result,right
6486 // and better if result is SFR
6487 if (AOP_TYPE (left) == AOP_ACC)
6489 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6490 FALSE, FALSE, FALSE));
6494 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6495 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6497 emitcode("mov", "b,a");
6501 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6502 emitcode ("xrl", "a,%s", rOp);
6505 aopPut (AOP (result), "a", offset);
6510 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6511 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6512 freeAsmop (result, NULL, ic, TRUE);
6515 /*-----------------------------------------------------------------*/
6516 /* genInline - write the inline code out */
6517 /*-----------------------------------------------------------------*/
6519 genInline (iCode * ic)
6521 char *buffer, *bp, *bp1;
6523 D (emitcode (";", "genInline ");
6526 _G.inLine += (!options.asmpeep);
6528 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6529 strcpy (buffer, IC_INLINE (ic));
6531 /* emit each line as a code */
6556 /* emitcode("",buffer); */
6557 _G.inLine -= (!options.asmpeep);
6560 /*-----------------------------------------------------------------*/
6561 /* genRRC - rotate right with carry */
6562 /*-----------------------------------------------------------------*/
6566 operand *left, *result;
6567 int size, offset = 0;
6570 D (emitcode (";", "genRRC ");
6573 /* rotate right with carry */
6574 left = IC_LEFT (ic);
6575 result = IC_RESULT (ic);
6576 aopOp (left, ic, FALSE, FALSE);
6577 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6579 /* move it to the result */
6580 size = AOP_SIZE (result);
6584 _startLazyDPSEvaluation ();
6587 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6589 emitcode ("rrc", "a");
6590 if (AOP_SIZE (result) > 1)
6591 aopPut (AOP (result), "a", offset--);
6593 _endLazyDPSEvaluation ();
6595 /* now we need to put the carry into the
6596 highest order byte of the result */
6597 if (AOP_SIZE (result) > 1)
6599 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6602 emitcode ("mov", "acc.7,c");
6603 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6604 freeAsmop (left, NULL, ic, TRUE);
6605 freeAsmop (result, NULL, ic, TRUE);
6608 /*-----------------------------------------------------------------*/
6609 /* genRLC - generate code for rotate left with carry */
6610 /*-----------------------------------------------------------------*/
6614 operand *left, *result;
6615 int size, offset = 0;
6618 D (emitcode (";", "genRLC ");
6621 /* rotate right with carry */
6622 left = IC_LEFT (ic);
6623 result = IC_RESULT (ic);
6624 aopOp (left, ic, FALSE, FALSE);
6625 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6627 /* move it to the result */
6628 size = AOP_SIZE (result);
6632 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6634 emitcode ("add", "a,acc");
6635 if (AOP_SIZE (result) > 1)
6637 aopPut (AOP (result), "a", offset++);
6640 _startLazyDPSEvaluation ();
6643 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6645 emitcode ("rlc", "a");
6646 if (AOP_SIZE (result) > 1)
6647 aopPut (AOP (result), "a", offset++);
6649 _endLazyDPSEvaluation ();
6651 /* now we need to put the carry into the
6652 highest order byte of the result */
6653 if (AOP_SIZE (result) > 1)
6655 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6658 emitcode ("mov", "acc.0,c");
6659 aopPut (AOP (result), "a", 0);
6660 freeAsmop (left, NULL, ic, TRUE);
6661 freeAsmop (result, NULL, ic, TRUE);
6664 /*-----------------------------------------------------------------*/
6665 /* genGetHbit - generates code get highest order bit */
6666 /*-----------------------------------------------------------------*/
6668 genGetHbit (iCode * ic)
6670 operand *left, *result;
6671 left = IC_LEFT (ic);
6672 result = IC_RESULT (ic);
6673 aopOp (left, ic, FALSE, FALSE);
6674 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6676 D (emitcode (";", "genGetHbit ");
6679 /* get the highest order byte into a */
6680 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6681 if (AOP_TYPE (result) == AOP_CRY)
6683 emitcode ("rlc", "a");
6688 emitcode ("rl", "a");
6689 emitcode ("anl", "a,#0x01");
6694 freeAsmop (left, NULL, ic, TRUE);
6695 freeAsmop (result, NULL, ic, TRUE);
6698 /*-----------------------------------------------------------------*/
6699 /* AccRol - rotate left accumulator by known count */
6700 /*-----------------------------------------------------------------*/
6702 AccRol (int shCount)
6704 shCount &= 0x0007; // shCount : 0..7
6711 emitcode ("rl", "a");
6714 emitcode ("rl", "a");
6715 emitcode ("rl", "a");
6718 emitcode ("swap", "a");
6719 emitcode ("rr", "a");
6722 emitcode ("swap", "a");
6725 emitcode ("swap", "a");
6726 emitcode ("rl", "a");
6729 emitcode ("rr", "a");
6730 emitcode ("rr", "a");
6733 emitcode ("rr", "a");
6738 /*-----------------------------------------------------------------*/
6739 /* AccLsh - left shift accumulator by known count */
6740 /*-----------------------------------------------------------------*/
6742 AccLsh (int shCount)
6747 emitcode ("add", "a,acc");
6748 else if (shCount == 2)
6750 emitcode ("add", "a,acc");
6751 emitcode ("add", "a,acc");
6755 /* rotate left accumulator */
6757 /* and kill the lower order bits */
6758 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6763 /*-----------------------------------------------------------------*/
6764 /* AccRsh - right shift accumulator by known count */
6765 /*-----------------------------------------------------------------*/
6767 AccRsh (int shCount)
6774 emitcode ("rrc", "a");
6778 /* rotate right accumulator */
6779 AccRol (8 - shCount);
6780 /* and kill the higher order bits */
6781 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6786 #ifdef BETTER_LITERAL_SHIFT
6787 /*-----------------------------------------------------------------*/
6788 /* AccSRsh - signed right shift accumulator by known count */
6789 /*-----------------------------------------------------------------*/
6791 AccSRsh (int shCount)
6798 emitcode ("mov", "c,acc.7");
6799 emitcode ("rrc", "a");
6801 else if (shCount == 2)
6803 emitcode ("mov", "c,acc.7");
6804 emitcode ("rrc", "a");
6805 emitcode ("mov", "c,acc.7");
6806 emitcode ("rrc", "a");
6810 tlbl = newiTempLabel (NULL);
6811 /* rotate right accumulator */
6812 AccRol (8 - shCount);
6813 /* and kill the higher order bits */
6814 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6815 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6816 emitcode ("orl", "a,#0x%02x",
6817 (unsigned char) ~SRMask[shCount]);
6818 emitcode ("", "%05d$:", tlbl->key + 100);
6824 #ifdef BETTER_LITERAL_SHIFT
6825 /*-----------------------------------------------------------------*/
6826 /* shiftR1Left2Result - shift right one byte from left to result */
6827 /*-----------------------------------------------------------------*/
6829 shiftR1Left2Result (operand * left, int offl,
6830 operand * result, int offr,
6831 int shCount, int sign)
6833 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6834 /* shift right accumulator */
6839 aopPut (AOP (result), "a", offr);
6843 #ifdef BETTER_LITERAL_SHIFT
6844 /*-----------------------------------------------------------------*/
6845 /* shiftL1Left2Result - shift left one byte from left to result */
6846 /*-----------------------------------------------------------------*/
6848 shiftL1Left2Result (operand * left, int offl,
6849 operand * result, int offr, int shCount)
6851 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6852 /* shift left accumulator */
6854 aopPut (AOP (result), "a", offr);
6858 #ifdef BETTER_LITERAL_SHIFT
6859 /*-----------------------------------------------------------------*/
6860 /* movLeft2Result - move byte from left to result */
6861 /*-----------------------------------------------------------------*/
6863 movLeft2Result (operand * left, int offl,
6864 operand * result, int offr, int sign)
6867 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6869 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6871 if (*l == '@' && (IS_AOP_PREG (result)))
6873 emitcode ("mov", "a,%s", l);
6874 aopPut (AOP (result), "a", offr);
6880 aopPut (AOP (result), l, offr);
6884 /* MSB sign in acc.7 ! */
6885 if (getDataSize (left) == offl + 1)
6887 emitcode ("mov", "a,%s", l);
6888 aopPut (AOP (result), "a", offr);
6896 #ifdef BETTER_LITERAL_SHIFT
6897 /*-----------------------------------------------------------------*/
6898 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6899 /*-----------------------------------------------------------------*/
6903 emitcode ("rrc", "a");
6904 emitcode ("xch", "a,%s", x);
6905 emitcode ("rrc", "a");
6906 emitcode ("xch", "a,%s", x);
6910 #ifdef BETTER_LITERAL_SHIFT
6912 /*-----------------------------------------------------------------*/
6913 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6914 /*-----------------------------------------------------------------*/
6918 emitcode ("xch", "a,%s", x);
6919 emitcode ("rlc", "a");
6920 emitcode ("xch", "a,%s", x);
6921 emitcode ("rlc", "a");
6925 #ifdef BETTER_LITERAL_SHIFT
6926 /*-----------------------------------------------------------------*/
6927 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6928 /*-----------------------------------------------------------------*/
6932 emitcode ("xch", "a,%s", x);
6933 emitcode ("add", "a,acc");
6934 emitcode ("xch", "a,%s", x);
6935 emitcode ("rlc", "a");
6939 #ifdef BETTER_LITERAL_SHIFT
6940 /*-----------------------------------------------------------------*/
6941 /* AccAXLsh - left shift a:x by known count (0..7) */
6942 /*-----------------------------------------------------------------*/
6944 AccAXLsh (char *x, int shCount)
6959 case 5: // AAAAABBB:CCCCCDDD
6961 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6963 emitcode ("anl", "a,#0x%02x",
6964 SLMask[shCount]); // BBB00000:CCCCCDDD
6966 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6968 AccRol (shCount); // DDDCCCCC:BBB00000
6970 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6972 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6974 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6976 emitcode ("anl", "a,#0x%02x",
6977 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6979 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6981 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6984 case 6: // AAAAAABB:CCCCCCDD
6985 emitcode ("anl", "a,#0x%02x",
6986 SRMask[shCount]); // 000000BB:CCCCCCDD
6987 emitcode ("mov", "c,acc.0"); // c = B
6988 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6990 AccAXRrl1 (x); // BCCCCCCD:D000000B
6991 AccAXRrl1 (x); // BBCCCCCC:DD000000
6993 emitcode("rrc","a");
6994 emitcode("xch","a,%s", x);
6995 emitcode("rrc","a");
6996 emitcode("mov","c,acc.0"); //<< get correct bit
6997 emitcode("xch","a,%s", x);
6999 emitcode("rrc","a");
7000 emitcode("xch","a,%s", x);
7001 emitcode("rrc","a");
7002 emitcode("xch","a,%s", x);
7005 case 7: // a:x <<= 7
7007 emitcode ("anl", "a,#0x%02x",
7008 SRMask[shCount]); // 0000000B:CCCCCCCD
7010 emitcode ("mov", "c,acc.0"); // c = B
7012 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7014 AccAXRrl1 (x); // BCCCCCCC:D0000000
7023 #ifdef BETTER_LITERAL_SHIFT
7025 /*-----------------------------------------------------------------*/
7026 /* AccAXRsh - right shift a:x known count (0..7) */
7027 /*-----------------------------------------------------------------*/
7029 AccAXRsh (char *x, int shCount)
7037 AccAXRrl1 (x); // 0->a:x
7042 AccAXRrl1 (x); // 0->a:x
7045 AccAXRrl1 (x); // 0->a:x
7050 case 5: // AAAAABBB:CCCCCDDD = a:x
7052 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7054 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7056 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7058 emitcode ("anl", "a,#0x%02x",
7059 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7061 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7063 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7065 emitcode ("anl", "a,#0x%02x",
7066 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7068 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7070 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7072 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7075 case 6: // AABBBBBB:CCDDDDDD
7077 emitcode ("mov", "c,acc.7");
7078 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7080 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7082 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7084 emitcode ("anl", "a,#0x%02x",
7085 SRMask[shCount]); // 000000AA:BBBBBBCC
7088 case 7: // ABBBBBBB:CDDDDDDD
7090 emitcode ("mov", "c,acc.7"); // c = A
7092 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7094 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7096 emitcode ("anl", "a,#0x%02x",
7097 SRMask[shCount]); // 0000000A:BBBBBBBC
7106 #ifdef BETTER_LITERAL_SHIFT
7107 /*-----------------------------------------------------------------*/
7108 /* AccAXRshS - right shift signed a:x known count (0..7) */
7109 /*-----------------------------------------------------------------*/
7111 AccAXRshS (char *x, int shCount)
7119 emitcode ("mov", "c,acc.7");
7120 AccAXRrl1 (x); // s->a:x
7124 emitcode ("mov", "c,acc.7");
7125 AccAXRrl1 (x); // s->a:x
7127 emitcode ("mov", "c,acc.7");
7128 AccAXRrl1 (x); // s->a:x
7133 case 5: // AAAAABBB:CCCCCDDD = a:x
7135 tlbl = newiTempLabel (NULL);
7136 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7138 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7140 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7142 emitcode ("anl", "a,#0x%02x",
7143 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7145 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7147 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7149 emitcode ("anl", "a,#0x%02x",
7150 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7152 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7154 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7156 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7158 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7159 emitcode ("orl", "a,#0x%02x",
7160 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7162 emitcode ("", "%05d$:", tlbl->key + 100);
7163 break; // SSSSAAAA:BBBCCCCC
7165 case 6: // AABBBBBB:CCDDDDDD
7167 tlbl = newiTempLabel (NULL);
7168 emitcode ("mov", "c,acc.7");
7169 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7171 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7173 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7175 emitcode ("anl", "a,#0x%02x",
7176 SRMask[shCount]); // 000000AA:BBBBBBCC
7178 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7179 emitcode ("orl", "a,#0x%02x",
7180 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7182 emitcode ("", "%05d$:", tlbl->key + 100);
7184 case 7: // ABBBBBBB:CDDDDDDD
7186 tlbl = newiTempLabel (NULL);
7187 emitcode ("mov", "c,acc.7"); // c = A
7189 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7191 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7193 emitcode ("anl", "a,#0x%02x",
7194 SRMask[shCount]); // 0000000A:BBBBBBBC
7196 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7197 emitcode ("orl", "a,#0x%02x",
7198 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7200 emitcode ("", "%05d$:", tlbl->key + 100);
7208 #ifdef BETTER_LITERAL_SHIFT
7210 _loadLeftIntoAx(char **lsb,
7216 // Get the initial value from left into a pair of registers.
7217 // MSB must be in A, LSB can be any register.
7219 // If the result is held in registers, it is an optimization
7220 // if the LSB can be held in the register which will hold the,
7221 // result LSB since this saves us from having to copy it into
7222 // the result following AccAXLsh.
7224 // If the result is addressed indirectly, this is not a gain.
7225 if (AOP_NEEDSACC(result))
7229 _startLazyDPSEvaluation();
7230 if (AOP_TYPE(left) == AOP_DPTR2)
7233 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7234 // get LSB in DP2_RESULT_REG.
7235 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7236 assert(!strcmp(leftByte, DP2_RESULT_REG));
7240 // get LSB into DP2_RESULT_REG
7241 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7242 if (strcmp(leftByte, DP2_RESULT_REG))
7245 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7248 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7249 assert(strcmp(leftByte, DP2_RESULT_REG));
7252 _endLazyDPSEvaluation();
7253 *lsb = DP2_RESULT_REG;
7257 if (sameRegs (AOP (result), AOP (left)) &&
7258 ((offl + MSB16) == offr))
7260 /* don't crash result[offr] */
7261 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7262 emitcode ("xch", "a,%s",
7263 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7267 movLeft2Result (left, offl, result, offr, 0);
7268 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7270 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7271 assert(strcmp(*lsb,"a"));
7276 _storeAxResults(char *lsb,
7280 _startLazyDPSEvaluation();
7281 if (AOP_NEEDSACC(result))
7283 /* We have to explicitly update the result LSB.
7285 emitcode("xch","a,%s", lsb);
7286 aopPut(AOP(result), "a", offr);
7287 emitcode("mov","a,%s", lsb);
7289 if (getDataSize (result) > 1)
7291 aopPut (AOP (result), "a", offr + MSB16);
7293 _endLazyDPSEvaluation();
7296 /*-----------------------------------------------------------------*/
7297 /* shiftL2Left2Result - shift left two bytes from left to result */
7298 /*-----------------------------------------------------------------*/
7300 shiftL2Left2Result (operand * left, int offl,
7301 operand * result, int offr, int shCount)
7305 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7307 AccAXLsh (lsb, shCount);
7309 _storeAxResults(lsb, result, offr);
7313 #ifdef BETTER_LITERAL_SHIFT
7314 /*-----------------------------------------------------------------*/
7315 /* shiftR2Left2Result - shift right two bytes from left to result */
7316 /*-----------------------------------------------------------------*/
7318 shiftR2Left2Result (operand * left, int offl,
7319 operand * result, int offr,
7320 int shCount, int sign)
7324 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7326 /* a:x >> shCount (x = lsb(result)) */
7329 AccAXRshS(lsb, shCount);
7333 AccAXRsh(lsb, shCount);
7336 _storeAxResults(lsb, result, offr);
7342 /*-----------------------------------------------------------------*/
7343 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7344 /*-----------------------------------------------------------------*/
7346 shiftLLeftOrResult (operand * left, int offl,
7347 operand * result, int offr, int shCount)
7349 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7350 /* shift left accumulator */
7352 /* or with result */
7353 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7354 /* back to result */
7355 aopPut (AOP (result), "a", offr);
7361 /*-----------------------------------------------------------------*/
7362 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7363 /*-----------------------------------------------------------------*/
7365 shiftRLeftOrResult (operand * left, int offl,
7366 operand * result, int offr, int shCount)
7368 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7369 /* shift right accumulator */
7371 /* or with result */
7372 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7373 /* back to result */
7374 aopPut (AOP (result), "a", offr);
7378 #ifdef BETTER_LITERAL_SHIFT
7379 /*-----------------------------------------------------------------*/
7380 /* genlshOne - left shift a one byte quantity by known count */
7381 /*-----------------------------------------------------------------*/
7383 genlshOne (operand * result, operand * left, int shCount)
7385 D (emitcode (";", "genlshOne "););
7386 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7390 #ifdef BETTER_LITERAL_SHIFT
7391 /*-----------------------------------------------------------------*/
7392 /* genlshTwo - left shift two bytes by known amount != 0 */
7393 /*-----------------------------------------------------------------*/
7395 genlshTwo (operand * result, operand * left, int shCount)
7399 D (emitcode (";", "genlshTwo "););
7401 size = getDataSize (result);
7403 /* if shCount >= 8 */
7408 _startLazyDPSEvaluation();
7414 _endLazyDPSEvaluation();
7415 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7416 aopPut (AOP (result), zero, LSB);
7420 movLeft2Result (left, LSB, result, MSB16, 0);
7421 aopPut (AOP (result), zero, LSB);
7422 _endLazyDPSEvaluation();
7427 aopPut (AOP (result), zero, LSB);
7428 _endLazyDPSEvaluation();
7432 /* 1 <= shCount <= 7 */
7437 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7441 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7449 /*-----------------------------------------------------------------*/
7450 /* shiftLLong - shift left one long from left to result */
7451 /* offl = LSB or MSB16 */
7452 /*-----------------------------------------------------------------*/
7454 shiftLLong (operand * left, operand * result, int offr)
7457 int size = AOP_SIZE (result);
7459 if (size >= LSB + offr)
7461 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7463 emitcode ("add", "a,acc");
7464 if (sameRegs (AOP (left), AOP (result)) &&
7465 size >= MSB16 + offr && offr != LSB)
7466 emitcode ("xch", "a,%s",
7467 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7469 aopPut (AOP (result), "a", LSB + offr);
7472 if (size >= MSB16 + offr)
7474 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7476 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7479 emitcode ("rlc", "a");
7480 if (sameRegs (AOP (left), AOP (result)) &&
7481 size >= MSB24 + offr && offr != LSB)
7482 emitcode ("xch", "a,%s",
7483 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7485 aopPut (AOP (result), "a", MSB16 + offr);
7488 if (size >= MSB24 + offr)
7490 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7492 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7495 emitcode ("rlc", "a");
7496 if (sameRegs (AOP (left), AOP (result)) &&
7497 size >= MSB32 + offr && offr != LSB)
7498 emitcode ("xch", "a,%s",
7499 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7501 aopPut (AOP (result), "a", MSB24 + offr);
7504 if (size > MSB32 + offr)
7506 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7508 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7511 emitcode ("rlc", "a");
7512 aopPut (AOP (result), "a", MSB32 + offr);
7515 aopPut (AOP (result), zero, LSB);
7521 /*-----------------------------------------------------------------*/
7522 /* genlshFour - shift four byte by a known amount != 0 */
7523 /*-----------------------------------------------------------------*/
7525 genlshFour (operand * result, operand * left, int shCount)
7529 D (emitcode (";", "genlshFour ");
7532 size = AOP_SIZE (result);
7534 /* if shifting more that 3 bytes */
7539 /* lowest order of left goes to the highest
7540 order of the destination */
7541 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7543 movLeft2Result (left, LSB, result, MSB32, 0);
7544 aopPut (AOP (result), zero, LSB);
7545 aopPut (AOP (result), zero, MSB16);
7546 aopPut (AOP (result), zero, MSB24);
7550 /* more than two bytes */
7551 else if (shCount >= 16)
7553 /* lower order two bytes goes to higher order two bytes */
7555 /* if some more remaining */
7557 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7560 movLeft2Result (left, MSB16, result, MSB32, 0);
7561 movLeft2Result (left, LSB, result, MSB24, 0);
7563 aopPut (AOP (result), zero, MSB16);
7564 aopPut (AOP (result), zero, LSB);
7568 /* if more than 1 byte */
7569 else if (shCount >= 8)
7571 /* lower order three bytes goes to higher order three bytes */
7576 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7578 movLeft2Result (left, LSB, result, MSB16, 0);
7584 movLeft2Result (left, MSB24, result, MSB32, 0);
7585 movLeft2Result (left, MSB16, result, MSB24, 0);
7586 movLeft2Result (left, LSB, result, MSB16, 0);
7587 aopPut (AOP (result), zero, LSB);
7589 else if (shCount == 1)
7590 shiftLLong (left, result, MSB16);
7593 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7594 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7595 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7596 aopPut (AOP (result), zero, LSB);
7601 /* 1 <= shCount <= 7 */
7602 else if (shCount <= 2)
7604 shiftLLong (left, result, LSB);
7606 shiftLLong (result, result, LSB);
7608 /* 3 <= shCount <= 7, optimize */
7611 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7612 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7613 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7618 #ifdef BETTER_LITERAL_SHIFT
7619 /*-----------------------------------------------------------------*/
7620 /* genLeftShiftLiteral - left shifting by known count */
7621 /*-----------------------------------------------------------------*/
7623 genLeftShiftLiteral (operand * left,
7628 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7631 size = getSize (operandType (result));
7633 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7635 /* We only handle certain easy cases so far. */
7637 && (shCount < (size * 8))
7641 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7645 freeAsmop (right, NULL, ic, TRUE);
7647 aopOp(left, ic, FALSE, FALSE);
7648 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7651 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7653 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7654 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7656 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7659 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7661 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7662 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7664 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7670 emitcode ("; shift left ", "result %d, left %d", size,
7674 /* I suppose that the left size >= result size */
7677 _startLazyDPSEvaluation();
7680 movLeft2Result (left, size, result, size, 0);
7682 _endLazyDPSEvaluation();
7684 else if (shCount >= (size * 8))
7686 _startLazyDPSEvaluation();
7689 aopPut (AOP (result), zero, size);
7691 _endLazyDPSEvaluation();
7698 genlshOne (result, left, shCount);
7702 genlshTwo (result, left, shCount);
7706 genlshFour (result, left, shCount);
7710 fprintf(stderr, "*** ack! mystery literal shift!\n");
7714 freeAsmop (left, NULL, ic, TRUE);
7715 freeAsmop (result, NULL, ic, TRUE);
7720 /*-----------------------------------------------------------------*/
7721 /* genLeftShift - generates code for left shifting */
7722 /*-----------------------------------------------------------------*/
7724 genLeftShift (iCode * ic)
7726 operand *left, *right, *result;
7729 symbol *tlbl, *tlbl1;
7731 D (emitcode (";", "genLeftShift "););
7733 right = IC_RIGHT (ic);
7734 left = IC_LEFT (ic);
7735 result = IC_RESULT (ic);
7737 aopOp (right, ic, FALSE, FALSE);
7740 #ifdef BETTER_LITERAL_SHIFT
7741 /* if the shift count is known then do it
7742 as efficiently as possible */
7743 if (AOP_TYPE (right) == AOP_LIT)
7745 if (genLeftShiftLiteral (left, right, result, ic))
7752 /* shift count is unknown then we have to form
7753 a loop get the loop count in B : Note: we take
7754 only the lower order byte since shifting
7755 more that 32 bits make no sense anyway, ( the
7756 largest size of an object can be only 32 bits ) */
7758 if (AOP_TYPE (right) == AOP_LIT)
7760 /* Really should be handled by genLeftShiftLiteral,
7761 * but since I'm too lazy to fix that today, at least we can make
7762 * some small improvement.
7764 emitcode("mov", "b,#0x%02x",
7765 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7769 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7770 emitcode ("inc", "b");
7772 freeAsmop (right, NULL, ic, TRUE);
7773 aopOp (left, ic, FALSE, FALSE);
7774 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7776 /* now move the left to the result if they are not the
7778 if (!sameRegs (AOP (left), AOP (result)) &&
7779 AOP_SIZE (result) > 1)
7782 size = AOP_SIZE (result);
7784 _startLazyDPSEvaluation ();
7787 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7788 if (*l == '@' && (IS_AOP_PREG (result)))
7791 emitcode ("mov", "a,%s", l);
7792 aopPut (AOP (result), "a", offset);
7795 aopPut (AOP (result), l, offset);
7798 _endLazyDPSEvaluation ();
7801 tlbl = newiTempLabel (NULL);
7802 size = AOP_SIZE (result);
7804 tlbl1 = newiTempLabel (NULL);
7806 /* if it is only one byte then */
7809 symbol *tlbl1 = newiTempLabel (NULL);
7811 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7813 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7814 emitcode ("", "%05d$:", tlbl->key + 100);
7815 emitcode ("add", "a,acc");
7816 emitcode ("", "%05d$:", tlbl1->key + 100);
7817 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7818 aopPut (AOP (result), "a", 0);
7822 reAdjustPreg (AOP (result));
7824 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7825 emitcode ("", "%05d$:", tlbl->key + 100);
7826 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7828 emitcode ("add", "a,acc");
7829 aopPut (AOP (result), "a", offset++);
7830 _startLazyDPSEvaluation ();
7833 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7835 emitcode ("rlc", "a");
7836 aopPut (AOP (result), "a", offset++);
7838 _endLazyDPSEvaluation ();
7839 reAdjustPreg (AOP (result));
7841 emitcode ("", "%05d$:", tlbl1->key + 100);
7842 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7844 freeAsmop (left, NULL, ic, TRUE);
7845 freeAsmop (result, NULL, ic, TRUE);
7848 #ifdef BETTER_LITERAL_SHIFT
7849 /*-----------------------------------------------------------------*/
7850 /* genrshOne - right shift a one byte quantity by known count */
7851 /*-----------------------------------------------------------------*/
7853 genrshOne (operand * result, operand * left,
7854 int shCount, int sign)
7856 D (emitcode (";", "genrshOne"););
7857 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7861 #ifdef BETTER_LITERAL_SHIFT
7862 /*-----------------------------------------------------------------*/
7863 /* genrshTwo - right shift two bytes by known amount != 0 */
7864 /*-----------------------------------------------------------------*/
7866 genrshTwo (operand * result, operand * left,
7867 int shCount, int sign)
7869 D (emitcode (";", "genrshTwo"););
7871 /* if shCount >= 8 */
7875 _startLazyDPSEvaluation();
7878 shiftR1Left2Result (left, MSB16, result, LSB,
7883 movLeft2Result (left, MSB16, result, LSB, sign);
7885 addSign (result, MSB16, sign);
7886 _endLazyDPSEvaluation();
7889 /* 1 <= shCount <= 7 */
7892 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7899 /*-----------------------------------------------------------------*/
7900 /* shiftRLong - shift right one long from left to result */
7901 /* offl = LSB or MSB16 */
7902 /*-----------------------------------------------------------------*/
7904 shiftRLong (operand * left, int offl,
7905 operand * result, int sign)
7907 int isSameRegs=sameRegs(AOP(left),AOP(result));
7909 if (isSameRegs && offl>1) {
7910 // we are in big trouble, but this shouldn't happen
7911 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7914 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7919 emitcode ("rlc", "a");
7920 emitcode ("subb", "a,acc");
7921 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7923 aopPut (AOP(result), zero, MSB32);
7928 emitcode ("clr", "c");
7930 emitcode ("mov", "c,acc.7");
7933 emitcode ("rrc", "a");
7935 if (isSameRegs && offl==MSB16) {
7936 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7938 aopPut (AOP (result), "a", MSB32);
7939 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7942 emitcode ("rrc", "a");
7943 if (isSameRegs && offl==1) {
7944 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7946 aopPut (AOP (result), "a", MSB24);
7947 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7949 emitcode ("rrc", "a");
7950 aopPut (AOP (result), "a", MSB16 - offl);
7954 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7955 emitcode ("rrc", "a");
7956 aopPut (AOP (result), "a", LSB);
7963 /*-----------------------------------------------------------------*/
7964 /* genrshFour - shift four byte by a known amount != 0 */
7965 /*-----------------------------------------------------------------*/
7967 genrshFour (operand * result, operand * left,
7968 int shCount, int sign)
7970 D (emitcode (";", "genrshFour");
7973 /* if shifting more that 3 bytes */
7978 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7980 movLeft2Result (left, MSB32, result, LSB, sign);
7981 addSign (result, MSB16, sign);
7983 else if (shCount >= 16)
7987 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7990 movLeft2Result (left, MSB24, result, LSB, 0);
7991 movLeft2Result (left, MSB32, result, MSB16, sign);
7993 addSign (result, MSB24, sign);
7995 else if (shCount >= 8)
7999 shiftRLong (left, MSB16, result, sign);
8000 else if (shCount == 0)
8002 movLeft2Result (left, MSB16, result, LSB, 0);
8003 movLeft2Result (left, MSB24, result, MSB16, 0);
8004 movLeft2Result (left, MSB32, result, MSB24, sign);
8005 addSign (result, MSB32, sign);
8009 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8010 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8011 /* the last shift is signed */
8012 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8013 addSign (result, MSB32, sign);
8017 { /* 1 <= shCount <= 7 */
8020 shiftRLong (left, LSB, result, sign);
8022 shiftRLong (result, LSB, result, sign);
8026 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8027 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8028 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8034 #ifdef BETTER_LITERAL_SHIFT
8035 /*-----------------------------------------------------------------*/
8036 /* genRightShiftLiteral - right shifting by known count */
8037 /*-----------------------------------------------------------------*/
8039 genRightShiftLiteral (operand * left,
8045 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8048 size = getSize (operandType (result));
8050 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8052 /* We only handle certain easy cases so far. */
8054 && (shCount < (size * 8))
8058 D(emitcode (";", "genRightShiftLiteral wimping out"););
8062 freeAsmop (right, NULL, ic, TRUE);
8064 aopOp (left, ic, FALSE, FALSE);
8065 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8068 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8072 /* test the LEFT size !!! */
8074 /* I suppose that the left size >= result size */
8077 size = getDataSize (result);
8078 _startLazyDPSEvaluation();
8081 movLeft2Result (left, size, result, size, 0);
8083 _endLazyDPSEvaluation();
8085 else if (shCount >= (size * 8))
8089 /* get sign in acc.7 */
8090 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8092 addSign (result, LSB, sign);
8099 genrshOne (result, left, shCount, sign);
8103 genrshTwo (result, left, shCount, sign);
8107 genrshFour (result, left, shCount, sign);
8114 freeAsmop (left, NULL, ic, TRUE);
8115 freeAsmop (result, NULL, ic, TRUE);
8121 /*-----------------------------------------------------------------*/
8122 /* genSignedRightShift - right shift of signed number */
8123 /*-----------------------------------------------------------------*/
8125 genSignedRightShift (iCode * ic)
8127 operand *right, *left, *result;
8130 symbol *tlbl, *tlbl1;
8132 D (emitcode (";", "genSignedRightShift "););
8134 /* we do it the hard way put the shift count in b
8135 and loop thru preserving the sign */
8137 right = IC_RIGHT (ic);
8138 left = IC_LEFT (ic);
8139 result = IC_RESULT (ic);
8141 aopOp (right, ic, FALSE, FALSE);
8143 #ifdef BETTER_LITERAL_SHIFT
8144 if (AOP_TYPE (right) == AOP_LIT)
8146 if (genRightShiftLiteral (left, right, result, ic, 1))
8152 /* shift count is unknown then we have to form
8153 a loop get the loop count in B : Note: we take
8154 only the lower order byte since shifting
8155 more that 32 bits make no sense anyway, ( the
8156 largest size of an object can be only 32 bits ) */
8158 if (AOP_TYPE (right) == AOP_LIT)
8160 /* Really should be handled by genRightShiftLiteral,
8161 * but since I'm too lazy to fix that today, at least we can make
8162 * some small improvement.
8164 emitcode("mov", "b,#0x%02x",
8165 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8169 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8170 emitcode ("inc", "b");
8172 freeAsmop (right, NULL, ic, TRUE);
8173 aopOp (left, ic, FALSE, FALSE);
8174 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8176 /* now move the left to the result if they are not the
8178 if (!sameRegs (AOP (left), AOP (result)) &&
8179 AOP_SIZE (result) > 1)
8182 size = AOP_SIZE (result);
8184 _startLazyDPSEvaluation ();
8187 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8188 if (*l == '@' && IS_AOP_PREG (result))
8191 emitcode ("mov", "a,%s", l);
8192 aopPut (AOP (result), "a", offset);
8195 aopPut (AOP (result), l, offset);
8198 _endLazyDPSEvaluation ();
8201 /* mov the highest order bit to OVR */
8202 tlbl = newiTempLabel (NULL);
8203 tlbl1 = newiTempLabel (NULL);
8205 size = AOP_SIZE (result);
8207 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8208 emitcode ("rlc", "a");
8209 emitcode ("mov", "ov,c");
8210 /* if it is only one byte then */
8213 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8215 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8216 emitcode ("", "%05d$:", tlbl->key + 100);
8217 emitcode ("mov", "c,ov");
8218 emitcode ("rrc", "a");
8219 emitcode ("", "%05d$:", tlbl1->key + 100);
8220 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8221 aopPut (AOP (result), "a", 0);
8225 reAdjustPreg (AOP (result));
8226 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8227 emitcode ("", "%05d$:", tlbl->key + 100);
8228 emitcode ("mov", "c,ov");
8229 _startLazyDPSEvaluation ();
8232 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8234 emitcode ("rrc", "a");
8235 aopPut (AOP (result), "a", offset--);
8237 _endLazyDPSEvaluation ();
8238 reAdjustPreg (AOP (result));
8239 emitcode ("", "%05d$:", tlbl1->key + 100);
8240 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8243 freeAsmop (left, NULL, ic, TRUE);
8244 freeAsmop (result, NULL, ic, TRUE);
8247 /*-----------------------------------------------------------------*/
8248 /* genRightShift - generate code for right shifting */
8249 /*-----------------------------------------------------------------*/
8251 genRightShift (iCode * ic)
8253 operand *right, *left, *result;
8257 symbol *tlbl, *tlbl1;
8259 D (emitcode (";", "genRightShift "););
8261 /* if signed then we do it the hard way preserve the
8262 sign bit moving it inwards */
8263 retype = getSpec (operandType (IC_RESULT (ic)));
8265 if (!SPEC_USIGN (retype))
8267 genSignedRightShift (ic);
8271 /* signed & unsigned types are treated the same : i.e. the
8272 signed is NOT propagated inwards : quoting from the
8273 ANSI - standard : "for E1 >> E2, is equivalent to division
8274 by 2**E2 if unsigned or if it has a non-negative value,
8275 otherwise the result is implementation defined ", MY definition
8276 is that the sign does not get propagated */
8278 right = IC_RIGHT (ic);
8279 left = IC_LEFT (ic);
8280 result = IC_RESULT (ic);
8282 aopOp (right, ic, FALSE, FALSE);
8284 #ifdef BETTER_LITERAL_SHIFT
8285 /* if the shift count is known then do it
8286 as efficiently as possible */
8287 if (AOP_TYPE (right) == AOP_LIT)
8289 if (genRightShiftLiteral (left, right, result, ic, 0))
8296 /* shift count is unknown then we have to form
8297 a loop get the loop count in B : Note: we take
8298 only the lower order byte since shifting
8299 more that 32 bits make no sense anyway, ( the
8300 largest size of an object can be only 32 bits ) */
8302 if (AOP_TYPE (right) == AOP_LIT)
8304 /* Really should be handled by genRightShiftLiteral,
8305 * but since I'm too lazy to fix that today, at least we can make
8306 * some small improvement.
8308 emitcode("mov", "b,#0x%02x",
8309 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8313 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8314 emitcode ("inc", "b");
8316 freeAsmop (right, NULL, ic, TRUE);
8317 aopOp (left, ic, FALSE, FALSE);
8318 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8320 /* now move the left to the result if they are not the
8322 if (!sameRegs (AOP (left), AOP (result)) &&
8323 AOP_SIZE (result) > 1)
8326 size = AOP_SIZE (result);
8328 _startLazyDPSEvaluation ();
8331 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8332 if (*l == '@' && IS_AOP_PREG (result))
8335 emitcode ("mov", "a,%s", l);
8336 aopPut (AOP (result), "a", offset);
8339 aopPut (AOP (result), l, offset);
8342 _endLazyDPSEvaluation ();
8345 tlbl = newiTempLabel (NULL);
8346 tlbl1 = newiTempLabel (NULL);
8347 size = AOP_SIZE (result);
8350 /* if it is only one byte then */
8353 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8355 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8356 emitcode ("", "%05d$:", tlbl->key + 100);
8358 emitcode ("rrc", "a");
8359 emitcode ("", "%05d$:", tlbl1->key + 100);
8360 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8361 aopPut (AOP (result), "a", 0);
8365 reAdjustPreg (AOP (result));
8366 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8367 emitcode ("", "%05d$:", tlbl->key + 100);
8369 _startLazyDPSEvaluation ();
8372 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8374 emitcode ("rrc", "a");
8375 aopPut (AOP (result), "a", offset--);
8377 _endLazyDPSEvaluation ();
8378 reAdjustPreg (AOP (result));
8380 emitcode ("", "%05d$:", tlbl1->key + 100);
8381 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8384 freeAsmop (left, NULL, ic, TRUE);
8385 freeAsmop (result, NULL, ic, TRUE);
8388 /*-----------------------------------------------------------------*/
8389 /* genUnpackBits - generates code for unpacking bits */
8390 /*-----------------------------------------------------------------*/
8392 genUnpackBits (operand * result, char *rname, int ptype)
8399 D (emitcode (";", "genUnpackBits ");
8402 etype = getSpec (operandType (result));
8404 /* read the first byte */
8410 emitcode ("mov", "a,@%s", rname);
8414 emitcode ("movx", "a,@%s", rname);
8418 emitcode ("movx", "a,@dptr");
8422 emitcode ("clr", "a");
8423 emitcode ("movc", "a,@a+dptr");
8427 emitcode ("lcall", "__gptrget");
8431 /* if we have bitdisplacement then it fits */
8432 /* into this byte completely or if length is */
8433 /* less than a byte */
8434 if ((shCnt = SPEC_BSTR (etype)) ||
8435 (SPEC_BLEN (etype) <= 8))
8438 /* shift right acc */
8441 emitcode ("anl", "a,#0x%02x",
8442 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8443 aopPut (AOP (result), "a", offset);
8447 /* bit field did not fit in a byte */
8448 rlen = SPEC_BLEN (etype) - 8;
8449 aopPut (AOP (result), "a", offset++);
8458 emitcode ("inc", "%s", rname);
8459 emitcode ("mov", "a,@%s", rname);
8463 emitcode ("inc", "%s", rname);
8464 emitcode ("movx", "a,@%s", rname);
8468 emitcode ("inc", "dptr");
8469 emitcode ("movx", "a,@dptr");
8473 emitcode ("clr", "a");
8474 emitcode ("inc", "dptr");
8475 emitcode ("movc", "a,@a+dptr");
8479 emitcode ("inc", "dptr");
8480 emitcode ("lcall", "__gptrget");
8485 /* if we are done */
8489 aopPut (AOP (result), "a", offset++);
8495 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
8496 aopPut (AOP (result), "a", offset);
8503 /*-----------------------------------------------------------------*/
8504 /* genDataPointerGet - generates code when ptr offset is known */
8505 /*-----------------------------------------------------------------*/
8507 genDataPointerGet (operand * left,
8513 int size, offset = 0;
8514 aopOp (result, ic, TRUE, FALSE);
8516 /* get the string representation of the name */
8517 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8518 size = AOP_SIZE (result);
8519 _startLazyDPSEvaluation ();
8523 sprintf (buffer, "(%s + %d)", l + 1, offset);
8525 sprintf (buffer, "%s", l + 1);
8526 aopPut (AOP (result), buffer, offset++);
8528 _endLazyDPSEvaluation ();
8530 freeAsmop (left, NULL, ic, TRUE);
8531 freeAsmop (result, NULL, ic, TRUE);
8534 /*-----------------------------------------------------------------*/
8535 /* genNearPointerGet - emitcode for near pointer fetch */
8536 /*-----------------------------------------------------------------*/
8538 genNearPointerGet (operand * left,
8545 sym_link *rtype, *retype, *letype;
8546 sym_link *ltype = operandType (left);
8549 rtype = operandType (result);
8550 retype = getSpec (rtype);
8551 letype = getSpec (ltype);
8553 aopOp (left, ic, FALSE, FALSE);
8555 /* if left is rematerialisable and
8556 result is not bit variable type and
8557 the left is pointer to data space i.e
8558 lower 128 bytes of space */
8559 if (AOP_TYPE (left) == AOP_IMMD &&
8560 !IS_BITVAR (retype) &&
8561 !IS_BITVAR (letype) &&
8562 DCL_TYPE (ltype) == POINTER)
8564 genDataPointerGet (left, result, ic);
8568 /* if the value is already in a pointer register
8569 then don't need anything more */
8570 if (!AOP_INPREG (AOP (left)))
8572 /* otherwise get a free pointer register */
8574 preg = getFreePtr (ic, &aop, FALSE);
8575 emitcode ("mov", "%s,%s",
8577 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8581 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8583 freeAsmop (left, NULL, ic, TRUE);
8584 aopOp (result, ic, FALSE, FALSE);
8586 /* if bitfield then unpack the bits */
8587 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8588 genUnpackBits (result, rname, POINTER);
8591 /* we have can just get the values */
8592 int size = AOP_SIZE (result);
8597 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8600 emitcode ("mov", "a,@%s", rname);
8601 aopPut (AOP (result), "a", offset);
8605 sprintf (buffer, "@%s", rname);
8606 aopPut (AOP (result), buffer, offset);
8610 emitcode ("inc", "%s", rname);
8614 /* now some housekeeping stuff */
8617 /* we had to allocate for this iCode */
8618 freeAsmop (NULL, aop, ic, TRUE);
8622 /* we did not allocate which means left
8623 already in a pointer register, then
8624 if size > 0 && this could be used again
8625 we have to point it back to where it
8627 if (AOP_SIZE (result) > 1 &&
8628 !OP_SYMBOL (left)->remat &&
8629 (OP_SYMBOL (left)->liveTo > ic->seq ||
8632 int size = AOP_SIZE (result) - 1;
8634 emitcode ("dec", "%s", rname);
8639 freeAsmop (result, NULL, ic, TRUE);
8643 /*-----------------------------------------------------------------*/
8644 /* genPagedPointerGet - emitcode for paged pointer fetch */
8645 /*-----------------------------------------------------------------*/
8647 genPagedPointerGet (operand * left,
8654 sym_link *rtype, *retype, *letype;
8656 rtype = operandType (result);
8657 retype = getSpec (rtype);
8658 letype = getSpec (operandType (left));
8659 aopOp (left, ic, FALSE, FALSE);
8661 /* if the value is already in a pointer register
8662 then don't need anything more */
8663 if (!AOP_INPREG (AOP (left)))
8665 /* otherwise get a free pointer register */
8667 preg = getFreePtr (ic, &aop, FALSE);
8668 emitcode ("mov", "%s,%s",
8670 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8674 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8676 freeAsmop (left, NULL, ic, TRUE);
8677 aopOp (result, ic, FALSE, FALSE);
8679 /* if bitfield then unpack the bits */
8680 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8681 genUnpackBits (result, rname, PPOINTER);
8684 /* we have can just get the values */
8685 int size = AOP_SIZE (result);
8691 emitcode ("movx", "a,@%s", rname);
8692 aopPut (AOP (result), "a", offset);
8697 emitcode ("inc", "%s", rname);
8701 /* now some housekeeping stuff */
8704 /* we had to allocate for this iCode */
8705 freeAsmop (NULL, aop, ic, TRUE);
8709 /* we did not allocate which means left
8710 already in a pointer register, then
8711 if size > 0 && this could be used again
8712 we have to point it back to where it
8714 if (AOP_SIZE (result) > 1 &&
8715 !OP_SYMBOL (left)->remat &&
8716 (OP_SYMBOL (left)->liveTo > ic->seq ||
8719 int size = AOP_SIZE (result) - 1;
8721 emitcode ("dec", "%s", rname);
8726 freeAsmop (result, NULL, ic, TRUE);
8731 /*-----------------------------------------------------------------*/
8732 /* genFarPointerGet - gget value from far space */
8733 /*-----------------------------------------------------------------*/
8735 genFarPointerGet (operand * left,
8736 operand * result, iCode * ic)
8739 sym_link *retype = getSpec (operandType (result));
8740 sym_link *letype = getSpec (operandType (left));
8741 D (emitcode (";", "genFarPointerGet");
8744 aopOp (left, ic, FALSE, FALSE);
8746 /* if the operand is already in dptr
8747 then we do nothing else we move the value to dptr */
8748 if (AOP_TYPE (left) != AOP_STR)
8750 /* if this is remateriazable */
8751 if (AOP_TYPE (left) == AOP_IMMD)
8753 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8757 /* we need to get it byte by byte */
8758 _startLazyDPSEvaluation ();
8759 if (AOP_TYPE (left) != AOP_DPTR)
8761 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8762 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8763 if (options.model == MODEL_FLAT24)
8764 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8768 /* We need to generate a load to DPTR indirect through DPTR. */
8769 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8771 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8772 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8773 if (options.model == MODEL_FLAT24)
8774 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8775 emitcode ("pop", "dph");
8776 emitcode ("pop", "dpl");
8778 _endLazyDPSEvaluation ();
8781 /* so dptr know contains the address */
8782 freeAsmop (left, NULL, ic, TRUE);
8783 aopOp (result, ic, FALSE, TRUE);
8785 /* if bit then unpack */
8786 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8787 genUnpackBits (result, "dptr", FPOINTER);
8790 size = AOP_SIZE (result);
8793 _startLazyDPSEvaluation ();
8800 emitcode ("movx", "a,@dptr");
8802 emitcode ("inc", "dptr");
8804 aopPut (AOP (result), "a", offset++);
8806 _endLazyDPSEvaluation ();
8809 freeAsmop (result, NULL, ic, TRUE);
8812 /*-----------------------------------------------------------------*/
8813 /* emitcodePointerGet - gget value from code space */
8814 /*-----------------------------------------------------------------*/
8816 emitcodePointerGet (operand * left,
8817 operand * result, iCode * ic)
8820 sym_link *retype = getSpec (operandType (result));
8822 aopOp (left, ic, FALSE, FALSE);
8824 /* if the operand is already in dptr
8825 then we do nothing else we move the value to dptr */
8826 if (AOP_TYPE (left) != AOP_STR)
8828 /* if this is remateriazable */
8829 if (AOP_TYPE (left) == AOP_IMMD)
8831 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8834 { /* we need to get it byte by byte */
8835 _startLazyDPSEvaluation ();
8836 if (AOP_TYPE (left) != AOP_DPTR)
8838 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8839 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8840 if (options.model == MODEL_FLAT24)
8841 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8845 /* We need to generate a load to DPTR indirect through DPTR. */
8846 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8848 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8849 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8850 if (options.model == MODEL_FLAT24)
8851 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8852 emitcode ("pop", "dph");
8853 emitcode ("pop", "dpl");
8855 _endLazyDPSEvaluation ();
8858 /* so dptr know contains the address */
8859 freeAsmop (left, NULL, ic, TRUE);
8860 aopOp (result, ic, FALSE, TRUE);
8862 /* if bit then unpack */
8863 if (IS_BITVAR (retype))
8864 genUnpackBits (result, "dptr", CPOINTER);
8867 size = AOP_SIZE (result);
8870 _startLazyDPSEvaluation ();
8876 emitcode ("clr", "a");
8877 emitcode ("movc", "a,@a+dptr");
8879 emitcode ("inc", "dptr");
8880 aopPut (AOP (result), "a", offset++);
8882 _endLazyDPSEvaluation ();
8885 freeAsmop (result, NULL, ic, TRUE);
8888 /*-----------------------------------------------------------------*/
8889 /* genGenPointerGet - gget value from generic pointer space */
8890 /*-----------------------------------------------------------------*/
8892 genGenPointerGet (operand * left,
8893 operand * result, iCode * ic)
8896 sym_link *retype = getSpec (operandType (result));
8897 sym_link *letype = getSpec (operandType (left));
8899 D (emitcode (";", "genGenPointerGet "); );
8901 aopOp (left, ic, FALSE, TRUE);
8903 /* if the operand is already in dptr
8904 then we do nothing else we move the value to dptr */
8905 if (AOP_TYPE (left) != AOP_STR)
8907 /* if this is remateriazable */
8908 if (AOP_TYPE (left) == AOP_IMMD)
8910 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8911 if (AOP(left)->aopu.aop_immd.from_cast_remat)
8912 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
8914 emitcode ("mov", "b,#%d", pointerCode (retype));
8917 { /* we need to get it byte by byte */
8918 _startLazyDPSEvaluation ();
8919 if (AOP(left)->type==AOP_DPTR2) {
8921 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8924 emitcode ("mov", "dpl,%s", l);
8925 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8928 emitcode ("mov", "dph,%s", l);
8929 if (options.model == MODEL_FLAT24) {
8930 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8933 emitcode ("mov", "dpx,%s", l);
8934 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8936 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8939 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8940 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8941 if (options.model == MODEL_FLAT24) {
8942 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8943 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8945 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8948 _endLazyDPSEvaluation ();
8951 /* so dptr know contains the address */
8952 freeAsmop (left, NULL, ic, TRUE);
8953 aopOp (result, ic, FALSE, TRUE);
8955 /* if bit then unpack */
8956 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8957 genUnpackBits (result, "dptr", GPOINTER);
8960 size = AOP_SIZE (result);
8965 emitcode ("lcall", "__gptrget");
8966 aopPut (AOP (result), "a", offset++);
8968 emitcode ("inc", "dptr");
8972 freeAsmop (result, NULL, ic, TRUE);
8975 /*-----------------------------------------------------------------*/
8976 /* genPointerGet - generate code for pointer get */
8977 /*-----------------------------------------------------------------*/
8979 genPointerGet (iCode * ic)
8981 operand *left, *result;
8982 sym_link *type, *etype;
8985 D (emitcode (";", "genPointerGet ");
8988 left = IC_LEFT (ic);
8989 result = IC_RESULT (ic);
8991 /* depending on the type of pointer we need to
8992 move it to the correct pointer register */
8993 type = operandType (left);
8994 etype = getSpec (type);
8995 /* if left is of type of pointer then it is simple */
8996 if (IS_PTR (type) && !IS_FUNC (type->next))
8997 p_type = DCL_TYPE (type);
9000 /* we have to go by the storage class */
9001 p_type = PTR_TYPE (SPEC_OCLS (etype));
9003 /* special case when cast remat */
9004 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9005 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9006 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9007 type = type = operandType (left);
9008 p_type = DCL_TYPE (type);
9010 /* now that we have the pointer type we assign
9011 the pointer values */
9017 genNearPointerGet (left, result, ic);
9021 genPagedPointerGet (left, result, ic);
9025 genFarPointerGet (left, result, ic);
9029 emitcodePointerGet (left, result, ic);
9033 genGenPointerGet (left, result, ic);
9039 /*-----------------------------------------------------------------*/
9040 /* genPackBits - generates code for packed bit storage */
9041 /*-----------------------------------------------------------------*/
9043 genPackBits (sym_link * etype,
9045 char *rname, int p_type)
9053 blen = SPEC_BLEN (etype);
9054 bstr = SPEC_BSTR (etype);
9056 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9059 /* if the bit lenth is less than or */
9060 /* it exactly fits a byte then */
9061 if (SPEC_BLEN (etype) <= 8)
9063 shCount = SPEC_BSTR (etype);
9065 /* shift left acc */
9068 if (SPEC_BLEN (etype) < 8)
9069 { /* if smaller than a byte */
9075 emitcode ("mov", "b,a");
9076 emitcode ("mov", "a,@%s", rname);
9080 emitcode ("mov", "b,a");
9081 emitcode ("movx", "a,@dptr");
9085 emitcode ("push", "b");
9086 emitcode ("push", "acc");
9087 emitcode ("lcall", "__gptrget");
9088 emitcode ("pop", "b");
9092 emitcode ("anl", "a,#0x%02x", (unsigned char)
9093 ((unsigned char) (0xFF << (blen + bstr)) |
9094 (unsigned char) (0xFF >> (8 - bstr))));
9095 emitcode ("orl", "a,b");
9096 if (p_type == GPOINTER)
9097 emitcode ("pop", "b");
9104 emitcode ("mov", "@%s,a", rname);
9108 emitcode ("movx", "@dptr,a");
9112 emitcode ("lcall", "__gptrput");
9117 if (SPEC_BLEN (etype) <= 8)
9120 emitcode ("inc", "%s", rname);
9121 rLen = SPEC_BLEN (etype);
9123 /* now generate for lengths greater than one byte */
9127 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9139 emitcode ("mov", "@%s,a", rname);
9142 emitcode ("mov", "@%s,%s", rname, l);
9147 emitcode ("movx", "@dptr,a");
9152 emitcode ("lcall", "__gptrput");
9155 emitcode ("inc", "%s", rname);
9160 /* last last was not complete */
9163 /* save the byte & read byte */
9167 emitcode ("mov", "b,a");
9168 emitcode ("mov", "a,@%s", rname);
9172 emitcode ("mov", "b,a");
9173 emitcode ("movx", "a,@dptr");
9177 emitcode ("push", "b");
9178 emitcode ("push", "acc");
9179 emitcode ("lcall", "__gptrget");
9180 emitcode ("pop", "b");
9184 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
9185 emitcode ("orl", "a,b");
9188 if (p_type == GPOINTER)
9189 emitcode ("pop", "b");
9195 emitcode ("mov", "@%s,a", rname);
9199 emitcode ("movx", "@dptr,a");
9203 emitcode ("lcall", "__gptrput");
9207 /*-----------------------------------------------------------------*/
9208 /* genDataPointerSet - remat pointer to data space */
9209 /*-----------------------------------------------------------------*/
9211 genDataPointerSet (operand * right,
9215 int size, offset = 0;
9216 char *l, buffer[256];
9218 aopOp (right, ic, FALSE, FALSE);
9220 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9221 size = AOP_SIZE (right);
9225 sprintf (buffer, "(%s + %d)", l + 1, offset);
9227 sprintf (buffer, "%s", l + 1);
9228 emitcode ("mov", "%s,%s", buffer,
9229 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9232 freeAsmop (right, NULL, ic, TRUE);
9233 freeAsmop (result, NULL, ic, TRUE);
9236 /*-----------------------------------------------------------------*/
9237 /* genNearPointerSet - emitcode for near pointer put */
9238 /*-----------------------------------------------------------------*/
9240 genNearPointerSet (operand * right,
9247 sym_link *retype, *letype;
9248 sym_link *ptype = operandType (result);
9250 retype = getSpec (operandType (right));
9251 letype = getSpec (ptype);
9253 aopOp (result, ic, FALSE, FALSE);
9255 /* if the result is rematerializable &
9256 in data space & not a bit variable */
9257 if (AOP_TYPE (result) == AOP_IMMD &&
9258 DCL_TYPE (ptype) == POINTER &&
9259 !IS_BITVAR (retype) &&
9260 !IS_BITVAR (letype))
9262 genDataPointerSet (right, result, ic);
9266 /* if the value is already in a pointer register
9267 then don't need anything more */
9268 if (!AOP_INPREG (AOP (result)))
9270 /* otherwise get a free pointer register */
9272 preg = getFreePtr (ic, &aop, FALSE);
9273 emitcode ("mov", "%s,%s",
9275 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9279 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9281 freeAsmop (result, NULL, ic, TRUE);
9282 aopOp (right, ic, FALSE, FALSE);
9284 /* if bitfield then unpack the bits */
9285 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9286 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9289 /* we have can just get the values */
9290 int size = AOP_SIZE (right);
9295 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9299 emitcode ("mov", "@%s,a", rname);
9302 emitcode ("mov", "@%s,%s", rname, l);
9304 emitcode ("inc", "%s", rname);
9309 /* now some housekeeping stuff */
9312 /* we had to allocate for this iCode */
9313 freeAsmop (NULL, aop, ic, TRUE);
9317 /* we did not allocate which means left
9318 already in a pointer register, then
9319 if size > 0 && this could be used again
9320 we have to point it back to where it
9322 if (AOP_SIZE (right) > 1 &&
9323 !OP_SYMBOL (result)->remat &&
9324 (OP_SYMBOL (result)->liveTo > ic->seq ||
9327 int size = AOP_SIZE (right) - 1;
9329 emitcode ("dec", "%s", rname);
9334 freeAsmop (right, NULL, ic, TRUE);
9339 /*-----------------------------------------------------------------*/
9340 /* genPagedPointerSet - emitcode for Paged pointer put */
9341 /*-----------------------------------------------------------------*/
9343 genPagedPointerSet (operand * right,
9350 sym_link *retype, *letype;
9352 retype = getSpec (operandType (right));
9353 letype = getSpec (operandType (result));
9355 aopOp (result, ic, FALSE, FALSE);
9357 /* if the value is already in a pointer register
9358 then don't need anything more */
9359 if (!AOP_INPREG (AOP (result)))
9361 /* otherwise get a free pointer register */
9363 preg = getFreePtr (ic, &aop, FALSE);
9364 emitcode ("mov", "%s,%s",
9366 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9370 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9372 freeAsmop (result, NULL, ic, TRUE);
9373 aopOp (right, ic, FALSE, FALSE);
9375 /* if bitfield then unpack the bits */
9376 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9377 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9380 /* we have can just get the values */
9381 int size = AOP_SIZE (right);
9386 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9389 emitcode ("movx", "@%s,a", rname);
9392 emitcode ("inc", "%s", rname);
9398 /* now some housekeeping stuff */
9401 /* we had to allocate for this iCode */
9402 freeAsmop (NULL, aop, ic, TRUE);
9406 /* we did not allocate which means left
9407 already in a pointer register, then
9408 if size > 0 && this could be used again
9409 we have to point it back to where it
9411 if (AOP_SIZE (right) > 1 &&
9412 !OP_SYMBOL (result)->remat &&
9413 (OP_SYMBOL (result)->liveTo > ic->seq ||
9416 int size = AOP_SIZE (right) - 1;
9418 emitcode ("dec", "%s", rname);
9423 freeAsmop (right, NULL, ic, TRUE);
9428 /*-----------------------------------------------------------------*/
9429 /* genFarPointerSet - set value from far space */
9430 /*-----------------------------------------------------------------*/
9432 genFarPointerSet (operand * right,
9433 operand * result, iCode * ic)
9436 sym_link *retype = getSpec (operandType (right));
9437 sym_link *letype = getSpec (operandType (result));
9439 aopOp (result, ic, FALSE, FALSE);
9441 /* if the operand is already in dptr
9442 then we do nothing else we move the value to dptr */
9443 if (AOP_TYPE (result) != AOP_STR)
9445 /* if this is remateriazable */
9446 if (AOP_TYPE (result) == AOP_IMMD)
9447 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9450 /* we need to get it byte by byte */
9451 _startLazyDPSEvaluation ();
9452 if (AOP_TYPE (result) != AOP_DPTR)
9454 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9455 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9456 if (options.model == MODEL_FLAT24)
9457 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9461 /* We need to generate a load to DPTR indirect through DPTR. */
9462 D (emitcode (";", "genFarPointerSet -- indirection special case.");
9464 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9465 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9466 if (options.model == MODEL_FLAT24)
9467 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9468 emitcode ("pop", "dph");
9469 emitcode ("pop", "dpl");
9471 _endLazyDPSEvaluation ();
9474 /* so dptr know contains the address */
9475 freeAsmop (result, NULL, ic, TRUE);
9476 aopOp (right, ic, FALSE, TRUE);
9478 /* if bit then unpack */
9479 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9480 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9483 size = AOP_SIZE (right);
9486 _startLazyDPSEvaluation ();
9489 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9495 emitcode ("movx", "@dptr,a");
9497 emitcode ("inc", "dptr");
9499 _endLazyDPSEvaluation ();
9502 freeAsmop (right, NULL, ic, TRUE);
9505 /*-----------------------------------------------------------------*/
9506 /* genGenPointerSet - set value from generic pointer space */
9507 /*-----------------------------------------------------------------*/
9509 genGenPointerSet (operand * right,
9510 operand * result, iCode * ic)
9513 sym_link *retype = getSpec (operandType (right));
9514 sym_link *letype = getSpec (operandType (result));
9516 aopOp (result, ic, FALSE, TRUE);
9518 /* if the operand is already in dptr
9519 then we do nothing else we move the value to dptr */
9520 if (AOP_TYPE (result) != AOP_STR)
9522 _startLazyDPSEvaluation ();
9523 /* if this is remateriazable */
9524 if (AOP_TYPE (result) == AOP_IMMD)
9526 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9527 if (AOP(result)->aopu.aop_immd.from_cast_remat)
9528 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
9530 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9533 { /* we need to get it byte by byte */
9534 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9535 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9536 if (options.model == MODEL_FLAT24) {
9537 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9538 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9540 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9543 _endLazyDPSEvaluation ();
9545 /* so dptr know contains the address */
9546 freeAsmop (result, NULL, ic, TRUE);
9547 aopOp (right, ic, FALSE, TRUE);
9549 /* if bit then unpack */
9550 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9551 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9554 size = AOP_SIZE (right);
9557 _startLazyDPSEvaluation ();
9560 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9566 emitcode ("lcall", "__gptrput");
9568 emitcode ("inc", "dptr");
9570 _endLazyDPSEvaluation ();
9573 freeAsmop (right, NULL, ic, TRUE);
9576 /*-----------------------------------------------------------------*/
9577 /* genPointerSet - stores the value into a pointer location */
9578 /*-----------------------------------------------------------------*/
9580 genPointerSet (iCode * ic)
9582 operand *right, *result;
9583 sym_link *type, *etype;
9586 D (emitcode (";", "genPointerSet ");
9589 right = IC_RIGHT (ic);
9590 result = IC_RESULT (ic);
9592 /* depending on the type of pointer we need to
9593 move it to the correct pointer register */
9594 type = operandType (result);
9595 etype = getSpec (type);
9596 /* if left is of type of pointer then it is simple */
9597 if (IS_PTR (type) && !IS_FUNC (type->next))
9599 p_type = DCL_TYPE (type);
9603 /* we have to go by the storage class */
9604 p_type = PTR_TYPE (SPEC_OCLS (etype));
9606 /* special case when cast remat */
9607 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9608 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9609 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9610 type = type = operandType (result);
9611 p_type = DCL_TYPE (type);
9614 /* now that we have the pointer type we assign
9615 the pointer values */
9621 genNearPointerSet (right, result, ic);
9625 genPagedPointerSet (right, result, ic);
9629 genFarPointerSet (right, result, ic);
9633 genGenPointerSet (right, result, ic);
9639 /*-----------------------------------------------------------------*/
9640 /* genIfx - generate code for Ifx statement */
9641 /*-----------------------------------------------------------------*/
9643 genIfx (iCode * ic, iCode * popIc)
9645 operand *cond = IC_COND (ic);
9648 D (emitcode (";", "genIfx "););
9650 aopOp (cond, ic, FALSE, FALSE);
9652 /* get the value into acc */
9653 if (AOP_TYPE (cond) != AOP_CRY)
9657 /* the result is now in the accumulator */
9658 freeAsmop (cond, NULL, ic, TRUE);
9660 /* if there was something to be popped then do it */
9664 /* if the condition is a bit variable */
9665 if (isbit && IS_ITEMP (cond) &&
9667 genIfxJump (ic, SPIL_LOC (cond)->rname);
9668 else if (isbit && !IS_ITEMP (cond))
9669 genIfxJump (ic, OP_SYMBOL (cond)->rname);
9671 genIfxJump (ic, "a");
9676 /*-----------------------------------------------------------------*/
9677 /* genAddrOf - generates code for address of */
9678 /*-----------------------------------------------------------------*/
9680 genAddrOf (iCode * ic)
9682 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9685 D (emitcode (";", "genAddrOf ");
9688 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9690 /* if the operand is on the stack then we
9691 need to get the stack offset of this
9695 /* if it has an offset then we need to compute
9699 emitcode ("mov", "a,_bp");
9700 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9701 aopPut (AOP (IC_RESULT (ic)), "a", 0);
9705 /* we can just move _bp */
9706 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9708 /* fill the result with zero */
9709 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9712 if (options.stack10bit && size < (FPTRSIZE - 1))
9715 "*** warning: pointer to stack var truncated.\n");
9722 if (options.stack10bit && offset == 2)
9724 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
9728 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9735 /* object not on stack then we need the name */
9736 size = AOP_SIZE (IC_RESULT (ic));
9741 char s[SDCC_NAME_MAX];
9743 sprintf (s, "#(%s >> %d)",
9747 sprintf (s, "#%s", sym->rname);
9748 aopPut (AOP (IC_RESULT (ic)), s, offset++);
9752 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9756 /*-----------------------------------------------------------------*/
9757 /* genArrayInit - generates code for address of */
9758 /*-----------------------------------------------------------------*/
9760 genArrayInit (iCode * ic)
9764 int elementSize = 0, eIndex;
9765 unsigned val, lastVal;
9767 operand *left=IC_LEFT(ic);
9769 D (emitcode (";", "genArrayInit "););
9771 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
9773 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
9775 // Load immediate value into DPTR.
9776 emitcode("mov", "dptr, %s",
9777 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
9779 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
9782 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9783 "Unexpected operand to genArrayInit.\n");
9786 // a regression because of SDCCcse.c:1.52
9787 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9788 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9789 if (options.model == MODEL_FLAT24)
9790 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9794 type = operandType(IC_LEFT(ic));
9796 if (type && type->next)
9798 elementSize = getSize(type->next);
9802 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9803 "can't determine element size in genArrayInit.\n");
9807 iLoop = IC_ARRAYILIST(ic);
9812 bool firstpass = TRUE;
9814 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
9815 iLoop->count, (int)iLoop->literalValue, elementSize);
9821 symbol *tlbl = NULL;
9823 count = ix > 256 ? 256 : ix;
9827 tlbl = newiTempLabel (NULL);
9828 if (firstpass || (count & 0xff))
9830 emitcode("mov", "b, #0x%x", count & 0xff);
9833 emitcode ("", "%05d$:", tlbl->key + 100);
9838 for (eIndex = 0; eIndex < elementSize; eIndex++)
9840 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
9843 emitcode("mov", "a, #0x%x", val);
9847 emitcode("movx", "@dptr, a");
9848 emitcode("inc", "dptr");
9853 emitcode("djnz", "b, %05d$", tlbl->key + 100);
9859 iLoop = iLoop->next;
9862 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
9865 /*-----------------------------------------------------------------*/
9866 /* genFarFarAssign - assignment when both are in far space */
9867 /*-----------------------------------------------------------------*/
9869 genFarFarAssign (operand * result, operand * right, iCode * ic)
9871 int size = AOP_SIZE (right);
9873 symbol *rSym = NULL;
9877 /* quick & easy case. */
9878 D(emitcode(";","genFarFarAssign (1 byte case)"););
9879 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9880 freeAsmop (right, NULL, ic, FALSE);
9881 /* now assign DPTR to result */
9883 aopOp(result, ic, FALSE, FALSE);
9885 aopPut(AOP(result), "a", 0);
9886 freeAsmop(result, NULL, ic, FALSE);
9890 /* See if we've got an underlying symbol to abuse. */
9891 if (IS_SYMOP(result) && OP_SYMBOL(result))
9893 if (IS_TRUE_SYMOP(result))
9895 rSym = OP_SYMBOL(result);
9897 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9899 rSym = OP_SYMBOL(result)->usl.spillLoc;
9903 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9905 /* We can use the '390 auto-toggle feature to good effect here. */
9907 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
9908 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
9909 emitcode ("mov", "dptr,#%s", rSym->rname);
9910 /* DP2 = result, DP1 = right, DP1 is current. */
9913 emitcode("movx", "a,@dptr");
9914 emitcode("movx", "@dptr,a");
9917 emitcode("inc", "dptr");
9918 emitcode("inc", "dptr");
9921 emitcode("mov", "dps, #0");
9922 freeAsmop (right, NULL, ic, FALSE);
9924 some alternative code for processors without auto-toggle
9925 no time to test now, so later well put in...kpb
9926 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
9927 emitcode("mov", "dps, #0x01"); /* Select DPTR2. */
9928 emitcode ("mov", "dptr,#%s", rSym->rname);
9929 /* DP2 = result, DP1 = right, DP1 is current. */
9933 emitcode("movx", "a,@dptr");
9935 emitcode("inc", "dptr");
9936 emitcode("inc", "dps");
9937 emitcode("movx", "@dptr,a");
9939 emitcode("inc", "dptr");
9940 emitcode("inc", "dps");
9942 emitcode("mov", "dps, #0");
9943 freeAsmop (right, NULL, ic, FALSE);
9948 D (emitcode (";", "genFarFarAssign"););
9949 aopOp (result, ic, TRUE, TRUE);
9951 _startLazyDPSEvaluation ();
9955 aopPut (AOP (result),
9956 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9959 _endLazyDPSEvaluation ();
9960 freeAsmop (result, NULL, ic, FALSE);
9961 freeAsmop (right, NULL, ic, FALSE);
9965 /*-----------------------------------------------------------------*/
9966 /* genAssign - generate code for assignment */
9967 /*-----------------------------------------------------------------*/
9969 genAssign (iCode * ic)
9971 operand *result, *right;
9973 unsigned long lit = 0L;
9975 D (emitcode (";", "genAssign ");
9978 result = IC_RESULT (ic);
9979 right = IC_RIGHT (ic);
9981 /* if they are the same */
9982 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9985 aopOp (right, ic, FALSE, FALSE);
9987 emitcode (";", "genAssign: resultIsFar = %s",
9988 isOperandInFarSpace (result) ?
9991 /* special case both in far space */
9992 if ((AOP_TYPE (right) == AOP_DPTR ||
9993 AOP_TYPE (right) == AOP_DPTR2) &&
9994 /* IS_TRUE_SYMOP(result) && */
9995 isOperandInFarSpace (result))
9997 genFarFarAssign (result, right, ic);
10001 aopOp (result, ic, TRUE, FALSE);
10003 /* if they are the same registers */
10004 if (sameRegs (AOP (right), AOP (result)))
10007 /* if the result is a bit */
10008 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10010 /* if the right size is a literal then
10011 we know what the value is */
10012 if (AOP_TYPE (right) == AOP_LIT)
10014 if (((int) operandLitValue (right)))
10015 aopPut (AOP (result), one, 0);
10017 aopPut (AOP (result), zero, 0);
10021 /* the right is also a bit variable */
10022 if (AOP_TYPE (right) == AOP_CRY)
10024 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10025 aopPut (AOP (result), "c", 0);
10029 /* we need to or */
10031 aopPut (AOP (result), "a", 0);
10035 /* bit variables done */
10037 size = AOP_SIZE (result);
10039 if (AOP_TYPE (right) == AOP_LIT)
10040 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10043 (AOP_TYPE (result) != AOP_REG) &&
10044 (AOP_TYPE (right) == AOP_LIT) &&
10045 !IS_FLOAT (operandType (right)))
10047 _startLazyDPSEvaluation ();
10048 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10050 aopPut (AOP (result),
10051 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10056 /* And now fill the rest with zeros. */
10059 emitcode ("clr", "a");
10063 aopPut (AOP (result), "a", offset++);
10065 _endLazyDPSEvaluation ();
10069 _startLazyDPSEvaluation ();
10072 aopPut (AOP (result),
10073 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10077 _endLazyDPSEvaluation ();
10081 freeAsmop (right, NULL, ic, FALSE);
10082 freeAsmop (result, NULL, ic, TRUE);
10085 /*-----------------------------------------------------------------*/
10086 /* genJumpTab - generates code for jump table */
10087 /*-----------------------------------------------------------------*/
10089 genJumpTab (iCode * ic)
10094 D (emitcode (";", "genJumpTab ");
10097 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10098 /* get the condition into accumulator */
10099 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10101 /* multiply by four! */
10102 emitcode ("add", "a,acc");
10103 emitcode ("add", "a,acc");
10104 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10106 jtab = newiTempLabel (NULL);
10107 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10108 emitcode ("jmp", "@a+dptr");
10109 emitcode ("", "%05d$:", jtab->key + 100);
10110 /* now generate the jump labels */
10111 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10112 jtab = setNextItem (IC_JTLABELS (ic)))
10113 emitcode ("ljmp", "%05d$", jtab->key + 100);
10117 /*-----------------------------------------------------------------*/
10118 /* genCast - gen code for casting */
10119 /*-----------------------------------------------------------------*/
10121 genCast (iCode * ic)
10123 operand *result = IC_RESULT (ic);
10124 sym_link *ctype = operandType (IC_LEFT (ic));
10125 sym_link *rtype = operandType (IC_RIGHT (ic));
10126 operand *right = IC_RIGHT (ic);
10129 D (emitcode (";", "genCast ");
10132 /* if they are equivalent then do nothing */
10133 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10136 aopOp (right, ic, FALSE, FALSE);
10137 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10139 /* if the result is a bit */
10140 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10141 if (IS_BITVAR(OP_SYMBOL(result)->type))
10143 /* if the right size is a literal then
10144 we know what the value is */
10145 if (AOP_TYPE (right) == AOP_LIT)
10147 if (((int) operandLitValue (right)))
10148 aopPut (AOP (result), one, 0);
10150 aopPut (AOP (result), zero, 0);
10155 /* the right is also a bit variable */
10156 if (AOP_TYPE (right) == AOP_CRY)
10158 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10159 aopPut (AOP (result), "c", 0);
10163 /* we need to or */
10165 aopPut (AOP (result), "a", 0);
10169 /* if they are the same size : or less */
10170 if (AOP_SIZE (result) <= AOP_SIZE (right))
10173 /* if they are in the same place */
10174 if (sameRegs (AOP (right), AOP (result)))
10177 /* if they in different places then copy */
10178 size = AOP_SIZE (result);
10180 _startLazyDPSEvaluation ();
10183 aopPut (AOP (result),
10184 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10188 _endLazyDPSEvaluation ();
10193 /* if the result is of type pointer */
10194 if (IS_PTR (ctype))
10198 sym_link *type = operandType (right);
10200 /* pointer to generic pointer */
10201 if (IS_GENPTR (ctype))
10207 p_type = DCL_TYPE (type);
10211 #if OLD_CAST_BEHAVIOR
10212 /* KV: we are converting a non-pointer type to
10213 * a generic pointer. This (ifdef'd out) code
10214 * says that the resulting generic pointer
10215 * should have the same class as the storage
10216 * location of the non-pointer variable.
10218 * For example, converting an int (which happens
10219 * to be stored in DATA space) to a pointer results
10220 * in a DATA generic pointer; if the original int
10221 * in XDATA space, so will be the resulting pointer.
10223 * I don't like that behavior, and thus this change:
10224 * all such conversions will be forced to XDATA and
10225 * throw a warning. If you want some non-XDATA
10226 * type, or you want to suppress the warning, you
10227 * must go through an intermediate cast, like so:
10229 * char _generic *gp = (char _xdata *)(intVar);
10231 sym_link *etype = getSpec (type);
10233 /* we have to go by the storage class */
10234 if (SPEC_OCLS (etype) != generic)
10236 p_type = PTR_TYPE (SPEC_OCLS (etype));
10241 /* Converting unknown class (i.e. register variable)
10242 * to generic pointer. This is not good, but
10243 * we'll make a guess (and throw a warning).
10246 werror (W_INT_TO_GEN_PTR_CAST);
10250 /* the first two bytes are known */
10251 size = GPTRSIZE - 1;
10253 _startLazyDPSEvaluation ();
10256 aopPut (AOP (result),
10257 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10261 _endLazyDPSEvaluation ();
10263 /* the last byte depending on type */
10281 /* this should never happen */
10282 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10283 "got unknown pointer type");
10286 aopPut (AOP (result), l, GPTRSIZE - 1);
10290 /* just copy the pointers */
10291 size = AOP_SIZE (result);
10293 _startLazyDPSEvaluation ();
10296 aopPut (AOP (result),
10297 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10301 _endLazyDPSEvaluation ();
10305 /* so we now know that the size of destination is greater
10306 than the size of the source */
10307 /* we move to result for the size of source */
10308 size = AOP_SIZE (right);
10310 _startLazyDPSEvaluation ();
10313 aopPut (AOP (result),
10314 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10318 _endLazyDPSEvaluation ();
10320 /* now depending on the sign of the source && destination */
10321 size = AOP_SIZE (result) - AOP_SIZE (right);
10322 /* if unsigned or not an integral type */
10323 /* also, if the source is a bit, we don't need to sign extend, because
10324 * it can't possibly have set the sign bit.
10326 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10330 aopPut (AOP (result), zero, offset++);
10335 /* we need to extend the sign :{ */
10336 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10337 FALSE, FALSE, TRUE);
10339 emitcode ("rlc", "a");
10340 emitcode ("subb", "a,acc");
10342 aopPut (AOP (result), "a", offset++);
10345 /* we are done hurray !!!! */
10348 freeAsmop (right, NULL, ic, TRUE);
10349 freeAsmop (result, NULL, ic, TRUE);
10353 /*-----------------------------------------------------------------*/
10354 /* genDjnz - generate decrement & jump if not zero instrucion */
10355 /*-----------------------------------------------------------------*/
10357 genDjnz (iCode * ic, iCode * ifx)
10359 symbol *lbl, *lbl1;
10363 /* if the if condition has a false label
10364 then we cannot save */
10365 if (IC_FALSE (ifx))
10368 /* if the minus is not of the form
10370 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10371 !IS_OP_LITERAL (IC_RIGHT (ic)))
10374 if (operandLitValue (IC_RIGHT (ic)) != 1)
10377 /* if the size of this greater than one then no
10379 if (getSize (operandType (IC_RESULT (ic))) > 1)
10382 /* otherwise we can save BIG */
10383 D(emitcode(";", "genDjnz"););
10385 lbl = newiTempLabel (NULL);
10386 lbl1 = newiTempLabel (NULL);
10388 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10390 if (AOP_NEEDSACC(IC_RESULT(ic)))
10392 /* If the result is accessed indirectly via
10393 * the accumulator, we must explicitly write
10394 * it back after the decrement.
10396 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10398 if (strcmp(rByte, "a"))
10400 /* Something is hopelessly wrong */
10401 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10402 __FILE__, __LINE__);
10403 /* We can just give up; the generated code will be inefficient,
10404 * but what the hey.
10406 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10409 emitcode ("dec", "%s", rByte);
10410 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10411 emitcode ("jnz", "%05d$", lbl->key + 100);
10413 else if (IS_AOP_PREG (IC_RESULT (ic)))
10415 emitcode ("dec", "%s",
10416 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10417 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10418 emitcode ("jnz", "%05d$", lbl->key + 100);
10422 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10425 emitcode ("sjmp", "%05d$", lbl1->key + 100);
10426 emitcode ("", "%05d$:", lbl->key + 100);
10427 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10428 emitcode ("", "%05d$:", lbl1->key + 100);
10430 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10431 ifx->generated = 1;
10435 /*-----------------------------------------------------------------*/
10436 /* genReceive - generate code for a receive iCode */
10437 /*-----------------------------------------------------------------*/
10439 genReceive (iCode * ic)
10442 D (emitcode (";", "genReceive ");
10445 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10446 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10447 IS_TRUE_SYMOP (IC_RESULT (ic))))
10449 int size = getSize (operandType (IC_RESULT (ic)));
10450 int offset = fReturnSizeDS390 - size;
10453 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10454 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10457 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10458 size = AOP_SIZE (IC_RESULT (ic));
10462 emitcode ("pop", "acc");
10463 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10470 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10472 assignResultValue (IC_RESULT (ic));
10475 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10478 /*-----------------------------------------------------------------*/
10479 /* gen390Code - generate code for Dallas 390 based controllers */
10480 /*-----------------------------------------------------------------*/
10482 gen390Code (iCode * lic)
10487 lineHead = lineCurr = NULL;
10489 if (options.model == MODEL_FLAT24) {
10490 fReturnSizeDS390 = 5;
10491 fReturn = fReturn24;
10493 fReturnSizeDS390 = 4;
10494 fReturn = fReturn16;
10495 options.stack10bit=0;
10499 /* print the allocation information */
10501 printAllocInfo (currFunc, codeOutFile);
10503 /* if debug information required */
10504 if (options.debug && currFunc)
10506 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
10508 if (IS_STATIC (currFunc->etype))
10509 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
10511 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
10514 /* stack pointer name */
10515 if (options.useXstack)
10521 for (ic = lic; ic; ic = ic->next)
10524 if (cln != ic->lineno)
10529 emitcode ("", "C$%s$%d$%d$%d ==.",
10530 FileBaseName (ic->filename), ic->lineno,
10531 ic->level, ic->block);
10534 emitcode (";", "%s %d", ic->filename, ic->lineno);
10537 /* if the result is marked as
10538 spilt and rematerializable or code for
10539 this has already been generated then
10541 if (resultRemat (ic) || ic->generated)
10544 /* depending on the operation */
10564 /* IPOP happens only when trying to restore a
10565 spilt live range, if there is an ifx statement
10566 following this pop then the if statement might
10567 be using some of the registers being popped which
10568 would destory the contents of the register so
10569 we need to check for this condition and handle it */
10571 ic->next->op == IFX &&
10572 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10573 genIfx (ic->next, ic);
10591 genEndFunction (ic);
10611 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10628 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10632 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10639 /* note these two are xlated by algebraic equivalence
10640 during parsing SDCC.y */
10641 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10642 "got '>=' or '<=' shouldn't have come here");
10646 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10658 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10662 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10666 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10690 genRightShift (ic);
10693 case GET_VALUE_AT_ADDRESS:
10694 genPointerGet (ic);
10698 if (POINTER_SET (ic))
10699 genPointerSet (ic);
10725 addSet (&_G.sendSet, ic);
10738 /* now we are ready to call the
10739 peep hole optimizer */
10740 if (!options.nopeep)
10741 peepHole (&lineHead);
10743 /* now do the actual printing */
10744 printLine (lineHead, codeOutFile);