1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for DS80C390
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 DS390 adaptation by Kevin Vigor <kevin@vigor.nu>
9 This program is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 In other words, you are welcome to use, share and improve this program.
24 You are forbidden to forbid anyone else to use, share and improve
25 what you give them. Help stamp out software-hoarding!
26 -------------------------------------------------------------------------*/
36 #include "SDCCglobl.h"
39 #ifdef HAVE_SYS_ISA_DEFS_H
40 #include <sys/isa_defs.h>
42 #ifdef HAVE_MACHINE_ENDIAN_H
43 #include <machine/endian.h>
48 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
49 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
50 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
56 #define BETTER_LITERAL_SHIFT
58 char *aopLiteral (value * val, int offset);
60 /* this is the down and dirty file with all kinds of
61 kludgy & hacky stuff. This is what it is all about
62 CODE GENERATION for a specific MCU . some of the
63 routines may be reusable, will have to see */
65 static char *zero = "#0x00";
66 static char *one = "#0x01";
71 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
72 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
74 unsigned fReturnSizeDS390 = 5; /* shared with ralloc.c */
75 static char *fReturn24[] =
76 {"dpl", "dph", "dpx", "b", "a"};
77 static char *fReturn16[] =
78 {"dpl", "dph", "b", "a"};
79 static char **fReturn = fReturn24;
80 static char *accUse[] =
83 static short rbank = -1;
97 static void saveRBank (int, iCode *, bool);
99 #define RESULTONSTACK(x) \
100 (IC_RESULT(x) && IC_RESULT(x)->aop && \
101 IC_RESULT(x)->aop->type == AOP_STK )
103 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
104 #define MOVA(x) { char *_mova_tmp = strdup(x); \
105 if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
107 emitcode("mov","a,%s",_mova_tmp); \
111 #define CLRC emitcode("clr","c")
112 #define SETC emitcode("setb","c")
114 // A scratch register which will be used to hold
115 // result bytes from operands in far space via DPTR2.
116 #define DP2_RESULT_REG "ap"
118 static lineNode *lineHead = NULL;
119 static lineNode *lineCurr = NULL;
121 static unsigned char SLMask[] =
122 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
123 0xE0, 0xC0, 0x80, 0x00};
124 static unsigned char SRMask[] =
125 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
126 0x07, 0x03, 0x01, 0x00};
133 /*-----------------------------------------------------------------*/
134 /* emitcode - writes the code into a file : for now it is simple */
135 /*-----------------------------------------------------------------*/
137 emitcode (char *inst, char *fmt,...)
140 char lb[INITIAL_INLINEASM];
148 sprintf (lb, "%s\t", inst);
150 sprintf (lb, "%s", inst);
151 vsprintf (lb + (strlen (lb)), fmt, ap);
154 vsprintf (lb, fmt, ap);
156 while (isspace (*lbp))
160 lineCurr = (lineCurr ?
161 connectLine (lineCurr, newLineNode (lb)) :
162 (lineHead = newLineNode (lb)));
163 lineCurr->isInline = _G.inLine;
164 lineCurr->isDebug = _G.debugLine;
168 /*-----------------------------------------------------------------*/
169 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
170 /*-----------------------------------------------------------------*/
172 getFreePtr (iCode * ic, asmop ** aopp, bool result)
174 bool r0iu = FALSE, r1iu = FALSE;
175 bool r0ou = FALSE, r1ou = FALSE;
177 /* the logic: if r0 & r1 used in the instruction
178 then we are in trouble otherwise */
180 /* first check if r0 & r1 are used by this
181 instruction, in which case we are in trouble */
182 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
183 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
188 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
189 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
191 /* if no usage of r0 then return it */
194 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
195 (*aopp)->type = AOP_R0;
197 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
200 /* if no usage of r1 then return it */
203 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
204 (*aopp)->type = AOP_R1;
206 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
209 /* now we know they both have usage */
210 /* if r0 not used in this instruction */
213 /* push it if not already pushed */
216 emitcode ("push", "%s",
217 ds390_regWithIdx (R0_IDX)->dname);
221 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
222 (*aopp)->type = AOP_R0;
224 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
227 /* if r1 not used then */
231 /* push it if not already pushed */
234 emitcode ("push", "%s",
235 ds390_regWithIdx (R1_IDX)->dname);
239 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
240 (*aopp)->type = AOP_R1;
241 return ds390_regWithIdx (R1_IDX);
245 /* I said end of world but not quite end of world yet */
246 /* if this is a result then we can push it on the stack */
249 (*aopp)->type = AOP_STK;
253 /* other wise this is true end of the world */
254 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
255 "getFreePtr should never reach here");
259 /*-----------------------------------------------------------------*/
260 /* newAsmop - creates a new asmOp */
261 /*-----------------------------------------------------------------*/
263 newAsmop (short type)
267 aop = Safe_calloc (1, sizeof (asmop));
272 static int _currentDPS; /* Current processor DPS. */
273 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
274 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
276 /*-----------------------------------------------------------------*/
277 /* genSetDPTR: generate code to select which DPTR is in use (zero */
278 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
279 /* alternate DPTR (DPL1/DPH1/DPX1). */
280 /*-----------------------------------------------------------------*/
285 /* If we are doing lazy evaluation, simply note the desired
286 * change, but don't emit any code yet.
296 emitcode ("mov", "dps, #0x00");
301 emitcode ("mov", "dps, #0x01");
305 /*-----------------------------------------------------------------*/
306 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
308 /* Any code that operates on DPTR (NB: not on the individual */
309 /* components, like DPH) *must* call _flushLazyDPS() before using */
310 /* DPTR within a lazy DPS evaluation block. */
312 /* Note that aopPut and aopGet already contain the proper calls to */
313 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
314 /* DPS evaluation block. */
316 /* Also, _flushLazyDPS must be called before any flow control */
317 /* operations that could potentially branch out of the block. */
319 /* Lazy DPS evaluation is simply an optimization (though an */
320 /* important one), so if in doubt, leave it out. */
321 /*-----------------------------------------------------------------*/
323 _startLazyDPSEvaluation (void)
327 #ifdef BETTER_LITERAL_SHIFT
334 /*-----------------------------------------------------------------*/
335 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
336 /* desired one. Call before using DPTR within a lazy DPS evaluation */
338 /*-----------------------------------------------------------------*/
348 if (_desiredDPS != _currentDPS)
352 emitcode ("inc", "dps");
356 emitcode ("dec", "dps");
358 _currentDPS = _desiredDPS;
362 /*-----------------------------------------------------------------*/
363 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
365 /* Forces us back to the safe state (standard DPTR selected). */
366 /*-----------------------------------------------------------------*/
368 _endLazyDPSEvaluation (void)
370 #ifdef BETTER_LITERAL_SHIFT
389 /*-----------------------------------------------------------------*/
390 /* pointerCode - returns the code for a pointer type */
391 /*-----------------------------------------------------------------*/
393 pointerCode (sym_link * etype)
396 return PTR_TYPE (SPEC_OCLS (etype));
400 /*-----------------------------------------------------------------*/
401 /* aopForSym - for a true symbol */
402 /*-----------------------------------------------------------------*/
404 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
407 memmap *space = SPEC_OCLS (sym->etype);
409 /* if already has one */
413 /* assign depending on the storage class */
414 /* if it is on the stack or indirectly addressable */
415 /* space we need to assign either r0 or r1 to it */
416 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
418 sym->aop = aop = newAsmop (0);
419 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
420 aop->size = getSize (sym->type);
422 /* now assign the address of the variable to
423 the pointer register */
424 if (aop->type != AOP_STK)
430 emitcode ("push", "acc");
432 emitcode ("mov", "a,_bp");
433 emitcode ("add", "a,#0x%02x",
435 ((char) (sym->stack - _G.nRegsSaved)) :
436 ((char) sym->stack)) & 0xff);
437 emitcode ("mov", "%s,a",
438 aop->aopu.aop_ptr->name);
441 emitcode ("pop", "acc");
444 emitcode ("mov", "%s,#%s",
445 aop->aopu.aop_ptr->name,
447 aop->paged = space->paged;
450 aop->aopu.aop_stk = sym->stack;
454 if (sym->onStack && options.stack10bit)
456 /* It's on the 10 bit stack, which is located in
461 emitcode ("push", "acc");
463 emitcode ("mov", "a,_bp");
464 emitcode ("add", "a,#0x%02x",
466 ((char) (sym->stack - _G.nRegsSaved)) :
467 ((char) sym->stack)) & 0xff);
471 if (options.model == MODEL_FLAT24)
472 emitcode ("mov", "dpx1,#0x40");
474 emitcode ("mov", "dph1,#0x00");
475 emitcode ("mov", "dpl1, a");
479 if (options.model == MODEL_FLAT24)
480 emitcode ("mov", "dpx,#0x40");
481 emitcode ("mov", "dph,#0x00");
482 emitcode ("mov", "dpl, a");
486 emitcode ("pop", "acc");
488 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
489 aop->size = getSize (sym->type);
493 /* if in bit space */
494 if (IN_BITSPACE (space))
496 sym->aop = aop = newAsmop (AOP_CRY);
497 aop->aopu.aop_dir = sym->rname;
498 aop->size = getSize (sym->type);
501 /* if it is in direct space */
502 if (IN_DIRSPACE (space))
504 sym->aop = aop = newAsmop (AOP_DIR);
505 aop->aopu.aop_dir = sym->rname;
506 aop->size = getSize (sym->type);
510 /* special case for a function */
511 if (IS_FUNC (sym->type))
513 sym->aop = aop = newAsmop (AOP_IMMD);
514 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
515 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
516 aop->size = FPTRSIZE;
520 /* only remaining is far space */
521 /* in which case DPTR gets the address */
522 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
527 emitcode ("mov", "dptr,#%s", sym->rname);
532 emitcode ("mov", "dptr,#%s", sym->rname);
534 aop->size = getSize (sym->type);
536 /* if it is in code space */
537 if (IN_CODESPACE (space))
543 /*-----------------------------------------------------------------*/
544 /* aopForRemat - rematerialzes an object */
545 /*-----------------------------------------------------------------*/
547 aopForRemat (symbol * sym)
549 iCode *ic = sym->rematiCode;
550 asmop *aop = newAsmop (AOP_IMMD);
557 val += (int) operandLitValue (IC_RIGHT (ic));
558 else if (ic->op == '-')
559 val -= (int) operandLitValue (IC_RIGHT (ic));
560 else if (IS_CAST_ICODE(ic)) {
561 sym_link *from_type = operandType(IC_RIGHT(ic));
562 aop->aopu.aop_immd.from_cast_remat = 1;
563 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
564 ptr_type = DCL_TYPE(from_type);
568 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
572 sprintf (buffer, "(%s %c 0x%04x)",
573 OP_SYMBOL (IC_LEFT (ic))->rname,
574 val >= 0 ? '+' : '-',
577 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
579 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
580 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
581 /* set immd2 field if required */
582 if (aop->aopu.aop_immd.from_cast_remat) {
583 sprintf(buffer,"#0x%02x",ptr_type);
584 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
585 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
591 /*-----------------------------------------------------------------*/
592 /* regsInCommon - two operands have some registers in common */
593 /*-----------------------------------------------------------------*/
595 regsInCommon (operand * op1, operand * op2)
600 /* if they have registers in common */
601 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
604 sym1 = OP_SYMBOL (op1);
605 sym2 = OP_SYMBOL (op2);
607 if (sym1->nRegs == 0 || sym2->nRegs == 0)
610 for (i = 0; i < sym1->nRegs; i++)
616 for (j = 0; j < sym2->nRegs; j++)
621 if (sym2->regs[j] == sym1->regs[i])
629 /*-----------------------------------------------------------------*/
630 /* operandsEqu - equivalent */
631 /*-----------------------------------------------------------------*/
633 operandsEqu (operand * op1, operand * op2)
637 /* if they not symbols */
638 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
641 sym1 = OP_SYMBOL (op1);
642 sym2 = OP_SYMBOL (op2);
644 /* if both are itemps & one is spilt
645 and the other is not then false */
646 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
647 sym1->isspilt != sym2->isspilt)
650 /* if they are the same */
654 if (strcmp (sym1->rname, sym2->rname) == 0)
658 /* if left is a tmp & right is not */
659 if (IS_ITEMP (op1) &&
662 (sym1->usl.spillLoc == sym2))
665 if (IS_ITEMP (op2) &&
669 (sym2->usl.spillLoc == sym1))
675 /*-----------------------------------------------------------------*/
676 /* sameRegs - two asmops have the same registers */
677 /*-----------------------------------------------------------------*/
679 sameRegs (asmop * aop1, asmop * aop2)
685 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
692 if (aop1->type != AOP_REG ||
693 aop2->type != AOP_REG)
696 if (aop1->size != aop2->size)
699 for (i = 0; i < aop1->size; i++)
700 if (aop1->aopu.aop_reg[i] !=
701 aop2->aopu.aop_reg[i])
707 /*-----------------------------------------------------------------*/
708 /* aopOp - allocates an asmop for an operand : */
709 /*-----------------------------------------------------------------*/
711 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
720 /* if this a literal */
721 if (IS_OP_LITERAL (op))
723 op->aop = aop = newAsmop (AOP_LIT);
724 aop->aopu.aop_lit = op->operand.valOperand;
725 aop->size = getSize (operandType (op));
729 /* if already has a asmop then continue */
733 /* if the underlying symbol has a aop */
734 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
736 op->aop = OP_SYMBOL (op)->aop;
740 /* if this is a true symbol */
741 if (IS_TRUE_SYMOP (op))
743 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
747 /* this is a temporary : this has
753 e) can be a return use only */
755 sym = OP_SYMBOL (op);
758 /* if the type is a conditional */
759 if (sym->regType == REG_CND)
761 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
766 /* if it is spilt then two situations
768 b) has a spill location */
769 if (sym->isspilt || sym->nRegs == 0)
772 /* rematerialize it NOW */
775 sym->aop = op->aop = aop =
777 aop->size = getSize (sym->type);
784 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
785 aop->size = getSize (sym->type);
786 for (i = 0; i < 2; i++)
787 aop->aopu.aop_str[i] = accUse[i];
797 /* a AOP_STR uses DPTR, but DPTR is already in use;
800 fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use!\n");
803 aop = op->aop = sym->aop = newAsmop (AOP_STR);
804 aop->size = getSize (sym->type);
805 for (i = 0; i < (int) fReturnSizeDS390; i++)
806 aop->aopu.aop_str[i] = fReturn[i];
810 /* else spill location */
811 sym->aop = op->aop = aop =
812 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
813 aop->size = getSize (sym->type);
817 /* must be in a register */
818 sym->aop = op->aop = aop = newAsmop (AOP_REG);
819 aop->size = sym->nRegs;
820 for (i = 0; i < sym->nRegs; i++)
821 aop->aopu.aop_reg[i] = sym->regs[i];
824 /*-----------------------------------------------------------------*/
825 /* freeAsmop - free up the asmop given to an operand */
826 /*----------------------------------------------------------------*/
828 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
845 /* depending on the asmop type only three cases need work AOP_RO
846 , AOP_R1 && AOP_STK */
854 emitcode ("pop", "ar0");
858 bitVectUnSetBit (ic->rUsed, R0_IDX);
866 emitcode ("pop", "ar1");
870 bitVectUnSetBit (ic->rUsed, R1_IDX);
876 int stk = aop->aopu.aop_stk + aop->size;
877 bitVectUnSetBit (ic->rUsed, R0_IDX);
878 bitVectUnSetBit (ic->rUsed, R1_IDX);
880 getFreePtr (ic, &aop, FALSE);
882 if (options.stack10bit)
884 /* I'm not sure what to do here yet... */
887 "*** Warning: probably generating bad code for "
888 "10 bit stack mode.\n");
893 emitcode ("mov", "a,_bp");
894 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
895 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
899 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
904 emitcode ("pop", "acc");
905 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
908 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
911 freeAsmop (op, NULL, ic, TRUE);
914 emitcode ("pop", "ar0");
920 emitcode ("pop", "ar1");
927 /* all other cases just dealloc */
933 OP_SYMBOL (op)->aop = NULL;
934 /* if the symbol has a spill */
936 SPIL_LOC (op)->aop = NULL;
941 /*------------------------------------------------------------------*/
942 /* aopGet - for fetching value of the aop */
944 /* Set canClobberACC if you are sure it is OK to clobber the value */
945 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
946 /* just less efficient. */
947 /*------------------------------------------------------------------*/
959 /* offset is greater than
961 if (offset > (aop->size - 1) &&
962 aop->type != AOP_LIT)
965 /* depending on type */
971 /* if we need to increment it */
972 while (offset > aop->coff)
974 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
978 while (offset < aop->coff)
980 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
987 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
988 return (dname ? "acc" : "a");
990 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
991 rs = Safe_calloc (1, strlen (s) + 1);
998 if (aop->type == AOP_DPTR2)
1004 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1010 while (offset > aop->coff)
1012 emitcode ("inc", "dptr");
1016 while (offset < aop->coff)
1018 emitcode ("lcall", "__decdptr");
1025 emitcode ("clr", "a");
1026 emitcode ("movc", "a,@a+dptr");
1030 emitcode ("movx", "a,@dptr");
1033 if (aop->type == AOP_DPTR2)
1039 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1040 return DP2_RESULT_REG;
1043 return (dname ? "acc" : "a");
1046 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1047 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1049 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1051 sprintf (s, "#(%s >> %d)",
1052 aop->aopu.aop_immd.aop_immd1,
1056 aop->aopu.aop_immd.aop_immd1);
1057 rs = Safe_calloc (1, strlen (s) + 1);
1063 sprintf (s, "(%s + %d)",
1067 sprintf (s, "%s", aop->aopu.aop_dir);
1068 rs = Safe_calloc (1, strlen (s) + 1);
1074 return aop->aopu.aop_reg[offset]->dname;
1076 return aop->aopu.aop_reg[offset]->name;
1079 emitcode ("clr", "a");
1080 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1081 emitcode ("rlc", "a");
1082 return (dname ? "acc" : "a");
1085 if (!offset && dname)
1087 return aop->aopu.aop_str[offset];
1090 return aopLiteral (aop->aopu.aop_lit, offset);
1094 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1098 return aop->aopu.aop_str[offset];
1102 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1103 "aopget got unsupported aop->type");
1106 /*-----------------------------------------------------------------*/
1107 /* aopPut - puts a string for a aop */
1108 /*-----------------------------------------------------------------*/
1110 aopPut (asmop * aop, char *s, int offset)
1114 if (aop->size && offset > (aop->size - 1))
1116 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1117 "aopPut got offset > aop->size");
1121 /* will assign value to value */
1122 /* depending on where it is ofcourse */
1127 sprintf (d, "(%s + %d)",
1128 aop->aopu.aop_dir, offset);
1130 sprintf (d, "%s", aop->aopu.aop_dir);
1133 emitcode ("mov", "%s,%s", d, s);
1138 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1139 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1142 strcmp (s, "r0") == 0 ||
1143 strcmp (s, "r1") == 0 ||
1144 strcmp (s, "r2") == 0 ||
1145 strcmp (s, "r3") == 0 ||
1146 strcmp (s, "r4") == 0 ||
1147 strcmp (s, "r5") == 0 ||
1148 strcmp (s, "r6") == 0 ||
1149 strcmp (s, "r7") == 0)
1150 emitcode ("mov", "%s,%s",
1151 aop->aopu.aop_reg[offset]->dname, s);
1153 emitcode ("mov", "%s,%s",
1154 aop->aopu.aop_reg[offset]->name, s);
1161 if (aop->type == AOP_DPTR2)
1169 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1170 "aopPut writting to code space");
1174 while (offset > aop->coff)
1177 emitcode ("inc", "dptr");
1180 while (offset < aop->coff)
1183 emitcode ("lcall", "__decdptr");
1188 /* if not in accumulater */
1191 emitcode ("movx", "@dptr,a");
1193 if (aop->type == AOP_DPTR2)
1201 while (offset > aop->coff)
1204 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1206 while (offset < aop->coff)
1209 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1216 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1222 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1224 else if (strcmp (s, "r0") == 0 ||
1225 strcmp (s, "r1") == 0 ||
1226 strcmp (s, "r2") == 0 ||
1227 strcmp (s, "r3") == 0 ||
1228 strcmp (s, "r4") == 0 ||
1229 strcmp (s, "r5") == 0 ||
1230 strcmp (s, "r6") == 0 ||
1231 strcmp (s, "r7") == 0)
1234 sprintf (buffer, "a%s", s);
1235 emitcode ("mov", "@%s,%s",
1236 aop->aopu.aop_ptr->name, buffer);
1239 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1244 if (strcmp (s, "a") == 0)
1245 emitcode ("push", "acc");
1247 emitcode ("push", "%s", s);
1252 /* if bit variable */
1253 if (!aop->aopu.aop_dir)
1255 emitcode ("clr", "a");
1256 emitcode ("rlc", "a");
1261 emitcode ("clr", "%s", aop->aopu.aop_dir);
1263 emitcode ("setb", "%s", aop->aopu.aop_dir);
1264 else if (!strcmp (s, "c"))
1265 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1268 if (strcmp (s, "a"))
1273 symbol *lbl = newiTempLabel (NULL);
1274 emitcode ("clr", "c");
1275 emitcode ("jz", "%05d$", lbl->key + 100);
1276 emitcode ("cpl", "c");
1277 emitcode ("", "%05d$:", lbl->key + 100);
1278 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1286 if (strcmp (aop->aopu.aop_str[offset], s))
1287 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1292 if (!offset && (strcmp (s, "acc") == 0))
1295 if (strcmp (aop->aopu.aop_str[offset], s))
1296 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1300 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1301 "aopPut got unsupported aop->type");
1308 /*--------------------------------------------------------------------*/
1309 /* reAdjustPreg - points a register back to where it should (coff==0) */
1310 /*--------------------------------------------------------------------*/
1312 reAdjustPreg (asmop * aop)
1314 if ((aop->coff==0) || (aop->size <= 1)) {
1323 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1327 if (aop->type == AOP_DPTR2)
1334 emitcode ("lcall", "__decdptr");
1337 if (aop->type == AOP_DPTR2)
1347 #define AOP(op) op->aop
1348 #define AOP_TYPE(op) AOP(op)->type
1349 #define AOP_SIZE(op) AOP(op)->size
1350 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1351 AOP_TYPE(x) == AOP_R0))
1353 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1354 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1357 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1358 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1359 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1361 /* Workaround for DS80C390 bug: div ab may return bogus results
1362 * if A is accessed in instruction immediately before the div.
1364 * Will be fixed in B4 rev of processor, Dallas claims.
1367 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1368 if (!AOP_NEEDSACC(RIGHT)) \
1370 /* We can load A first, then B, since \
1371 * B (the RIGHT operand) won't clobber A, \
1372 * thus avoiding touching A right before the div. \
1374 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1375 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1377 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1381 /* Just stuff in a nop after loading A. */ \
1382 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1383 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1385 emitcode("nop", "; workaround for DS80C390 div bug."); \
1388 /*-----------------------------------------------------------------*/
1389 /* genNotFloat - generates not for float operations */
1390 /*-----------------------------------------------------------------*/
1392 genNotFloat (operand * op, operand * res)
1398 D (emitcode (";", "genNotFloat ");
1401 /* we will put 127 in the first byte of
1403 aopPut (AOP (res), "#127", 0);
1404 size = AOP_SIZE (op) - 1;
1407 _startLazyDPSEvaluation ();
1408 l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1413 emitcode ("orl", "a,%s",
1415 offset++, FALSE, FALSE, FALSE));
1417 _endLazyDPSEvaluation ();
1419 tlbl = newiTempLabel (NULL);
1420 aopPut (res->aop, one, 1);
1421 emitcode ("jz", "%05d$", (tlbl->key + 100));
1422 aopPut (res->aop, zero, 1);
1423 emitcode ("", "%05d$:", (tlbl->key + 100));
1425 size = res->aop->size - 2;
1427 /* put zeros in the rest */
1429 aopPut (res->aop, zero, offset++);
1432 /*-----------------------------------------------------------------*/
1433 /* opIsGptr: returns non-zero if the passed operand is */
1434 /* a generic pointer type. */
1435 /*-----------------------------------------------------------------*/
1437 opIsGptr (operand * op)
1439 sym_link *type = operandType (op);
1441 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1448 /*-----------------------------------------------------------------*/
1449 /* getDataSize - get the operand data size */
1450 /*-----------------------------------------------------------------*/
1452 getDataSize (operand * op)
1455 size = AOP_SIZE (op);
1456 if (size == GPTRSIZE)
1458 sym_link *type = operandType (op);
1459 if (IS_GENPTR (type))
1461 /* generic pointer; arithmetic operations
1462 * should ignore the high byte (pointer type).
1470 /*-----------------------------------------------------------------*/
1471 /* outAcc - output Acc */
1472 /*-----------------------------------------------------------------*/
1474 outAcc (operand * result)
1477 size = getDataSize (result);
1480 aopPut (AOP (result), "a", 0);
1483 /* unsigned or positive */
1486 aopPut (AOP (result), zero, offset++);
1491 /*-----------------------------------------------------------------*/
1492 /* outBitC - output a bit C */
1493 /*-----------------------------------------------------------------*/
1495 outBitC (operand * result)
1497 /* if the result is bit */
1498 if (AOP_TYPE (result) == AOP_CRY)
1500 aopPut (AOP (result), "c", 0);
1504 emitcode ("clr", "a");
1505 emitcode ("rlc", "a");
1510 /*-----------------------------------------------------------------*/
1511 /* toBoolean - emit code for orl a,operator(sizeop) */
1512 /*-----------------------------------------------------------------*/
1514 toBoolean (operand * oper)
1516 int size = AOP_SIZE (oper) - 1;
1520 /* The generic part of a generic pointer should
1521 * not participate in it's truth value.
1523 * i.e. 0x10000000 is zero.
1525 if (opIsGptr (oper))
1527 D (emitcode (";", "toBoolean: generic ptr special case.");
1532 _startLazyDPSEvaluation ();
1533 if (AOP_NEEDSACC (oper) && size)
1536 emitcode ("push", "b");
1537 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1541 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1547 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1551 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1554 _endLazyDPSEvaluation ();
1558 emitcode ("mov", "a,b");
1559 emitcode ("pop", "b");
1564 /*-----------------------------------------------------------------*/
1565 /* genNot - generate code for ! operation */
1566 /*-----------------------------------------------------------------*/
1571 sym_link *optype = operandType (IC_LEFT (ic));
1573 D (emitcode (";", "genNot ");
1576 /* assign asmOps to operand & result */
1577 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1578 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1580 /* if in bit space then a special case */
1581 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1583 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1584 emitcode ("cpl", "c");
1585 outBitC (IC_RESULT (ic));
1589 /* if type float then do float */
1590 if (IS_FLOAT (optype))
1592 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1596 toBoolean (IC_LEFT (ic));
1598 tlbl = newiTempLabel (NULL);
1599 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1600 emitcode ("", "%05d$:", tlbl->key + 100);
1601 outBitC (IC_RESULT (ic));
1604 /* release the aops */
1605 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1606 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1610 /*-----------------------------------------------------------------*/
1611 /* genCpl - generate code for complement */
1612 /*-----------------------------------------------------------------*/
1619 D (emitcode (";", "genCpl ");
1623 /* assign asmOps to operand & result */
1624 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1625 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1627 /* if both are in bit space then
1629 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1630 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1633 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1634 emitcode ("cpl", "c");
1635 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1639 size = AOP_SIZE (IC_RESULT (ic));
1640 _startLazyDPSEvaluation ();
1643 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1645 emitcode ("cpl", "a");
1646 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1648 _endLazyDPSEvaluation ();
1652 /* release the aops */
1653 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1654 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1657 /*-----------------------------------------------------------------*/
1658 /* genUminusFloat - unary minus for floating points */
1659 /*-----------------------------------------------------------------*/
1661 genUminusFloat (operand * op, operand * result)
1663 int size, offset = 0;
1665 /* for this we just need to flip the
1666 first it then copy the rest in place */
1667 D (emitcode (";", "genUminusFloat");
1670 _startLazyDPSEvaluation ();
1671 size = AOP_SIZE (op) - 1;
1672 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1675 emitcode ("cpl", "acc.7");
1676 aopPut (AOP (result), "a", 3);
1680 aopPut (AOP (result),
1681 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1685 _endLazyDPSEvaluation ();
1688 /*-----------------------------------------------------------------*/
1689 /* genUminus - unary minus code generation */
1690 /*-----------------------------------------------------------------*/
1692 genUminus (iCode * ic)
1695 sym_link *optype, *rtype;
1697 D (emitcode (";", "genUminus ");
1702 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1703 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1705 /* if both in bit space then special
1707 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1708 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1711 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1712 emitcode ("cpl", "c");
1713 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1717 optype = operandType (IC_LEFT (ic));
1718 rtype = operandType (IC_RESULT (ic));
1720 /* if float then do float stuff */
1721 if (IS_FLOAT (optype))
1723 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1727 /* otherwise subtract from zero */
1728 size = AOP_SIZE (IC_LEFT (ic));
1730 _startLazyDPSEvaluation ();
1733 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1734 if (!strcmp (l, "a"))
1738 emitcode ("cpl", "a");
1739 emitcode ("addc", "a,#0");
1745 emitcode ("clr", "a");
1746 emitcode ("subb", "a,%s", l);
1748 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1750 _endLazyDPSEvaluation ();
1752 /* if any remaining bytes in the result */
1753 /* we just need to propagate the sign */
1754 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1756 emitcode ("rlc", "a");
1757 emitcode ("subb", "a,acc");
1759 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1763 /* release the aops */
1764 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1765 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1768 /*-----------------------------------------------------------------*/
1769 /* saveRegisters - will look for a call and save the registers */
1770 /*-----------------------------------------------------------------*/
1772 saveRegisters (iCode * lic)
1780 for (ic = lic; ic; ic = ic->next)
1781 if (ic->op == CALL || ic->op == PCALL)
1786 fprintf (stderr, "found parameter push with no function call\n");
1790 /* if the registers have been saved already then
1792 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type) ||
1793 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))))
1796 /* find the registers in use at this time
1797 and push them away to safety */
1798 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1802 if (options.useXstack)
1804 if (bitVectBitValue (rsave, R0_IDX))
1805 emitcode ("mov", "b,r0");
1806 emitcode ("mov", "r0,%s", spname);
1807 for (i = 0; i < ds390_nRegs; i++)
1809 if (bitVectBitValue (rsave, i))
1812 emitcode ("mov", "a,b");
1814 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1815 emitcode ("movx", "@r0,a");
1816 emitcode ("inc", "r0");
1819 emitcode ("mov", "%s,r0", spname);
1820 if (bitVectBitValue (rsave, R0_IDX))
1821 emitcode ("mov", "r0,b");
1824 for (i = 0; i < ds390_nRegs; i++)
1826 if (bitVectBitValue (rsave, i))
1827 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1830 detype = getSpec (operandType (IC_LEFT (ic)));
1833 /*-----------------------------------------------------------------*/
1834 /* unsaveRegisters - pop the pushed registers */
1835 /*-----------------------------------------------------------------*/
1837 unsaveRegisters (iCode * ic)
1841 /* find the registers in use at this time
1842 and push them away to safety */
1843 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1846 if (options.useXstack)
1848 emitcode ("mov", "r0,%s", spname);
1849 for (i = ds390_nRegs; i >= 0; i--)
1851 if (bitVectBitValue (rsave, i))
1853 emitcode ("dec", "r0");
1854 emitcode ("movx", "a,@r0");
1856 emitcode ("mov", "b,a");
1858 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1862 emitcode ("mov", "%s,r0", spname);
1863 if (bitVectBitValue (rsave, R0_IDX))
1864 emitcode ("mov", "r0,b");
1867 for (i = ds390_nRegs; i >= 0; i--)
1869 if (bitVectBitValue (rsave, i))
1870 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1876 /*-----------------------------------------------------------------*/
1878 /*-----------------------------------------------------------------*/
1880 pushSide (operand * oper, int size)
1883 _startLazyDPSEvaluation ();
1886 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1887 if (AOP_TYPE (oper) != AOP_REG &&
1888 AOP_TYPE (oper) != AOP_DIR &&
1891 emitcode ("mov", "a,%s", l);
1892 emitcode ("push", "acc");
1895 emitcode ("push", "%s", l);
1897 _endLazyDPSEvaluation ();
1900 /*-----------------------------------------------------------------*/
1901 /* assignResultValue - */
1902 /*-----------------------------------------------------------------*/
1904 assignResultValue (operand * oper)
1907 int size = AOP_SIZE (oper);
1909 _startLazyDPSEvaluation ();
1912 aopPut (AOP (oper), fReturn[offset], offset);
1915 _endLazyDPSEvaluation ();
1919 /*-----------------------------------------------------------------*/
1920 /* genXpush - pushes onto the external stack */
1921 /*-----------------------------------------------------------------*/
1923 genXpush (iCode * ic)
1925 asmop *aop = newAsmop (0);
1927 int size, offset = 0;
1929 D (emitcode (";", "genXpush ");
1932 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1933 r = getFreePtr (ic, &aop, FALSE);
1936 emitcode ("mov", "%s,_spx", r->name);
1938 size = AOP_SIZE (IC_LEFT (ic));
1939 _startLazyDPSEvaluation ();
1943 char *l = aopGet (AOP (IC_LEFT (ic)),
1944 offset++, FALSE, FALSE, TRUE);
1946 emitcode ("movx", "@%s,a", r->name);
1947 emitcode ("inc", "%s", r->name);
1950 _endLazyDPSEvaluation ();
1953 emitcode ("mov", "_spx,%s", r->name);
1955 freeAsmop (NULL, aop, ic, TRUE);
1956 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1959 /*-----------------------------------------------------------------*/
1960 /* genIpush - genrate code for pushing this gets a little complex */
1961 /*-----------------------------------------------------------------*/
1963 genIpush (iCode * ic)
1965 int size, offset = 0;
1968 D (emitcode (";", "genIpush ");
1971 /* if this is not a parm push : ie. it is spill push
1972 and spill push is always done on the local stack */
1976 /* and the item is spilt then do nothing */
1977 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1980 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1981 size = AOP_SIZE (IC_LEFT (ic));
1982 /* push it on the stack */
1983 _startLazyDPSEvaluation ();
1986 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1992 emitcode ("push", "%s", l);
1994 _endLazyDPSEvaluation ();
1998 /* this is a paramter push: in this case we call
1999 the routine to find the call and save those
2000 registers that need to be saved */
2003 /* if use external stack then call the external
2004 stack pushing routine */
2005 if (options.useXstack)
2011 /* then do the push */
2012 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2014 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2015 size = AOP_SIZE (IC_LEFT (ic));
2017 _startLazyDPSEvaluation ();
2020 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2021 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2022 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2025 emitcode ("mov", "a,%s", l);
2026 emitcode ("push", "acc");
2029 emitcode ("push", "%s", l);
2031 _endLazyDPSEvaluation ();
2033 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2036 /*-----------------------------------------------------------------*/
2037 /* genIpop - recover the registers: can happen only for spilling */
2038 /*-----------------------------------------------------------------*/
2040 genIpop (iCode * ic)
2044 D (emitcode (";", "genIpop ");
2048 /* if the temp was not pushed then */
2049 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2052 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2053 size = AOP_SIZE (IC_LEFT (ic));
2054 offset = (size - 1);
2055 _startLazyDPSEvaluation ();
2058 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2059 FALSE, TRUE, TRUE));
2061 _endLazyDPSEvaluation ();
2063 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2066 /*-----------------------------------------------------------------*/
2067 /* unsaveRBank - restores the resgister bank from stack */
2068 /*-----------------------------------------------------------------*/
2070 unsaveRBank (int bank, iCode * ic, bool popPsw)
2076 if (options.useXstack)
2080 /* Assume r0 is available for use. */
2081 r = ds390_regWithIdx (R0_IDX);;
2086 r = getFreePtr (ic, &aop, FALSE);
2088 emitcode ("mov", "%s,_spx", r->name);
2093 if (options.useXstack)
2095 emitcode ("movx", "a,@%s", r->name);
2096 emitcode ("mov", "psw,a");
2097 emitcode ("dec", "%s", r->name);
2101 emitcode ("pop", "psw");
2105 for (i = (ds390_nRegs - 1); i >= 0; i--)
2107 if (options.useXstack)
2109 emitcode ("movx", "a,@%s", r->name);
2110 emitcode ("mov", "(%s+%d),a",
2111 regs390[i].base, 8 * bank + regs390[i].offset);
2112 emitcode ("dec", "%s", r->name);
2116 emitcode ("pop", "(%s+%d)",
2117 regs390[i].base, 8 * bank + regs390[i].offset);
2120 if (options.useXstack)
2122 emitcode ("mov", "_spx,%s", r->name);
2127 freeAsmop (NULL, aop, ic, TRUE);
2131 /*-----------------------------------------------------------------*/
2132 /* saveRBank - saves an entire register bank on the stack */
2133 /*-----------------------------------------------------------------*/
2135 saveRBank (int bank, iCode * ic, bool pushPsw)
2141 if (options.useXstack)
2145 /* Assume r0 is available for use. */
2146 r = ds390_regWithIdx (R0_IDX);;
2151 r = getFreePtr (ic, &aop, FALSE);
2153 emitcode ("mov", "%s,_spx", r->name);
2156 for (i = 0; i < ds390_nRegs; i++)
2158 if (options.useXstack)
2160 emitcode ("inc", "%s", r->name);
2161 emitcode ("mov", "a,(%s+%d)",
2162 regs390[i].base, 8 * bank + regs390[i].offset);
2163 emitcode ("movx", "@%s,a", r->name);
2166 emitcode ("push", "(%s+%d)",
2167 regs390[i].base, 8 * bank + regs390[i].offset);
2172 if (options.useXstack)
2174 emitcode ("mov", "a,psw");
2175 emitcode ("movx", "@%s,a", r->name);
2176 emitcode ("inc", "%s", r->name);
2177 emitcode ("mov", "_spx,%s", r->name);
2181 emitcode ("push", "psw");
2184 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2189 freeAsmop (NULL, aop, ic, TRUE);
2198 /*-----------------------------------------------------------------*/
2199 /* genCall - generates a call statement */
2200 /*-----------------------------------------------------------------*/
2202 genCall (iCode * ic)
2205 bool restoreBank = FALSE;
2206 bool swapBanks = FALSE;
2208 D (emitcode (";", "genCall "););
2210 /* if we are calling a not _naked function that is not using
2211 the same register bank then we need to save the
2212 destination registers on the stack */
2213 dtype = operandType (IC_LEFT (ic));
2214 if (dtype && !IFFUNC_ISNAKED(dtype) &&
2215 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2216 IFFUNC_ISISR (currFunc->type))
2220 /* This is unexpected; the bank should have been saved in
2223 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2229 /* if caller saves & we have not saved then */
2233 /* if send set is not empty the assign */
2234 /* We've saved all the registers we care about;
2235 * therefore, we may clobber any register not used
2236 * in the calling convention (i.e. anything not in
2243 for (sic = setFirstItem (_G.sendSet); sic;
2244 sic = setNextItem (_G.sendSet))
2246 int size, offset = 0;
2248 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2249 size = AOP_SIZE (IC_LEFT (sic));
2251 _startLazyDPSEvaluation ();
2254 char *l = aopGet (AOP(IC_LEFT(sic)), offset,
2255 FALSE, FALSE, TRUE);
2256 if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size)
2258 emitcode("mov", "%s,%s", regs390[offset].name, l);
2260 else if (strcmp (l, fReturn[offset]))
2262 emitcode ("mov", "%s,%s",
2268 _endLazyDPSEvaluation ();
2269 if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR)
2271 size = AOP_SIZE (IC_LEFT (sic));
2279 emitcode("mov", "%s,%s",
2280 fReturn[size], regs390[size].name);
2283 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2290 emitcode ("mov", "psw,#0x%02x",
2291 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2295 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2296 OP_SYMBOL (IC_LEFT (ic))->rname :
2297 OP_SYMBOL (IC_LEFT (ic))->name));
2301 emitcode ("mov", "psw,#0x%02x",
2302 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2305 /* if we need assign a result value */
2306 if ((IS_ITEMP (IC_RESULT (ic)) &&
2307 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2308 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2309 IS_TRUE_SYMOP (IC_RESULT (ic)))
2311 if (isOperandInFarSpace (IC_RESULT (ic))
2312 && getSize (operandType (IC_RESULT (ic))) <= 2)
2314 int size = getSize (operandType (IC_RESULT (ic)));
2316 /* Special case for 1 or 2 byte return in far space. */
2320 emitcode ("mov", "b,%s", fReturn[1]);
2323 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2324 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2328 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2330 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2335 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2338 assignResultValue (IC_RESULT (ic));
2340 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2344 /* adjust the stack for parameters if
2349 if (ic->parmBytes > 3)
2351 emitcode ("mov", "a,%s", spname);
2352 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2353 emitcode ("mov", "%s,a", spname);
2356 for (i = 0; i < ic->parmBytes; i++)
2357 emitcode ("dec", "%s", spname);
2360 /* if we hade saved some registers then unsave them */
2361 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2362 unsaveRegisters (ic);
2364 /* if register bank was saved then pop them */
2366 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2369 /*-----------------------------------------------------------------*/
2370 /* genPcall - generates a call by pointer statement */
2371 /*-----------------------------------------------------------------*/
2373 genPcall (iCode * ic)
2376 symbol *rlbl = newiTempLabel (NULL);
2378 D (emitcode (";", "genPcall ");
2382 /* if caller saves & we have not saved then */
2386 /* if we are calling a function that is not using
2387 the same register bank then we need to save the
2388 destination registers on the stack */
2389 dtype = operandType (IC_LEFT (ic));
2391 IFFUNC_ISISR (currFunc->type) &&
2392 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)))
2393 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2396 /* push the return address on to the stack */
2397 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2398 emitcode ("push", "acc");
2399 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2400 emitcode ("push", "acc");
2402 if (options.model == MODEL_FLAT24)
2404 emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2405 emitcode ("push", "acc");
2408 /* now push the calling address */
2409 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2411 pushSide (IC_LEFT (ic), FPTRSIZE);
2413 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2415 /* if send set is not empty the assign */
2420 for (sic = setFirstItem (_G.sendSet); sic;
2421 sic = setNextItem (_G.sendSet))
2423 int size, offset = 0;
2425 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2426 size = AOP_SIZE (IC_LEFT (sic));
2427 _startLazyDPSEvaluation ();
2430 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2431 FALSE, FALSE, TRUE);
2432 if (strcmp (l, fReturn[offset]))
2434 emitcode ("mov", "%s,%s",
2440 _endLazyDPSEvaluation ();
2441 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2446 emitcode ("ret", "");
2447 emitcode ("", "%05d$:", (rlbl->key + 100));
2450 /* if we need assign a result value */
2451 if ((IS_ITEMP (IC_RESULT (ic)) &&
2452 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2453 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2454 IS_TRUE_SYMOP (IC_RESULT (ic)))
2458 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2461 assignResultValue (IC_RESULT (ic));
2463 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2466 /* adjust the stack for parameters if
2471 if (ic->parmBytes > 3)
2473 emitcode ("mov", "a,%s", spname);
2474 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2475 emitcode ("mov", "%s,a", spname);
2478 for (i = 0; i < ic->parmBytes; i++)
2479 emitcode ("dec", "%s", spname);
2483 /* if register bank was saved then unsave them */
2485 (FUNC_REGBANK (currFunc->type) !=
2486 FUNC_REGBANK (dtype)))
2487 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2489 /* if we hade saved some registers then
2492 unsaveRegisters (ic);
2496 /*-----------------------------------------------------------------*/
2497 /* resultRemat - result is rematerializable */
2498 /*-----------------------------------------------------------------*/
2500 resultRemat (iCode * ic)
2502 if (SKIP_IC (ic) || ic->op == IFX)
2505 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2507 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2508 if (sym->remat && !POINTER_SET (ic))
2515 #if defined(__BORLANDC__) || defined(_MSC_VER)
2516 #define STRCASECMP stricmp
2518 #define STRCASECMP strcasecmp
2521 /*-----------------------------------------------------------------*/
2522 /* inExcludeList - return 1 if the string is in exclude Reg list */
2523 /*-----------------------------------------------------------------*/
2525 inExcludeList (char *s)
2529 if (options.excludeRegs[i] &&
2530 STRCASECMP (options.excludeRegs[i], "none") == 0)
2533 for (i = 0; options.excludeRegs[i]; i++)
2535 if (options.excludeRegs[i] &&
2536 STRCASECMP (s, options.excludeRegs[i]) == 0)
2542 /*-----------------------------------------------------------------*/
2543 /* genFunction - generated code for function entry */
2544 /*-----------------------------------------------------------------*/
2546 genFunction (iCode * ic)
2550 bool switchedPSW = FALSE;
2552 D (emitcode (";", "genFunction "););
2555 /* create the function header */
2556 emitcode (";", "-----------------------------------------");
2557 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2558 emitcode (";", "-----------------------------------------");
2560 emitcode ("", "%s:", sym->rname);
2561 ftype = operandType (IC_LEFT (ic));
2563 if (IFFUNC_ISNAKED(ftype))
2565 emitcode(";", "naked function: no prologue.");
2569 /* if critical function then turn interrupts off */
2570 if (IFFUNC_ISCRITICAL (ftype))
2571 emitcode ("clr", "ea");
2573 /* here we need to generate the equates for the
2574 register bank if required */
2575 if (FUNC_REGBANK (ftype) != rbank)
2579 rbank = FUNC_REGBANK (ftype);
2580 for (i = 0; i < ds390_nRegs; i++)
2582 if (strcmp (regs390[i].base, "0") == 0)
2583 emitcode ("", "%s = 0x%02x",
2585 8 * rbank + regs390[i].offset);
2587 emitcode ("", "%s = %s + 0x%02x",
2590 8 * rbank + regs390[i].offset);
2594 /* if this is an interrupt service routine then
2595 save acc, b, dpl, dph */
2596 if (IFFUNC_ISISR (sym->type))
2599 if (!inExcludeList ("acc"))
2600 emitcode ("push", "acc");
2601 if (!inExcludeList ("b"))
2602 emitcode ("push", "b");
2603 if (!inExcludeList ("dpl"))
2604 emitcode ("push", "dpl");
2605 if (!inExcludeList ("dph"))
2606 emitcode ("push", "dph");
2607 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2609 emitcode ("push", "dpx");
2610 /* Make sure we're using standard DPTR */
2611 emitcode ("push", "dps");
2612 emitcode ("mov", "dps, #0x00");
2613 if (options.stack10bit)
2615 /* This ISR could conceivably use DPTR2. Better save it. */
2616 emitcode ("push", "dpl1");
2617 emitcode ("push", "dph1");
2618 emitcode ("push", "dpx1");
2619 emitcode ("push", DP2_RESULT_REG);
2622 /* if this isr has no bank i.e. is going to
2623 run with bank 0 , then we need to save more
2625 if (!FUNC_REGBANK (sym->type))
2628 /* if this function does not call any other
2629 function then we can be economical and
2630 save only those registers that are used */
2631 if (!IFFUNC_HASFCALL(sym->type))
2635 /* if any registers used */
2638 /* save the registers used */
2639 for (i = 0; i < sym->regsUsed->size; i++)
2641 if (bitVectBitValue (sym->regsUsed, i) ||
2642 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2643 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2650 /* this function has a function call cannot
2651 determines register usage so we will have to push the
2653 saveRBank (0, ic, FALSE);
2658 /* This ISR uses a non-zero bank.
2660 * We assume that the bank is available for our
2663 * However, if this ISR calls a function which uses some
2664 * other bank, we must save that bank entirely.
2666 unsigned long banksToSave = 0;
2668 if (IFFUNC_HASFCALL(sym->type))
2671 #define MAX_REGISTER_BANKS 4
2676 for (i = ic; i; i = i->next)
2678 if (i->op == ENDFUNCTION)
2680 /* we got to the end OK. */
2688 dtype = operandType (IC_LEFT(i));
2690 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2692 /* Mark this bank for saving. */
2693 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2695 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2699 banksToSave |= (1 << FUNC_REGBANK(dtype));
2702 /* And note that we don't need to do it in
2710 /* This is a mess; we have no idea what
2711 * register bank the called function might
2714 * The only thing I can think of to do is
2715 * throw a warning and hope.
2717 werror(W_FUNCPTR_IN_USING_ISR);
2721 if (banksToSave && options.useXstack)
2723 /* Since we aren't passing it an ic,
2724 * saveRBank will assume r0 is available to abuse.
2726 * So switch to our (trashable) bank now, so
2727 * the caller's R0 isn't trashed.
2729 emitcode ("push", "psw");
2730 emitcode ("mov", "psw,#0x%02x",
2731 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2735 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2737 if (banksToSave & (1 << ix))
2739 saveRBank(ix, NULL, FALSE);
2743 // jwk: this needs a closer look
2744 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2749 /* if callee-save to be used for this function
2750 then save the registers being used in this function */
2751 if (IFFUNC_CALLEESAVES(sym->type))
2755 /* if any registers used */
2758 /* save the registers used */
2759 for (i = 0; i < sym->regsUsed->size; i++)
2761 if (bitVectBitValue (sym->regsUsed, i) ||
2762 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2764 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2772 /* set the register bank to the desired value */
2773 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2776 emitcode ("push", "psw");
2777 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2780 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2783 if (options.useXstack)
2785 emitcode ("mov", "r0,%s", spname);
2786 emitcode ("mov", "a,_bp");
2787 emitcode ("movx", "@r0,a");
2788 emitcode ("inc", "%s", spname);
2792 /* set up the stack */
2793 emitcode ("push", "_bp"); /* save the callers stack */
2795 emitcode ("mov", "_bp,%s", spname);
2798 /* adjust the stack for the function */
2804 werror (W_STACK_OVERFLOW, sym->name);
2806 if (i > 3 && sym->recvSize < 4)
2809 emitcode ("mov", "a,sp");
2810 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2811 emitcode ("mov", "sp,a");
2816 emitcode ("inc", "sp");
2822 emitcode ("mov", "a,_spx");
2823 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2824 emitcode ("mov", "_spx,a");
2829 /*-----------------------------------------------------------------*/
2830 /* genEndFunction - generates epilogue for functions */
2831 /*-----------------------------------------------------------------*/
2833 genEndFunction (iCode * ic)
2835 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2837 D (emitcode (";", "genEndFunction "););
2839 if (IFFUNC_ISNAKED(sym->type))
2841 emitcode(";", "naked function: no epilogue.");
2845 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2847 emitcode ("mov", "%s,_bp", spname);
2850 /* if use external stack but some variables were
2851 added to the local stack then decrement the
2853 if (options.useXstack && sym->stack)
2855 emitcode ("mov", "a,sp");
2856 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2857 emitcode ("mov", "sp,a");
2861 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2863 if (options.useXstack)
2865 emitcode ("mov", "r0,%s", spname);
2866 emitcode ("movx", "a,@r0");
2867 emitcode ("mov", "_bp,a");
2868 emitcode ("dec", "%s", spname);
2872 emitcode ("pop", "_bp");
2876 /* restore the register bank */
2877 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2879 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
2880 || !options.useXstack)
2882 /* Special case of ISR using non-zero bank with useXstack
2885 emitcode ("pop", "psw");
2889 if (IFFUNC_ISISR (sym->type))
2892 /* now we need to restore the registers */
2893 /* if this isr has no bank i.e. is going to
2894 run with bank 0 , then we need to save more
2896 if (!FUNC_REGBANK (sym->type))
2898 /* if this function does not call any other
2899 function then we can be economical and
2900 save only those registers that are used */
2901 if (!IFFUNC_HASFCALL(sym->type))
2905 /* if any registers used */
2908 /* save the registers used */
2909 for (i = sym->regsUsed->size; i >= 0; i--)
2911 if (bitVectBitValue (sym->regsUsed, i) ||
2912 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2913 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2920 /* this function has a function call cannot
2921 determines register usage so we will have to pop the
2923 unsaveRBank (0, ic, FALSE);
2928 /* This ISR uses a non-zero bank.
2930 * Restore any register banks saved by genFunction
2933 // jwk: this needs a closer look
2934 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2937 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2939 if (savedBanks & (1 << ix))
2941 unsaveRBank(ix, NULL, FALSE);
2945 if (options.useXstack)
2947 /* Restore bank AFTER calling unsaveRBank,
2948 * since it can trash r0.
2950 emitcode ("pop", "psw");
2954 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2956 if (options.stack10bit)
2958 emitcode ("pop", DP2_RESULT_REG);
2959 emitcode ("pop", "dpx1");
2960 emitcode ("pop", "dph1");
2961 emitcode ("pop", "dpl1");
2963 emitcode ("pop", "dps");
2964 emitcode ("pop", "dpx");
2966 if (!inExcludeList ("dph"))
2967 emitcode ("pop", "dph");
2968 if (!inExcludeList ("dpl"))
2969 emitcode ("pop", "dpl");
2970 if (!inExcludeList ("b"))
2971 emitcode ("pop", "b");
2972 if (!inExcludeList ("acc"))
2973 emitcode ("pop", "acc");
2975 if (IFFUNC_ISCRITICAL (sym->type))
2976 emitcode ("setb", "ea");
2978 /* if debug then send end of function */
2979 if (options.debug && currFunc) {
2981 emitcode ("", "C$%s$%d$%d$%d ==.",
2982 FileBaseName (ic->filename), currFunc->lastLine,
2983 ic->level, ic->block);
2984 if (IS_STATIC (currFunc->etype))
2985 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2987 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2991 emitcode ("reti", "");
2995 if (IFFUNC_ISCRITICAL (sym->type))
2996 emitcode ("setb", "ea");
2998 if (IFFUNC_CALLEESAVES(sym->type))
3002 /* if any registers used */
3005 /* save the registers used */
3006 for (i = sym->regsUsed->size; i >= 0; i--)
3008 if (bitVectBitValue (sym->regsUsed, i) ||
3009 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3010 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3016 /* if debug then send end of function */
3017 if (options.debug && currFunc)
3020 emitcode ("", "C$%s$%d$%d$%d ==.",
3021 FileBaseName (ic->filename), currFunc->lastLine,
3022 ic->level, ic->block);
3023 if (IS_STATIC (currFunc->etype))
3024 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3026 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3030 emitcode ("ret", "");
3035 /*-----------------------------------------------------------------*/
3036 /* genRet - generate code for return statement */
3037 /*-----------------------------------------------------------------*/
3041 int size, offset = 0, pushed = 0;
3043 D (emitcode (";", "genRet ");
3046 /* if we have no return value then
3047 just generate the "ret" */
3051 /* we have something to return then
3052 move the return value into place */
3053 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
3054 size = AOP_SIZE (IC_LEFT (ic));
3056 _startLazyDPSEvaluation ();
3060 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3062 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3063 FALSE, TRUE, FALSE);
3064 emitcode ("push", "%s", l);
3069 /* Since A is the last element of fReturn,
3070 * is is OK to clobber it in the aopGet.
3072 l = aopGet (AOP (IC_LEFT (ic)), offset,
3073 FALSE, FALSE, TRUE);
3074 if (strcmp (fReturn[offset], l))
3075 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3078 _endLazyDPSEvaluation ();
3085 if (strcmp (fReturn[pushed], "a"))
3086 emitcode ("pop", fReturn[pushed]);
3088 emitcode ("pop", "acc");
3091 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3094 /* generate a jump to the return label
3095 if the next is not the return statement */
3096 if (!(ic->next && ic->next->op == LABEL &&
3097 IC_LABEL (ic->next) == returnLabel))
3099 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3103 /*-----------------------------------------------------------------*/
3104 /* genLabel - generates a label */
3105 /*-----------------------------------------------------------------*/
3107 genLabel (iCode * ic)
3109 /* special case never generate */
3110 if (IC_LABEL (ic) == entryLabel)
3113 D (emitcode (";", "genLabel ");
3116 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3119 /*-----------------------------------------------------------------*/
3120 /* genGoto - generates a ljmp */
3121 /*-----------------------------------------------------------------*/
3123 genGoto (iCode * ic)
3125 D (emitcode (";", "genGoto ");
3127 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3130 /*-----------------------------------------------------------------*/
3131 /* findLabelBackwards: walks back through the iCode chain looking */
3132 /* for the given label. Returns number of iCode instructions */
3133 /* between that label and given ic. */
3134 /* Returns zero if label not found. */
3135 /*-----------------------------------------------------------------*/
3137 findLabelBackwards (iCode * ic, int key)
3146 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3148 /* printf("findLabelBackwards = %d\n", count); */
3156 /*-----------------------------------------------------------------*/
3157 /* genPlusIncr :- does addition with increment if possible */
3158 /*-----------------------------------------------------------------*/
3160 genPlusIncr (iCode * ic)
3162 unsigned int icount;
3163 unsigned int size = getDataSize (IC_RESULT (ic));
3165 /* will try to generate an increment */
3166 /* if the right side is not a literal
3168 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3171 /* if the literal value of the right hand side
3172 is greater than 4 then it is not worth it */
3173 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3176 /* if increment 16 bits in register */
3178 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3179 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3180 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3188 /* If the next instruction is a goto and the goto target
3189 * is <= 5 instructions previous to this, we can generate
3190 * jumps straight to that target.
3192 if (ic->next && ic->next->op == GOTO
3193 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3196 emitcode (";", "tail increment optimized (range %d)", labelRange);
3197 tlbl = IC_LABEL (ic->next);
3202 tlbl = newiTempLabel (NULL);
3205 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3206 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3207 IS_AOP_PREG (IC_RESULT (ic)))
3208 emitcode ("cjne", "%s,#0x00,%05d$"
3209 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3213 emitcode ("clr", "a");
3214 emitcode ("cjne", "a,%s,%05d$"
3215 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3219 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3222 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3223 IS_AOP_PREG (IC_RESULT (ic)))
3224 emitcode ("cjne", "%s,#0x00,%05d$"
3225 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3228 emitcode ("cjne", "a,%s,%05d$"
3229 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3232 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3236 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3237 IS_AOP_PREG (IC_RESULT (ic)))
3238 emitcode ("cjne", "%s,#0x00,%05d$"
3239 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3243 emitcode ("cjne", "a,%s,%05d$"
3244 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3247 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3252 emitcode ("", "%05d$:", tlbl->key + 100);
3257 /* if the sizes are greater than 1 then we cannot */
3258 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3259 AOP_SIZE (IC_LEFT (ic)) > 1)
3262 /* we can if the aops of the left & result match or
3263 if they are in registers and the registers are the
3266 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3267 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3268 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3273 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3274 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3275 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3280 _startLazyDPSEvaluation ();
3283 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3285 _endLazyDPSEvaluation ();
3294 /*-----------------------------------------------------------------*/
3295 /* outBitAcc - output a bit in acc */
3296 /*-----------------------------------------------------------------*/
3298 outBitAcc (operand * result)
3300 symbol *tlbl = newiTempLabel (NULL);
3301 /* if the result is a bit */
3302 if (AOP_TYPE (result) == AOP_CRY)
3304 aopPut (AOP (result), "a", 0);
3308 emitcode ("jz", "%05d$", tlbl->key + 100);
3309 emitcode ("mov", "a,%s", one);
3310 emitcode ("", "%05d$:", tlbl->key + 100);
3315 /*-----------------------------------------------------------------*/
3316 /* genPlusBits - generates code for addition of two bits */
3317 /*-----------------------------------------------------------------*/
3319 genPlusBits (iCode * ic)
3321 D (emitcode (";", "genPlusBits ");
3323 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3325 symbol *lbl = newiTempLabel (NULL);
3326 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3327 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3328 emitcode ("cpl", "c");
3329 emitcode ("", "%05d$:", (lbl->key + 100));
3330 outBitC (IC_RESULT (ic));
3334 emitcode ("clr", "a");
3335 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3336 emitcode ("rlc", "a");
3337 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3338 emitcode ("addc", "a,#0x00");
3339 outAcc (IC_RESULT (ic));
3344 adjustArithmeticResult (iCode * ic)
3346 if (opIsGptr (IC_RESULT (ic)) &&
3347 opIsGptr (IC_LEFT (ic)) &&
3348 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3350 aopPut (AOP (IC_RESULT (ic)),
3351 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3355 if (opIsGptr (IC_RESULT (ic)) &&
3356 opIsGptr (IC_RIGHT (ic)) &&
3357 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3359 aopPut (AOP (IC_RESULT (ic)),
3360 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3364 if (opIsGptr (IC_RESULT (ic)) &&
3365 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3366 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3367 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3368 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3371 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3372 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3376 #if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
3377 // Please don't bring it back without a really good reason.
3378 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3379 // (because all three operands are in far space).
3380 #define AOP_OP_3(ic) \
3381 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3382 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3383 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3384 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3385 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3386 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3388 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3390 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3394 // Macro to aopOp all three operands of an ic. If this cannot be done,
3395 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3396 // will be set TRUE. The caller must then handle the case specially, noting
3397 // that the IC_RESULT operand is not aopOp'd.
3398 #define AOP_OP_3_NOFATAL(ic, rc) \
3399 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3400 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3401 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3402 isOperandInFarSpace(IC_RESULT(ic))) \
3404 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3409 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3410 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3412 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3413 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3415 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3417 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3421 // aopOp the left & right operands of an ic.
3422 #define AOP_OP_2(ic) \
3423 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3424 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3426 // convienience macro.
3427 #define AOP_SET_LOCALS(ic) \
3428 left = IC_LEFT(ic); \
3429 right = IC_RIGHT(ic); \
3430 result = IC_RESULT(ic);
3433 // Given an integer value of pushedSize bytes on the stack,
3434 // adjust it to be resultSize bytes, either by discarding
3435 // the most significant bytes or by zero-padding.
3437 // On exit from this macro, pushedSize will have been adjusted to
3438 // equal resultSize, and ACC may be trashed.
3439 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3440 /* If the pushed data is bigger than the result, \
3441 * simply discard unused bytes. Icky, but works. \
3443 while (pushedSize > resultSize) \
3445 D (emitcode (";", "discarding unused result byte."););\
3446 emitcode ("pop", "acc"); \
3449 if (pushedSize < resultSize) \
3451 emitcode ("clr", "a"); \
3452 /* Conversly, we haven't pushed enough here. \
3453 * just zero-pad, and all is well. \
3455 while (pushedSize < resultSize) \
3457 emitcode("push", "acc"); \
3461 assert(pushedSize == resultSize);
3463 /*-----------------------------------------------------------------*/
3464 /* genPlus - generates code for addition */
3465 /*-----------------------------------------------------------------*/
3467 genPlus (iCode * ic)
3469 int size, offset = 0;
3470 bool pushResult = FALSE;
3473 D (emitcode (";", "genPlus "););
3475 /* special cases :- */
3477 AOP_OP_3_NOFATAL (ic, pushResult);
3480 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3485 /* if literal, literal on the right or
3486 if left requires ACC or right is already
3488 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3489 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3490 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3492 operand *t = IC_RIGHT (ic);
3493 IC_RIGHT (ic) = IC_LEFT (ic);
3495 emitcode (";", "Swapped plus args.");
3498 /* if both left & right are in bit
3500 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3501 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3507 /* if left in bit space & right literal */
3508 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3509 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3511 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3512 /* if result in bit space */
3513 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3515 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3516 emitcode ("cpl", "c");
3517 outBitC (IC_RESULT (ic));
3521 size = getDataSize (IC_RESULT (ic));
3522 _startLazyDPSEvaluation ();
3525 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3526 emitcode ("addc", "a,#00");
3527 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3529 _endLazyDPSEvaluation ();
3534 /* if I can do an increment instead
3535 of add then GOOD for ME */
3536 if (genPlusIncr (ic) == TRUE)
3538 emitcode (";", "did genPlusIncr");
3543 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3545 _startLazyDPSEvaluation ();
3548 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3550 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3552 emitcode ("add", "a,%s",
3553 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3555 emitcode ("addc", "a,%s",
3556 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3560 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3562 /* right is going to use ACC or we would have taken the
3565 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3567 D(emitcode(";", "+ AOP_ACC special case."););
3568 emitcode("xch", "a, %s", DP2_RESULT_REG);
3570 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3573 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3576 emitcode("add", "a, %s", DP2_RESULT_REG);
3580 emitcode ("add", "a,%s",
3581 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3586 emitcode ("addc", "a,%s",
3587 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3592 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3596 emitcode ("push", "acc");
3600 _endLazyDPSEvaluation ();
3604 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3606 size = getDataSize (IC_LEFT (ic));
3607 rSize = getDataSize (IC_RESULT (ic));
3609 ADJUST_PUSHED_RESULT(size, rSize);
3611 _startLazyDPSEvaluation ();
3614 emitcode ("pop", "acc");
3615 aopPut (AOP (IC_RESULT (ic)), "a", size);
3617 _endLazyDPSEvaluation ();
3620 adjustArithmeticResult (ic);
3623 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3624 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3625 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3628 /*-----------------------------------------------------------------*/
3629 /* genMinusDec :- does subtraction with deccrement if possible */
3630 /*-----------------------------------------------------------------*/
3632 genMinusDec (iCode * ic)
3634 unsigned int icount;
3635 unsigned int size = getDataSize (IC_RESULT (ic));
3637 /* will try to generate an increment */
3638 /* if the right side is not a literal
3640 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3643 /* if the literal value of the right hand side
3644 is greater than 4 then it is not worth it */
3645 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3648 /* if decrement 16 bits in register */
3649 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3650 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3651 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3659 /* If the next instruction is a goto and the goto target
3660 * is <= 5 instructions previous to this, we can generate
3661 * jumps straight to that target.
3663 if (ic->next && ic->next->op == GOTO
3664 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3667 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3668 tlbl = IC_LABEL (ic->next);
3673 tlbl = newiTempLabel (NULL);
3677 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3678 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3679 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3680 IS_AOP_PREG (IC_RESULT (ic)))
3681 emitcode ("cjne", "%s,#0xff,%05d$"
3682 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3686 emitcode ("mov", "a,#0xff");
3687 emitcode ("cjne", "a,%s,%05d$"
3688 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3691 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3694 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3695 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3696 IS_AOP_PREG (IC_RESULT (ic)))
3697 emitcode ("cjne", "%s,#0xff,%05d$"
3698 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3702 emitcode ("cjne", "a,%s,%05d$"
3703 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3706 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3710 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3711 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3712 IS_AOP_PREG (IC_RESULT (ic)))
3713 emitcode ("cjne", "%s,#0xff,%05d$"
3714 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3718 emitcode ("cjne", "a,%s,%05d$"
3719 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3722 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3726 emitcode ("", "%05d$:", tlbl->key + 100);
3731 /* if the sizes are greater than 1 then we cannot */
3732 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3733 AOP_SIZE (IC_LEFT (ic)) > 1)
3736 /* we can if the aops of the left & result match or
3737 if they are in registers and the registers are the
3740 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3741 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3742 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3745 _startLazyDPSEvaluation ();
3748 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3750 _endLazyDPSEvaluation ();
3758 /*-----------------------------------------------------------------*/
3759 /* addSign - complete with sign */
3760 /*-----------------------------------------------------------------*/
3762 addSign (operand * result, int offset, int sign)
3764 int size = (getDataSize (result) - offset);
3767 _startLazyDPSEvaluation();
3770 emitcode ("rlc", "a");
3771 emitcode ("subb", "a,acc");
3774 aopPut (AOP (result), "a", offset++);
3781 aopPut (AOP (result), zero, offset++);
3784 _endLazyDPSEvaluation();
3788 /*-----------------------------------------------------------------*/
3789 /* genMinusBits - generates code for subtraction of two bits */
3790 /*-----------------------------------------------------------------*/
3792 genMinusBits (iCode * ic)
3794 symbol *lbl = newiTempLabel (NULL);
3796 D (emitcode (";", "genMinusBits "););
3798 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3800 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3801 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3802 emitcode ("cpl", "c");
3803 emitcode ("", "%05d$:", (lbl->key + 100));
3804 outBitC (IC_RESULT (ic));
3808 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3809 emitcode ("subb", "a,acc");
3810 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3811 emitcode ("inc", "a");
3812 emitcode ("", "%05d$:", (lbl->key + 100));
3813 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3814 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3818 /*-----------------------------------------------------------------*/
3819 /* genMinus - generates code for subtraction */
3820 /*-----------------------------------------------------------------*/
3822 genMinus (iCode * ic)
3824 int size, offset = 0;
3826 unsigned long lit = 0L;
3827 bool pushResult = FALSE;
3829 D (emitcode (";", "genMinus "););
3831 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3832 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3833 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3834 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3840 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3842 /* special cases :- */
3843 /* if both left & right are in bit space */
3844 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3845 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3851 /* if I can do an decrement instead
3852 of subtract then GOOD for ME */
3853 if (genMinusDec (ic) == TRUE)
3858 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3860 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3866 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3871 /* if literal, add a,#-lit, else normal subb */
3872 _startLazyDPSEvaluation ();
3875 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3876 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3877 emitcode ("subb", "a,%s",
3878 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3881 /* first add without previous c */
3883 if (!size && lit==-1) {
3884 emitcode ("dec", "a");
3886 emitcode ("add", "a,#0x%02x",
3887 (unsigned int) (lit & 0x0FFL));
3890 emitcode ("addc", "a,#0x%02x",
3891 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3897 emitcode ("push", "acc");
3901 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3905 _endLazyDPSEvaluation ();
3909 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3911 size = getDataSize (IC_LEFT (ic));
3912 rSize = getDataSize (IC_RESULT (ic));
3914 ADJUST_PUSHED_RESULT(size, rSize);
3916 _startLazyDPSEvaluation ();
3919 emitcode ("pop", "acc");
3920 aopPut (AOP (IC_RESULT (ic)), "a", size);
3922 _endLazyDPSEvaluation ();
3925 adjustArithmeticResult (ic);
3928 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3929 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3930 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3934 /*-----------------------------------------------------------------*/
3935 /* genMultbits :- multiplication of bits */
3936 /*-----------------------------------------------------------------*/
3938 genMultbits (operand * left,
3943 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3944 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3945 aopOp(result, ic, TRUE, FALSE);
3950 /*-----------------------------------------------------------------*/
3951 /* genMultOneByte : 8*8=8/16 bit multiplication */
3952 /*-----------------------------------------------------------------*/
3954 genMultOneByte (operand * left,
3959 sym_link *opetype = operandType (result);
3963 /* (if two literals: the value is computed before) */
3964 /* if one literal, literal on the right */
3965 if (AOP_TYPE (left) == AOP_LIT)
3970 emitcode (";", "swapped left and right");
3973 if (SPEC_USIGN(opetype)
3974 // ignore the sign of left and right, what else can we do?
3975 || (SPEC_USIGN(operandType(left)) &&
3976 SPEC_USIGN(operandType(right)))) {
3977 // just an unsigned 8*8=8/16 multiply
3978 //emitcode (";","unsigned");
3979 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3980 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3981 emitcode ("mul", "ab");
3984 aopOp(result, ic, TRUE, FALSE);
3986 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
3988 // this should never happen
3989 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3990 AOP_SIZE(result), __FILE__, lineno);
3994 aopPut (AOP (result), "a", 0);
3996 if (AOP_SIZE(result)==2)
3998 aopPut (AOP (result), "b", 1);
4003 // we have to do a signed multiply
4005 emitcode (";", "signed");
4006 emitcode ("clr", "F0"); // reset sign flag
4007 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4009 lbl=newiTempLabel(NULL);
4010 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
4011 // left side is negative, 8-bit two's complement, this fails for -128
4012 emitcode ("setb", "F0"); // set sign flag
4013 emitcode ("cpl", "a");
4014 emitcode ("inc", "a");
4016 emitcode ("", "%05d$:", lbl->key+100);
4019 if (AOP_TYPE(right)==AOP_LIT) {
4020 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4021 /* AND literal negative */
4022 if ((int) val < 0) {
4023 emitcode ("cpl", "F0"); // complement sign flag
4024 emitcode ("mov", "b,#0x%02x", -val);
4026 emitcode ("mov", "b,#0x%02x", val);
4029 lbl=newiTempLabel(NULL);
4030 emitcode ("mov", "b,a");
4031 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4032 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
4033 // right side is negative, 8-bit two's complement
4034 emitcode ("cpl", "F0"); // complement sign flag
4035 emitcode ("cpl", "a");
4036 emitcode ("inc", "a");
4037 emitcode ("", "%05d$:", lbl->key+100);
4039 emitcode ("mul", "ab");
4042 aopOp(result, ic, TRUE, FALSE);
4044 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4046 // this should never happen
4047 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4048 AOP_SIZE(result), __FILE__, lineno);
4052 lbl=newiTempLabel(NULL);
4053 emitcode ("jnb", "F0,%05d$", lbl->key+100);
4054 // only ONE op was negative, we have to do a 8/16-bit two's complement
4055 emitcode ("cpl", "a"); // lsb
4056 if (AOP_SIZE(result)==1) {
4057 emitcode ("inc", "a");
4059 emitcode ("add", "a,#1");
4060 emitcode ("xch", "a,b");
4061 emitcode ("cpl", "a"); // msb
4062 emitcode ("addc", "a,#0");
4063 emitcode ("xch", "a,b");
4066 emitcode ("", "%05d$:", lbl->key+100);
4067 aopPut (AOP (result), "a", 0);
4069 if (AOP_SIZE(result)==2) {
4070 aopPut (AOP (result), "b", 1);
4074 /*-----------------------------------------------------------------*/
4075 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4076 /*-----------------------------------------------------------------*/
4077 static void genMultTwoByte (operand *left, operand *right,
4078 operand *result, iCode *ic)
4080 sym_link *retype = getSpec(operandType(right));
4081 sym_link *letype = getSpec(operandType(left));
4082 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4085 if (AOP_TYPE (left) == AOP_LIT) {
4090 /* load up MB with right */
4092 emitcode("clr","F0");
4093 if (AOP_TYPE(right) == AOP_LIT) {
4094 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4096 emitcode("setb","F0");
4099 emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4100 emitcode ("mov","mb,#0x%02x",val & 0xff);
4102 lbl = newiTempLabel(NULL);
4103 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4104 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4105 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4106 emitcode ("xch", "a,b");
4107 emitcode ("cpl","a");
4108 emitcode ("add", "a,#1");
4109 emitcode ("xch", "a,b");
4110 emitcode ("cpl", "a"); // msb
4111 emitcode ("addc", "a,#0");
4112 emitcode ("setb","F0");
4113 emitcode ("","%05d$:",lbl->key+100);
4114 emitcode ("mov","mb,b");
4115 emitcode ("mov","mb,a");
4118 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4119 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4121 /* load up MA with left */
4123 lbl = newiTempLabel(NULL);
4124 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4125 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4126 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4127 emitcode ("xch", "a,b");
4128 emitcode ("cpl","a");
4129 emitcode ("add", "a,#1");
4130 emitcode ("xch", "a,b");
4131 emitcode ("cpl", "a"); // msb
4132 emitcode ("addc","a,#0");
4133 emitcode ("jbc","F0,%05d$",lbl->key+100);
4134 emitcode ("setb","F0");
4135 emitcode ("","%05d$:",lbl->key+100);
4136 emitcode ("mov","ma,b");
4137 emitcode ("mov","ma,a");
4139 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4140 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4142 /* wait for multiplication to finish */
4143 lbl = newiTempLabel(NULL);
4144 emitcode("","%05d$:", lbl->key+100);
4145 emitcode("mov","a,mcnt1");
4146 emitcode("anl","a,#0x80");
4147 emitcode("jnz","%05d$",lbl->key+100);
4149 freeAsmop (left, NULL, ic, TRUE);
4150 freeAsmop (right, NULL, ic,TRUE);
4151 aopOp(result, ic, TRUE, FALSE);
4153 /* if unsigned then simple */
4155 emitcode ("mov","a,ma");
4156 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4157 emitcode ("mov","a,ma");
4158 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4159 aopPut(AOP(result),"ma",1);
4160 aopPut(AOP(result),"ma",0);
4162 emitcode("push","ma");
4163 emitcode("push","ma");
4164 emitcode("push","ma");
4166 /* negate result if needed */
4167 lbl = newiTempLabel(NULL);
4168 emitcode("jnb","F0,%05d$",lbl->key+100);
4169 emitcode("cpl","a");
4170 emitcode("add","a,#1");
4171 emitcode("","%05d$:", lbl->key+100);
4172 aopPut(AOP(result),"a",0);
4173 emitcode("pop","acc");
4174 lbl = newiTempLabel(NULL);
4175 emitcode("jnb","F0,%05d$",lbl->key+100);
4176 emitcode("cpl","a");
4177 emitcode("addc","a,#0");
4178 emitcode("","%05d$:", lbl->key+100);
4179 aopPut(AOP(result),"a",1);
4180 emitcode("pop","acc");
4181 if (AOP_SIZE(result) >= 3) {
4182 lbl = newiTempLabel(NULL);
4183 emitcode("jnb","F0,%05d$",lbl->key+100);
4184 emitcode("cpl","a");
4185 emitcode("addc","a,#0");
4186 emitcode("","%05d$:", lbl->key+100);
4187 aopPut(AOP(result),"a",2);
4189 emitcode("pop","acc");
4190 if (AOP_SIZE(result) >= 4) {
4191 lbl = newiTempLabel(NULL);
4192 emitcode("jnb","F0,%05d$",lbl->key+100);
4193 emitcode("cpl","a");
4194 emitcode("addc","a,#0");
4195 emitcode("","%05d$:", lbl->key+100);
4196 aopPut(AOP(result),"a",3);
4200 freeAsmop (result, NULL, ic, TRUE);
4204 /*-----------------------------------------------------------------*/
4205 /* genMult - generates code for multiplication */
4206 /*-----------------------------------------------------------------*/
4208 genMult (iCode * ic)
4210 operand *left = IC_LEFT (ic);
4211 operand *right = IC_RIGHT (ic);
4212 operand *result = IC_RESULT (ic);
4214 D (emitcode (";", "genMult "););
4216 /* assign the amsops */
4219 /* special cases first */
4221 if (AOP_TYPE (left) == AOP_CRY &&
4222 AOP_TYPE (right) == AOP_CRY)
4224 genMultbits (left, right, result, ic);
4228 /* if both are of size == 1 */
4229 if (AOP_SIZE (left) == 1 &&
4230 AOP_SIZE (right) == 1)
4232 genMultOneByte (left, right, result, ic);
4236 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4237 /* use the ds390 ARITHMETIC accel UNIT */
4238 genMultTwoByte (left, right, result, ic);
4241 /* should have been converted to function call */
4245 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4246 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4247 freeAsmop (result, NULL, ic, TRUE);
4250 /*-----------------------------------------------------------------*/
4251 /* genDivbits :- division of bits */
4252 /*-----------------------------------------------------------------*/
4254 genDivbits (operand * left,
4262 /* the result must be bit */
4263 LOAD_AB_FOR_DIV (left, right, l);
4264 emitcode ("div", "ab");
4265 emitcode ("rrc", "a");
4266 aopOp(result, ic, TRUE, FALSE);
4268 aopPut (AOP (result), "c", 0);
4271 /*-----------------------------------------------------------------*/
4272 /* genDivOneByte : 8 bit division */
4273 /*-----------------------------------------------------------------*/
4275 genDivOneByte (operand * left,
4280 sym_link *opetype = operandType (result);
4286 /* signed or unsigned */
4287 if (SPEC_USIGN (opetype))
4289 /* unsigned is easy */
4290 LOAD_AB_FOR_DIV (left, right, l);
4291 emitcode ("div", "ab");
4294 aopOp(result, ic, TRUE, FALSE);
4295 aopPut (AOP (result), "a", 0);
4298 size = AOP_SIZE (result) - 1;
4302 aopPut (AOP (result), zero, offset++);
4307 /* signed is a little bit more difficult */
4309 /* save the signs of the operands */
4310 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4312 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4313 emitcode ("push", "acc"); /* save it on the stack */
4315 /* now sign adjust for both left & right */
4316 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4318 lbl = newiTempLabel (NULL);
4319 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4320 emitcode ("cpl", "a");
4321 emitcode ("inc", "a");
4322 emitcode ("", "%05d$:", (lbl->key + 100));
4323 emitcode ("mov", "b,a");
4325 /* sign adjust left side */
4326 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4329 lbl = newiTempLabel (NULL);
4330 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4331 emitcode ("cpl", "a");
4332 emitcode ("inc", "a");
4333 emitcode ("", "%05d$:", (lbl->key + 100));
4335 /* now the division */
4336 emitcode ("nop", "; workaround for DS80C390 div bug.");
4337 emitcode ("div", "ab");
4338 /* we are interested in the lower order
4340 emitcode ("mov", "b,a");
4341 lbl = newiTempLabel (NULL);
4342 emitcode ("pop", "acc");
4343 /* if there was an over flow we don't
4344 adjust the sign of the result */
4345 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4346 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4348 emitcode ("clr", "a");
4349 emitcode ("subb", "a,b");
4350 emitcode ("mov", "b,a");
4351 emitcode ("", "%05d$:", (lbl->key + 100));
4353 /* now we are done */
4355 aopOp(result, ic, TRUE, FALSE);
4357 aopPut (AOP (result), "b", 0);
4359 size = AOP_SIZE (result) - 1;
4363 emitcode ("mov", "c,b.7");
4364 emitcode ("subb", "a,acc");
4368 aopPut (AOP (result), "a", offset++);
4374 /*-----------------------------------------------------------------*/
4375 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4376 /*-----------------------------------------------------------------*/
4377 static void genDivTwoByte (operand *left, operand *right,
4378 operand *result, iCode *ic)
4380 sym_link *retype = getSpec(operandType(right));
4381 sym_link *letype = getSpec(operandType(left));
4382 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4385 /* load up MA with left */
4387 emitcode("clr","F0");
4388 lbl = newiTempLabel(NULL);
4389 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4390 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4391 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4392 emitcode ("xch", "a,b");
4393 emitcode ("cpl","a");
4394 emitcode ("add", "a,#1");
4395 emitcode ("xch", "a,b");
4396 emitcode ("cpl", "a"); // msb
4397 emitcode ("addc","a,#0");
4398 emitcode ("setb","F0");
4399 emitcode ("","%05d$:",lbl->key+100);
4400 emitcode ("mov","ma,b");
4401 emitcode ("mov","ma,a");
4403 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4404 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4407 /* load up MB with right */
4409 if (AOP_TYPE(right) == AOP_LIT) {
4410 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4412 lbl = newiTempLabel(NULL);
4413 emitcode ("jbc","F0,%05d$",lbl->key+100);
4414 emitcode("setb","F0");
4415 emitcode ("","%05d$:",lbl->key+100);
4418 emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4419 emitcode ("mov","mb,#0x%02x",val & 0xff);
4421 lbl = newiTempLabel(NULL);
4422 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4423 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4424 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4425 emitcode ("xch", "a,b");
4426 emitcode ("cpl","a");
4427 emitcode ("add", "a,#1");
4428 emitcode ("xch", "a,b");
4429 emitcode ("cpl", "a"); // msb
4430 emitcode ("addc", "a,#0");
4431 emitcode ("jbc","F0,%05d$",lbl->key+100);
4432 emitcode ("setb","F0");
4433 emitcode ("","%05d$:",lbl->key+100);
4434 emitcode ("mov","mb,b");
4435 emitcode ("mov","mb,a");
4438 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4439 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4442 /* wait for multiplication to finish */
4443 lbl = newiTempLabel(NULL);
4444 emitcode("","%05d$:", lbl->key+100);
4445 emitcode("mov","a,mcnt1");
4446 emitcode("anl","a,#0x80");
4447 emitcode("jnz","%05d$",lbl->key+100);
4449 freeAsmop (left, NULL, ic, TRUE);
4450 freeAsmop (right, NULL, ic,TRUE);
4451 aopOp(result, ic, TRUE, FALSE);
4453 /* if unsigned then simple */
4455 aopPut(AOP(result),"ma",1);
4456 aopPut(AOP(result),"ma",0);
4458 emitcode("push","ma");
4460 /* negate result if needed */
4461 lbl = newiTempLabel(NULL);
4462 emitcode("jnb","F0,%05d$",lbl->key+100);
4463 emitcode("cpl","a");
4464 emitcode("add","a,#1");
4465 emitcode("","%05d$:", lbl->key+100);
4466 aopPut(AOP(result),"a",0);
4467 emitcode("pop","acc");
4468 lbl = newiTempLabel(NULL);
4469 emitcode("jnb","F0,%05d$",lbl->key+100);
4470 emitcode("cpl","a");
4471 emitcode("addc","a,#0");
4472 emitcode("","%05d$:", lbl->key+100);
4473 aopPut(AOP(result),"a",1);
4475 freeAsmop (result, NULL, ic, TRUE);
4479 /*-----------------------------------------------------------------*/
4480 /* genDiv - generates code for division */
4481 /*-----------------------------------------------------------------*/
4485 operand *left = IC_LEFT (ic);
4486 operand *right = IC_RIGHT (ic);
4487 operand *result = IC_RESULT (ic);
4489 D (emitcode (";", "genDiv "););
4491 /* assign the amsops */
4494 /* special cases first */
4496 if (AOP_TYPE (left) == AOP_CRY &&
4497 AOP_TYPE (right) == AOP_CRY)
4499 genDivbits (left, right, result, ic);
4503 /* if both are of size == 1 */
4504 if (AOP_SIZE (left) == 1 &&
4505 AOP_SIZE (right) == 1)
4507 genDivOneByte (left, right, result, ic);
4511 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4512 /* use the ds390 ARITHMETIC accel UNIT */
4513 genDivTwoByte (left, right, result, ic);
4516 /* should have been converted to function call */
4519 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4520 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4521 freeAsmop (result, NULL, ic, TRUE);
4524 /*-----------------------------------------------------------------*/
4525 /* genModbits :- modulus of bits */
4526 /*-----------------------------------------------------------------*/
4528 genModbits (operand * left,
4536 /* the result must be bit */
4537 LOAD_AB_FOR_DIV (left, right, l);
4538 emitcode ("div", "ab");
4539 emitcode ("mov", "a,b");
4540 emitcode ("rrc", "a");
4541 aopOp(result, ic, TRUE, FALSE);
4542 aopPut (AOP (result), "c", 0);
4545 /*-----------------------------------------------------------------*/
4546 /* genModOneByte : 8 bit modulus */
4547 /*-----------------------------------------------------------------*/
4549 genModOneByte (operand * left,
4554 sym_link *opetype = operandType (result);
4558 /* signed or unsigned */
4559 if (SPEC_USIGN (opetype))
4561 /* unsigned is easy */
4562 LOAD_AB_FOR_DIV (left, right, l);
4563 emitcode ("div", "ab");
4564 aopOp(result, ic, TRUE, FALSE);
4565 aopPut (AOP (result), "b", 0);
4569 /* signed is a little bit more difficult */
4571 /* save the signs of the operands */
4572 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4575 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4576 emitcode ("push", "acc"); /* save it on the stack */
4578 /* now sign adjust for both left & right */
4579 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4582 lbl = newiTempLabel (NULL);
4583 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4584 emitcode ("cpl", "a");
4585 emitcode ("inc", "a");
4586 emitcode ("", "%05d$:", (lbl->key + 100));
4587 emitcode ("mov", "b,a");
4589 /* sign adjust left side */
4590 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4593 lbl = newiTempLabel (NULL);
4594 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4595 emitcode ("cpl", "a");
4596 emitcode ("inc", "a");
4597 emitcode ("", "%05d$:", (lbl->key + 100));
4599 /* now the multiplication */
4600 emitcode ("nop", "; workaround for DS80C390 div bug.");
4601 emitcode ("div", "ab");
4602 /* we are interested in the lower order
4604 lbl = newiTempLabel (NULL);
4605 emitcode ("pop", "acc");
4606 /* if there was an over flow we don't
4607 adjust the sign of the result */
4608 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4609 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4611 emitcode ("clr", "a");
4612 emitcode ("subb", "a,b");
4613 emitcode ("mov", "b,a");
4614 emitcode ("", "%05d$:", (lbl->key + 100));
4616 /* now we are done */
4617 aopOp(result, ic, TRUE, FALSE);
4618 aopPut (AOP (result), "b", 0);
4622 /*-----------------------------------------------------------------*/
4623 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
4624 /*-----------------------------------------------------------------*/
4625 static void genModTwoByte (operand *left, operand *right,
4626 operand *result, iCode *ic)
4628 sym_link *retype = getSpec(operandType(right));
4629 sym_link *letype = getSpec(operandType(left));
4630 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4633 /* load up MA with left */
4635 lbl = newiTempLabel(NULL);
4636 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4637 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4638 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4639 emitcode ("xch", "a,b");
4640 emitcode ("cpl","a");
4641 emitcode ("add", "a,#1");
4642 emitcode ("xch", "a,b");
4643 emitcode ("cpl", "a"); // msb
4644 emitcode ("addc","a,#0");
4645 emitcode ("","%05d$:",lbl->key+100);
4646 emitcode ("mov","ma,b");
4647 emitcode ("mov","ma,a");
4649 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4650 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4653 /* load up MB with right */
4655 if (AOP_TYPE(right) == AOP_LIT) {
4656 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4660 emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4661 emitcode ("mov","mb,#0x%02x",val & 0xff);
4663 lbl = newiTempLabel(NULL);
4664 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4665 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4666 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4667 emitcode ("xch", "a,b");
4668 emitcode ("cpl","a");
4669 emitcode ("add", "a,#1");
4670 emitcode ("xch", "a,b");
4671 emitcode ("cpl", "a"); // msb
4672 emitcode ("addc", "a,#0");
4673 emitcode ("","%05d$:",lbl->key+100);
4674 emitcode ("mov","mb,b");
4675 emitcode ("mov","mb,a");
4678 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4679 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4682 /* wait for multiplication to finish */
4683 lbl = newiTempLabel(NULL);
4684 emitcode("","%05d$:", lbl->key+100);
4685 emitcode("mov","a,mcnt1");
4686 emitcode("anl","a,#0x80");
4687 emitcode("jnz","%05d$",lbl->key+100);
4689 freeAsmop (left, NULL, ic, TRUE);
4690 freeAsmop (right, NULL, ic,TRUE);
4691 aopOp(result, ic, TRUE, FALSE);
4693 aopPut(AOP(result),"mb",1);
4694 aopPut(AOP(result),"mb",0);
4695 freeAsmop (result, NULL, ic, TRUE);
4699 /*-----------------------------------------------------------------*/
4700 /* genMod - generates code for division */
4701 /*-----------------------------------------------------------------*/
4705 operand *left = IC_LEFT (ic);
4706 operand *right = IC_RIGHT (ic);
4707 operand *result = IC_RESULT (ic);
4709 D (emitcode (";", "genMod "); );
4711 /* assign the amsops */
4714 /* special cases first */
4716 if (AOP_TYPE (left) == AOP_CRY &&
4717 AOP_TYPE (right) == AOP_CRY)
4719 genModbits (left, right, result, ic);
4723 /* if both are of size == 1 */
4724 if (AOP_SIZE (left) == 1 &&
4725 AOP_SIZE (right) == 1)
4727 genModOneByte (left, right, result, ic);
4731 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4732 /* use the ds390 ARITHMETIC accel UNIT */
4733 genModTwoByte (left, right, result, ic);
4737 /* should have been converted to function call */
4741 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4742 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4743 freeAsmop (result, NULL, ic, TRUE);
4746 /*-----------------------------------------------------------------*/
4747 /* genIfxJump :- will create a jump depending on the ifx */
4748 /*-----------------------------------------------------------------*/
4750 genIfxJump (iCode * ic, char *jval)
4753 symbol *tlbl = newiTempLabel (NULL);
4756 D (emitcode (";", "genIfxJump ");
4759 /* if true label then we jump if condition
4763 jlbl = IC_TRUE (ic);
4764 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4765 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4769 /* false label is present */
4770 jlbl = IC_FALSE (ic);
4771 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4772 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4774 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4775 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4777 emitcode (inst, "%05d$", tlbl->key + 100);
4778 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4779 emitcode ("", "%05d$:", tlbl->key + 100);
4781 /* mark the icode as generated */
4785 /*-----------------------------------------------------------------*/
4786 /* genCmp :- greater or less than comparison */
4787 /*-----------------------------------------------------------------*/
4789 genCmp (operand * left, operand * right,
4790 iCode * ic, iCode * ifx, int sign)
4792 int size, offset = 0;
4793 unsigned long lit = 0L;
4796 D (emitcode (";", "genCmp");
4799 result = IC_RESULT (ic);
4801 /* if left & right are bit variables */
4802 if (AOP_TYPE (left) == AOP_CRY &&
4803 AOP_TYPE (right) == AOP_CRY)
4805 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4806 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4810 /* subtract right from left if at the
4811 end the carry flag is set then we know that
4812 left is greater than right */
4813 size = max (AOP_SIZE (left), AOP_SIZE (right));
4815 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4816 if ((size == 1) && !sign &&
4817 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4819 symbol *lbl = newiTempLabel (NULL);
4820 emitcode ("cjne", "%s,%s,%05d$",
4821 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4822 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4824 emitcode ("", "%05d$:", lbl->key + 100);
4828 if (AOP_TYPE (right) == AOP_LIT)
4830 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4831 /* optimize if(x < 0) or if(x >= 0) */
4840 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4842 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4843 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4845 aopOp (result, ic, FALSE, FALSE);
4847 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4849 freeAsmop (result, NULL, ic, TRUE);
4850 genIfxJump (ifx, "acc.7");
4855 emitcode ("rlc", "a");
4857 goto release_freedLR;
4865 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4866 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4867 emitcode (";", "genCmp #2");
4868 if (sign && (size == 0))
4870 emitcode (";", "genCmp #3");
4871 emitcode ("xrl", "a,#0x80");
4872 if (AOP_TYPE (right) == AOP_LIT)
4874 unsigned long lit = (unsigned long)
4875 floatFromVal (AOP (right)->aopu.aop_lit);
4876 emitcode (";", "genCmp #3.1");
4877 emitcode ("subb", "a,#0x%02x",
4878 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4882 emitcode (";", "genCmp #3.2");
4883 if (AOP_NEEDSACC (right))
4885 emitcode ("push", "acc");
4887 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4888 FALSE, FALSE, FALSE));
4889 emitcode ("xrl", "b,#0x80");
4890 if (AOP_NEEDSACC (right))
4892 emitcode ("pop", "acc");
4894 emitcode ("subb", "a,b");
4901 emitcode (";", "genCmp #4");
4902 if (AOP_NEEDSACC (right))
4905 emitcode (";", "genCmp #4.1");
4906 emitcode ("xch", "a, b");
4907 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4908 emitcode ("xch", "a, b");
4913 emitcode (";", "genCmp #4.2");
4914 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4917 emitcode ("subb", "a,%s", s);
4924 /* Don't need the left & right operands any more; do need the result. */
4925 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4926 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4928 aopOp (result, ic, FALSE, FALSE);
4932 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4938 /* if the result is used in the next
4939 ifx conditional branch then generate
4940 code a little differently */
4943 genIfxJump (ifx, "c");
4949 /* leave the result in acc */
4951 freeAsmop (result, NULL, ic, TRUE);
4954 /*-----------------------------------------------------------------*/
4955 /* genCmpGt :- greater than comparison */
4956 /*-----------------------------------------------------------------*/
4958 genCmpGt (iCode * ic, iCode * ifx)
4960 operand *left, *right;
4961 sym_link *letype, *retype;
4964 D (emitcode (";", "genCmpGt ");
4967 left = IC_LEFT (ic);
4968 right = IC_RIGHT (ic);
4970 letype = getSpec (operandType (left));
4971 retype = getSpec (operandType (right));
4972 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4974 /* assign the left & right amsops */
4977 genCmp (right, left, ic, ifx, sign);
4980 /*-----------------------------------------------------------------*/
4981 /* genCmpLt - less than comparisons */
4982 /*-----------------------------------------------------------------*/
4984 genCmpLt (iCode * ic, iCode * ifx)
4986 operand *left, *right;
4987 sym_link *letype, *retype;
4990 D (emitcode (";", "genCmpLt "););
4992 left = IC_LEFT (ic);
4993 right = IC_RIGHT (ic);
4995 letype = getSpec (operandType (left));
4996 retype = getSpec (operandType (right));
4997 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4999 /* assign the left & right amsops */
5002 genCmp (left, right, ic, ifx, sign);
5005 /*-----------------------------------------------------------------*/
5006 /* gencjneshort - compare and jump if not equal */
5007 /*-----------------------------------------------------------------*/
5009 gencjneshort (operand * left, operand * right, symbol * lbl)
5011 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5013 unsigned long lit = 0L;
5015 D (emitcode (";", "gencjneshort");
5018 /* if the left side is a literal or
5019 if the right is in a pointer register and left
5021 if ((AOP_TYPE (left) == AOP_LIT) ||
5022 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5029 if (AOP_TYPE (right) == AOP_LIT)
5030 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5032 if (opIsGptr (left) || opIsGptr (right))
5034 /* We are comparing a generic pointer to something.
5035 * Exclude the generic type byte from the comparison.
5038 D (emitcode (";", "cjneshort: generic ptr special case.");
5043 /* if the right side is a literal then anything goes */
5044 if (AOP_TYPE (right) == AOP_LIT &&
5045 AOP_TYPE (left) != AOP_DIR)
5049 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5051 emitcode ("cjne", "a,%s,%05d$",
5052 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5058 /* if the right side is in a register or in direct space or
5059 if the left is a pointer register & right is not */
5060 else if (AOP_TYPE (right) == AOP_REG ||
5061 AOP_TYPE (right) == AOP_DIR ||
5062 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5063 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5067 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5068 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5069 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5070 emitcode ("jnz", "%05d$", lbl->key + 100);
5072 emitcode ("cjne", "a,%s,%05d$",
5073 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5080 /* right is a pointer reg need both a & b */
5083 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5084 if (strcmp (l, "b"))
5085 emitcode ("mov", "b,%s", l);
5086 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5087 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5093 /*-----------------------------------------------------------------*/
5094 /* gencjne - compare and jump if not equal */
5095 /*-----------------------------------------------------------------*/
5097 gencjne (operand * left, operand * right, symbol * lbl)
5099 symbol *tlbl = newiTempLabel (NULL);
5101 D (emitcode (";", "gencjne");
5104 gencjneshort (left, right, lbl);
5106 emitcode ("mov", "a,%s", one);
5107 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5108 emitcode ("", "%05d$:", lbl->key + 100);
5109 emitcode ("clr", "a");
5110 emitcode ("", "%05d$:", tlbl->key + 100);
5113 /*-----------------------------------------------------------------*/
5114 /* genCmpEq - generates code for equal to */
5115 /*-----------------------------------------------------------------*/
5117 genCmpEq (iCode * ic, iCode * ifx)
5119 operand *left, *right, *result;
5121 D (emitcode (";", "genCmpEq ");
5125 AOP_SET_LOCALS (ic);
5127 /* if literal, literal on the right or
5128 if the right is in a pointer register and left
5130 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5131 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5133 operand *t = IC_RIGHT (ic);
5134 IC_RIGHT (ic) = IC_LEFT (ic);
5138 if (ifx && /* !AOP_SIZE(result) */
5139 OP_SYMBOL (result) &&
5140 OP_SYMBOL (result)->regType == REG_CND)
5143 /* if they are both bit variables */
5144 if (AOP_TYPE (left) == AOP_CRY &&
5145 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5147 if (AOP_TYPE (right) == AOP_LIT)
5149 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5152 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5153 emitcode ("cpl", "c");
5157 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5161 emitcode ("clr", "c");
5163 /* AOP_TYPE(right) == AOP_CRY */
5167 symbol *lbl = newiTempLabel (NULL);
5168 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5169 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5170 emitcode ("cpl", "c");
5171 emitcode ("", "%05d$:", (lbl->key + 100));
5173 /* if true label then we jump if condition
5175 tlbl = newiTempLabel (NULL);
5178 emitcode ("jnc", "%05d$", tlbl->key + 100);
5179 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5183 emitcode ("jc", "%05d$", tlbl->key + 100);
5184 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5186 emitcode ("", "%05d$:", tlbl->key + 100);
5190 tlbl = newiTempLabel (NULL);
5191 gencjneshort (left, right, tlbl);
5194 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5195 emitcode ("", "%05d$:", tlbl->key + 100);
5199 symbol *lbl = newiTempLabel (NULL);
5200 emitcode ("sjmp", "%05d$", lbl->key + 100);
5201 emitcode ("", "%05d$:", tlbl->key + 100);
5202 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5203 emitcode ("", "%05d$:", lbl->key + 100);
5206 /* mark the icode as generated */
5209 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5210 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5214 /* if they are both bit variables */
5215 if (AOP_TYPE (left) == AOP_CRY &&
5216 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5218 if (AOP_TYPE (right) == AOP_LIT)
5220 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5223 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5224 emitcode ("cpl", "c");
5228 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5232 emitcode ("clr", "c");
5234 /* AOP_TYPE(right) == AOP_CRY */
5238 symbol *lbl = newiTempLabel (NULL);
5239 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5240 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5241 emitcode ("cpl", "c");
5242 emitcode ("", "%05d$:", (lbl->key + 100));
5245 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5246 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5248 aopOp (result, ic, TRUE, FALSE);
5251 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5258 genIfxJump (ifx, "c");
5261 /* if the result is used in an arithmetic operation
5262 then put the result in place */
5267 gencjne (left, right, newiTempLabel (NULL));
5269 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5270 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5272 aopOp (result, ic, TRUE, FALSE);
5274 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5276 aopPut (AOP (result), "a", 0);
5281 genIfxJump (ifx, "a");
5284 /* if the result is used in an arithmetic operation
5285 then put the result in place */
5286 if (AOP_TYPE (result) != AOP_CRY)
5288 /* leave the result in acc */
5292 freeAsmop (result, NULL, ic, TRUE);
5295 /*-----------------------------------------------------------------*/
5296 /* ifxForOp - returns the icode containing the ifx for operand */
5297 /*-----------------------------------------------------------------*/
5299 ifxForOp (operand * op, iCode * ic)
5301 /* if true symbol then needs to be assigned */
5302 if (IS_TRUE_SYMOP (op))
5305 /* if this has register type condition and
5306 the next instruction is ifx with the same operand
5307 and live to of the operand is upto the ifx only then */
5309 ic->next->op == IFX &&
5310 IC_COND (ic->next)->key == op->key &&
5311 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5316 /*-----------------------------------------------------------------*/
5317 /* genAndOp - for && operation */
5318 /*-----------------------------------------------------------------*/
5320 genAndOp (iCode * ic)
5322 operand *left, *right, *result;
5325 D (emitcode (";", "genAndOp "););
5327 /* note here that && operations that are in an
5328 if statement are taken away by backPatchLabels
5329 only those used in arthmetic operations remain */
5331 AOP_SET_LOCALS (ic);
5333 /* if both are bit variables */
5334 if (AOP_TYPE (left) == AOP_CRY &&
5335 AOP_TYPE (right) == AOP_CRY)
5337 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5338 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5339 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5340 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5342 aopOp (result,ic,FALSE, FALSE);
5347 tlbl = newiTempLabel (NULL);
5349 emitcode ("jz", "%05d$", tlbl->key + 100);
5351 emitcode ("", "%05d$:", tlbl->key + 100);
5352 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5353 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5355 aopOp (result,ic,FALSE, FALSE);
5358 freeAsmop (result, NULL, ic, TRUE);
5362 /*-----------------------------------------------------------------*/
5363 /* genOrOp - for || operation */
5364 /*-----------------------------------------------------------------*/
5366 genOrOp (iCode * ic)
5368 operand *left, *right, *result;
5371 D (emitcode (";", "genOrOp "););
5373 /* note here that || operations that are in an
5374 if statement are taken away by backPatchLabels
5375 only those used in arthmetic operations remain */
5377 AOP_SET_LOCALS (ic);
5379 /* if both are bit variables */
5380 if (AOP_TYPE (left) == AOP_CRY &&
5381 AOP_TYPE (right) == AOP_CRY)
5383 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5384 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5385 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5386 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5388 aopOp (result,ic,FALSE, FALSE);
5394 tlbl = newiTempLabel (NULL);
5396 emitcode ("jnz", "%05d$", tlbl->key + 100);
5398 emitcode ("", "%05d$:", tlbl->key + 100);
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 freeAsmop (result, NULL, ic, TRUE);
5410 /*-----------------------------------------------------------------*/
5411 /* isLiteralBit - test if lit == 2^n */
5412 /*-----------------------------------------------------------------*/
5414 isLiteralBit (unsigned long lit)
5416 unsigned long pw[32] =
5417 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5418 0x100L, 0x200L, 0x400L, 0x800L,
5419 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5420 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5421 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5422 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5423 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5426 for (idx = 0; idx < 32; idx++)
5432 /*-----------------------------------------------------------------*/
5433 /* continueIfTrue - */
5434 /*-----------------------------------------------------------------*/
5436 continueIfTrue (iCode * ic)
5439 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5443 /*-----------------------------------------------------------------*/
5445 /*-----------------------------------------------------------------*/
5447 jumpIfTrue (iCode * ic)
5450 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5454 /*-----------------------------------------------------------------*/
5455 /* jmpTrueOrFalse - */
5456 /*-----------------------------------------------------------------*/
5458 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5460 // ugly but optimized by peephole
5463 symbol *nlbl = newiTempLabel (NULL);
5464 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5465 emitcode ("", "%05d$:", tlbl->key + 100);
5466 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5467 emitcode ("", "%05d$:", nlbl->key + 100);
5471 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5472 emitcode ("", "%05d$:", tlbl->key + 100);
5477 // Generate code to perform a bit-wise logic operation
5478 // on two operands in far space (assumed to already have been
5479 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5480 // in far space. This requires pushing the result on the stack
5481 // then popping it into the result.
5483 genFarFarLogicOp(iCode *ic, char *logicOp)
5485 int size, resultSize, compSize;
5489 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5490 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5491 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5493 _startLazyDPSEvaluation();
5494 for (size = compSize; (size--); offset++)
5496 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5497 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5498 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5500 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5501 emitcode ("push", "acc");
5503 _endLazyDPSEvaluation();
5505 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5506 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5507 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5509 resultSize = AOP_SIZE(IC_RESULT(ic));
5511 ADJUST_PUSHED_RESULT(compSize, resultSize);
5513 _startLazyDPSEvaluation();
5516 emitcode ("pop", "acc");
5517 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5519 _endLazyDPSEvaluation();
5520 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5524 /*-----------------------------------------------------------------*/
5525 /* genAnd - code for and */
5526 /*-----------------------------------------------------------------*/
5528 genAnd (iCode * ic, iCode * ifx)
5530 operand *left, *right, *result;
5531 int size, offset = 0;
5532 unsigned long lit = 0L;
5537 D (emitcode (";", "genAnd "););
5539 AOP_OP_3_NOFATAL (ic, pushResult);
5540 AOP_SET_LOCALS (ic);
5544 genFarFarLogicOp(ic, "anl");
5549 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5551 AOP_TYPE (left), AOP_TYPE (right));
5552 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5554 AOP_SIZE (left), AOP_SIZE (right));
5557 /* if left is a literal & right is not then exchange them */
5558 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5559 #ifdef LOGIC_OPS_BROKEN
5560 || AOP_NEEDSACC (left)
5564 operand *tmp = right;
5569 /* if result = right then exchange them */
5570 if (sameRegs (AOP (result), AOP (right)))
5572 operand *tmp = right;
5577 /* if right is bit then exchange them */
5578 if (AOP_TYPE (right) == AOP_CRY &&
5579 AOP_TYPE (left) != AOP_CRY)
5581 operand *tmp = right;
5585 if (AOP_TYPE (right) == AOP_LIT)
5586 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5588 size = AOP_SIZE (result);
5591 // result = bit & yy;
5592 if (AOP_TYPE (left) == AOP_CRY)
5594 // c = bit & literal;
5595 if (AOP_TYPE (right) == AOP_LIT)
5599 if (size && sameRegs (AOP (result), AOP (left)))
5602 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5607 if (size && (AOP_TYPE (result) == AOP_CRY))
5609 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5612 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5617 emitcode ("clr", "c");
5622 if (AOP_TYPE (right) == AOP_CRY)
5625 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5626 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5631 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5633 emitcode ("rrc", "a");
5634 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5642 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5643 genIfxJump (ifx, "c");
5647 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5648 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5649 if ((AOP_TYPE (right) == AOP_LIT) &&
5650 (AOP_TYPE (result) == AOP_CRY) &&
5651 (AOP_TYPE (left) != AOP_CRY))
5653 int posbit = isLiteralBit (lit);
5658 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5661 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5667 sprintf (buffer, "acc.%d", posbit & 0x07);
5668 genIfxJump (ifx, buffer);
5675 symbol *tlbl = newiTempLabel (NULL);
5676 int sizel = AOP_SIZE (left);
5678 emitcode ("setb", "c");
5681 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5683 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5685 if ((posbit = isLiteralBit (bytelit)) != 0)
5686 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5689 if (bytelit != 0x0FFL)
5690 emitcode ("anl", "a,%s",
5691 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5692 emitcode ("jnz", "%05d$", tlbl->key + 100);
5697 // bit = left & literal
5700 emitcode ("clr", "c");
5701 emitcode ("", "%05d$:", tlbl->key + 100);
5703 // if(left & literal)
5707 jmpTrueOrFalse (ifx, tlbl);
5715 /* if left is same as result */
5716 if (sameRegs (AOP (result), AOP (left)))
5718 for (; size--; offset++)
5720 if (AOP_TYPE (right) == AOP_LIT)
5722 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5724 else if (bytelit == 0)
5725 aopPut (AOP (result), zero, offset);
5726 else if (IS_AOP_PREG (result))
5728 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5729 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5730 aopPut (AOP (result), "a", offset);
5733 emitcode ("anl", "%s,%s",
5734 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5735 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5739 if (AOP_TYPE (left) == AOP_ACC)
5740 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5743 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5744 if (IS_AOP_PREG (result))
5746 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5747 aopPut (AOP (result), "a", offset);
5751 emitcode ("anl", "%s,a",
5752 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5759 // left & result in different registers
5760 if (AOP_TYPE (result) == AOP_CRY)
5763 // if(size), result in bit
5764 // if(!size && ifx), conditional oper: if(left & right)
5765 symbol *tlbl = newiTempLabel (NULL);
5766 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5768 emitcode ("setb", "c");
5771 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5772 emitcode ("anl", "a,%s",
5773 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5775 if (AOP_TYPE(left)==AOP_ACC) {
5776 emitcode("mov", "b,a");
5777 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5778 emitcode("anl", "a,b");
5780 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5781 emitcode ("anl", "a,%s",
5782 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5785 emitcode ("jnz", "%05d$", tlbl->key + 100);
5791 emitcode ("", "%05d$:", tlbl->key + 100);
5795 jmpTrueOrFalse (ifx, tlbl);
5799 for (; (size--); offset++)
5802 // result = left & right
5803 if (AOP_TYPE (right) == AOP_LIT)
5805 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5807 aopPut (AOP (result),
5808 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5812 else if (bytelit == 0)
5814 aopPut (AOP (result), zero, offset);
5817 D (emitcode (";", "better literal AND."););
5818 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5819 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5820 FALSE, FALSE, FALSE));
5825 // faster than result <- left, anl result,right
5826 // and better if result is SFR
5827 if (AOP_TYPE (left) == AOP_ACC)
5829 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5830 FALSE, FALSE, FALSE));
5834 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
5835 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
5837 emitcode("mov", "b,a");
5841 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5842 emitcode ("anl", "a,%s", rOp);
5845 aopPut (AOP (result), "a", offset);
5851 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5852 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5853 freeAsmop (result, NULL, ic, TRUE);
5857 /*-----------------------------------------------------------------*/
5858 /* genOr - code for or */
5859 /*-----------------------------------------------------------------*/
5861 genOr (iCode * ic, iCode * ifx)
5863 operand *left, *right, *result;
5864 int size, offset = 0;
5865 unsigned long lit = 0L;
5868 D (emitcode (";", "genOr "););
5870 AOP_OP_3_NOFATAL (ic, pushResult);
5871 AOP_SET_LOCALS (ic);
5875 genFarFarLogicOp(ic, "orl");
5881 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5883 AOP_TYPE (left), AOP_TYPE (right));
5884 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5886 AOP_SIZE (left), AOP_SIZE (right));
5889 /* if left is a literal & right is not then exchange them */
5890 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5891 #ifdef LOGIC_OPS_BROKEN
5892 || AOP_NEEDSACC (left) // I think this is a net loss now.
5896 operand *tmp = right;
5901 /* if result = right then exchange them */
5902 if (sameRegs (AOP (result), AOP (right)))
5904 operand *tmp = right;
5909 /* if right is bit then exchange them */
5910 if (AOP_TYPE (right) == AOP_CRY &&
5911 AOP_TYPE (left) != AOP_CRY)
5913 operand *tmp = right;
5917 if (AOP_TYPE (right) == AOP_LIT)
5918 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5920 size = AOP_SIZE (result);
5924 if (AOP_TYPE (left) == AOP_CRY)
5926 if (AOP_TYPE (right) == AOP_LIT)
5928 // c = bit & literal;
5931 // lit != 0 => result = 1
5932 if (AOP_TYPE (result) == AOP_CRY)
5935 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5937 continueIfTrue (ifx);
5940 emitcode ("setb", "c");
5944 // lit == 0 => result = left
5945 if (size && sameRegs (AOP (result), AOP (left)))
5947 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5952 if (AOP_TYPE (right) == AOP_CRY)
5955 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5956 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5961 symbol *tlbl = newiTempLabel (NULL);
5962 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5963 emitcode ("setb", "c");
5964 emitcode ("jb", "%s,%05d$",
5965 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5967 emitcode ("jnz", "%05d$", tlbl->key + 100);
5968 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5970 jmpTrueOrFalse (ifx, tlbl);
5976 emitcode ("", "%05d$:", tlbl->key + 100);
5985 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5986 genIfxJump (ifx, "c");
5990 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5991 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5992 if ((AOP_TYPE (right) == AOP_LIT) &&
5993 (AOP_TYPE (result) == AOP_CRY) &&
5994 (AOP_TYPE (left) != AOP_CRY))
6000 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6002 continueIfTrue (ifx);
6007 // lit = 0, result = boolean(left)
6009 emitcode ("setb", "c");
6013 symbol *tlbl = newiTempLabel (NULL);
6014 emitcode ("jnz", "%05d$", tlbl->key + 100);
6016 emitcode ("", "%05d$:", tlbl->key + 100);
6020 genIfxJump (ifx, "a");
6028 /* if left is same as result */
6029 if (sameRegs (AOP (result), AOP (left)))
6031 for (; size--; offset++)
6033 if (AOP_TYPE (right) == AOP_LIT)
6035 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6041 if (IS_AOP_PREG (left))
6043 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6044 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6045 aopPut (AOP (result), "a", offset);
6049 emitcode ("orl", "%s,%s",
6050 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6051 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6057 if (AOP_TYPE (left) == AOP_ACC)
6059 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6063 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6064 if (IS_AOP_PREG (left))
6066 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6067 aopPut (AOP (result), "a", offset);
6071 emitcode ("orl", "%s,a",
6072 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6080 // left & result in different registers
6081 if (AOP_TYPE (result) == AOP_CRY)
6084 // if(size), result in bit
6085 // if(!size && ifx), conditional oper: if(left | right)
6086 symbol *tlbl = newiTempLabel (NULL);
6087 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6089 emitcode ("setb", "c");
6092 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6093 emitcode ("orl", "a,%s",
6094 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6096 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6097 emitcode ("orl", "a,%s",
6098 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6100 emitcode ("jnz", "%05d$", tlbl->key + 100);
6106 emitcode ("", "%05d$:", tlbl->key + 100);
6110 jmpTrueOrFalse (ifx, tlbl);
6114 _startLazyDPSEvaluation();
6115 for (; (size--); offset++)
6118 // result = left & right
6119 if (AOP_TYPE (right) == AOP_LIT)
6121 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6123 aopPut (AOP (result),
6124 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6128 D (emitcode (";", "better literal OR."););
6129 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6130 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6131 FALSE, FALSE, FALSE));
6136 // faster than result <- left, anl result,right
6137 // and better if result is SFR
6138 if (AOP_TYPE (left) == AOP_ACC)
6140 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6141 FALSE, FALSE, FALSE));
6145 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6147 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6149 emitcode("mov", "b,a");
6153 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6154 emitcode ("orl", "a,%s", rOp);
6157 aopPut (AOP (result), "a", offset);
6159 _endLazyDPSEvaluation();
6164 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6165 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6166 freeAsmop (result, NULL, ic, TRUE);
6169 /*-----------------------------------------------------------------*/
6170 /* genXor - code for xclusive or */
6171 /*-----------------------------------------------------------------*/
6173 genXor (iCode * ic, iCode * ifx)
6175 operand *left, *right, *result;
6176 int size, offset = 0;
6177 unsigned long lit = 0L;
6180 D (emitcode (";", "genXor "););
6182 AOP_OP_3_NOFATAL (ic, pushResult);
6183 AOP_SET_LOCALS (ic);
6187 genFarFarLogicOp(ic, "xrl");
6192 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6194 AOP_TYPE (left), AOP_TYPE (right));
6195 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6197 AOP_SIZE (left), AOP_SIZE (right));
6200 /* if left is a literal & right is not ||
6201 if left needs acc & right does not */
6202 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6203 #ifdef LOGIC_OPS_BROKEN
6204 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6208 operand *tmp = right;
6213 /* if result = right then exchange them */
6214 if (sameRegs (AOP (result), AOP (right)))
6216 operand *tmp = right;
6221 /* if right is bit then exchange them */
6222 if (AOP_TYPE (right) == AOP_CRY &&
6223 AOP_TYPE (left) != AOP_CRY)
6225 operand *tmp = right;
6229 if (AOP_TYPE (right) == AOP_LIT)
6230 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6232 size = AOP_SIZE (result);
6236 if (AOP_TYPE (left) == AOP_CRY)
6238 if (AOP_TYPE (right) == AOP_LIT)
6240 // c = bit & literal;
6243 // lit>>1 != 0 => result = 1
6244 if (AOP_TYPE (result) == AOP_CRY)
6247 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6249 continueIfTrue (ifx);
6252 emitcode ("setb", "c");
6259 // lit == 0, result = left
6260 if (size && sameRegs (AOP (result), AOP (left)))
6262 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6266 // lit == 1, result = not(left)
6267 if (size && sameRegs (AOP (result), AOP (left)))
6269 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6274 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6275 emitcode ("cpl", "c");
6284 symbol *tlbl = newiTempLabel (NULL);
6285 if (AOP_TYPE (right) == AOP_CRY)
6288 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6292 int sizer = AOP_SIZE (right);
6294 // if val>>1 != 0, result = 1
6295 emitcode ("setb", "c");
6298 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6300 // test the msb of the lsb
6301 emitcode ("anl", "a,#0xfe");
6302 emitcode ("jnz", "%05d$", tlbl->key + 100);
6306 emitcode ("rrc", "a");
6308 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6309 emitcode ("cpl", "c");
6310 emitcode ("", "%05d$:", (tlbl->key + 100));
6317 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6318 genIfxJump (ifx, "c");
6322 if (sameRegs (AOP (result), AOP (left)))
6324 /* if left is same as result */
6325 for (; size--; offset++)
6327 if (AOP_TYPE (right) == AOP_LIT)
6329 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6331 else if (IS_AOP_PREG (left))
6333 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6334 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6335 aopPut (AOP (result), "a", offset);
6338 emitcode ("xrl", "%s,%s",
6339 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6340 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6344 if (AOP_TYPE (left) == AOP_ACC)
6345 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6348 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6349 if (IS_AOP_PREG (left))
6351 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6352 aopPut (AOP (result), "a", offset);
6355 emitcode ("xrl", "%s,a",
6356 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6363 // left & result in different registers
6364 if (AOP_TYPE (result) == AOP_CRY)
6367 // if(size), result in bit
6368 // if(!size && ifx), conditional oper: if(left ^ right)
6369 symbol *tlbl = newiTempLabel (NULL);
6370 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6372 emitcode ("setb", "c");
6375 if ((AOP_TYPE (right) == AOP_LIT) &&
6376 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6378 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6382 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6383 emitcode ("xrl", "a,%s",
6384 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6386 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6387 emitcode ("xrl", "a,%s",
6388 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6391 emitcode ("jnz", "%05d$", tlbl->key + 100);
6397 emitcode ("", "%05d$:", tlbl->key + 100);
6401 jmpTrueOrFalse (ifx, tlbl);
6404 for (; (size--); offset++)
6407 // result = left & right
6408 if (AOP_TYPE (right) == AOP_LIT)
6410 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6412 aopPut (AOP (result),
6413 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6417 D (emitcode (";", "better literal XOR.");
6419 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6420 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6421 FALSE, FALSE, FALSE));
6425 // faster than result <- left, anl result,right
6426 // and better if result is SFR
6427 if (AOP_TYPE (left) == AOP_ACC)
6429 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6430 FALSE, FALSE, FALSE));
6434 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6435 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6437 emitcode("mov", "b,a");
6441 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6442 emitcode ("xrl", "a,%s", rOp);
6445 aopPut (AOP (result), "a", offset);
6450 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6451 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6452 freeAsmop (result, NULL, ic, TRUE);
6455 /*-----------------------------------------------------------------*/
6456 /* genInline - write the inline code out */
6457 /*-----------------------------------------------------------------*/
6459 genInline (iCode * ic)
6461 char *buffer, *bp, *bp1;
6463 D (emitcode (";", "genInline ");
6466 _G.inLine += (!options.asmpeep);
6468 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6469 strcpy (buffer, IC_INLINE (ic));
6471 /* emit each line as a code */
6496 /* emitcode("",buffer); */
6497 _G.inLine -= (!options.asmpeep);
6500 /*-----------------------------------------------------------------*/
6501 /* genRRC - rotate right with carry */
6502 /*-----------------------------------------------------------------*/
6506 operand *left, *result;
6507 int size, offset = 0;
6510 D (emitcode (";", "genRRC ");
6513 /* rotate right with carry */
6514 left = IC_LEFT (ic);
6515 result = IC_RESULT (ic);
6516 aopOp (left, ic, FALSE, FALSE);
6517 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6519 /* move it to the result */
6520 size = AOP_SIZE (result);
6524 _startLazyDPSEvaluation ();
6527 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6529 emitcode ("rrc", "a");
6530 if (AOP_SIZE (result) > 1)
6531 aopPut (AOP (result), "a", offset--);
6533 _endLazyDPSEvaluation ();
6535 /* now we need to put the carry into the
6536 highest order byte of the result */
6537 if (AOP_SIZE (result) > 1)
6539 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6542 emitcode ("mov", "acc.7,c");
6543 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6544 freeAsmop (left, NULL, ic, TRUE);
6545 freeAsmop (result, NULL, ic, TRUE);
6548 /*-----------------------------------------------------------------*/
6549 /* genRLC - generate code for rotate left with carry */
6550 /*-----------------------------------------------------------------*/
6554 operand *left, *result;
6555 int size, offset = 0;
6558 D (emitcode (";", "genRLC ");
6561 /* rotate right with carry */
6562 left = IC_LEFT (ic);
6563 result = IC_RESULT (ic);
6564 aopOp (left, ic, FALSE, FALSE);
6565 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6567 /* move it to the result */
6568 size = AOP_SIZE (result);
6572 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6574 emitcode ("add", "a,acc");
6575 if (AOP_SIZE (result) > 1)
6577 aopPut (AOP (result), "a", offset++);
6580 _startLazyDPSEvaluation ();
6583 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6585 emitcode ("rlc", "a");
6586 if (AOP_SIZE (result) > 1)
6587 aopPut (AOP (result), "a", offset++);
6589 _endLazyDPSEvaluation ();
6591 /* now we need to put the carry into the
6592 highest order byte of the result */
6593 if (AOP_SIZE (result) > 1)
6595 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6598 emitcode ("mov", "acc.0,c");
6599 aopPut (AOP (result), "a", 0);
6600 freeAsmop (left, NULL, ic, TRUE);
6601 freeAsmop (result, NULL, ic, TRUE);
6604 /*-----------------------------------------------------------------*/
6605 /* genGetHbit - generates code get highest order bit */
6606 /*-----------------------------------------------------------------*/
6608 genGetHbit (iCode * ic)
6610 operand *left, *result;
6611 left = IC_LEFT (ic);
6612 result = IC_RESULT (ic);
6613 aopOp (left, ic, FALSE, FALSE);
6614 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6616 D (emitcode (";", "genGetHbit ");
6619 /* get the highest order byte into a */
6620 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6621 if (AOP_TYPE (result) == AOP_CRY)
6623 emitcode ("rlc", "a");
6628 emitcode ("rl", "a");
6629 emitcode ("anl", "a,#0x01");
6634 freeAsmop (left, NULL, ic, TRUE);
6635 freeAsmop (result, NULL, ic, TRUE);
6638 /*-----------------------------------------------------------------*/
6639 /* AccRol - rotate left accumulator by known count */
6640 /*-----------------------------------------------------------------*/
6642 AccRol (int shCount)
6644 shCount &= 0x0007; // shCount : 0..7
6651 emitcode ("rl", "a");
6654 emitcode ("rl", "a");
6655 emitcode ("rl", "a");
6658 emitcode ("swap", "a");
6659 emitcode ("rr", "a");
6662 emitcode ("swap", "a");
6665 emitcode ("swap", "a");
6666 emitcode ("rl", "a");
6669 emitcode ("rr", "a");
6670 emitcode ("rr", "a");
6673 emitcode ("rr", "a");
6678 /*-----------------------------------------------------------------*/
6679 /* AccLsh - left shift accumulator by known count */
6680 /*-----------------------------------------------------------------*/
6682 AccLsh (int shCount)
6687 emitcode ("add", "a,acc");
6688 else if (shCount == 2)
6690 emitcode ("add", "a,acc");
6691 emitcode ("add", "a,acc");
6695 /* rotate left accumulator */
6697 /* and kill the lower order bits */
6698 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6703 /*-----------------------------------------------------------------*/
6704 /* AccRsh - right shift accumulator by known count */
6705 /*-----------------------------------------------------------------*/
6707 AccRsh (int shCount)
6714 emitcode ("rrc", "a");
6718 /* rotate right accumulator */
6719 AccRol (8 - shCount);
6720 /* and kill the higher order bits */
6721 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6726 #ifdef BETTER_LITERAL_SHIFT
6727 /*-----------------------------------------------------------------*/
6728 /* AccSRsh - signed right shift accumulator by known count */
6729 /*-----------------------------------------------------------------*/
6731 AccSRsh (int shCount)
6738 emitcode ("mov", "c,acc.7");
6739 emitcode ("rrc", "a");
6741 else if (shCount == 2)
6743 emitcode ("mov", "c,acc.7");
6744 emitcode ("rrc", "a");
6745 emitcode ("mov", "c,acc.7");
6746 emitcode ("rrc", "a");
6750 tlbl = newiTempLabel (NULL);
6751 /* rotate right accumulator */
6752 AccRol (8 - shCount);
6753 /* and kill the higher order bits */
6754 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6755 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6756 emitcode ("orl", "a,#0x%02x",
6757 (unsigned char) ~SRMask[shCount]);
6758 emitcode ("", "%05d$:", tlbl->key + 100);
6764 #ifdef BETTER_LITERAL_SHIFT
6765 /*-----------------------------------------------------------------*/
6766 /* shiftR1Left2Result - shift right one byte from left to result */
6767 /*-----------------------------------------------------------------*/
6769 shiftR1Left2Result (operand * left, int offl,
6770 operand * result, int offr,
6771 int shCount, int sign)
6773 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6774 /* shift right accumulator */
6779 aopPut (AOP (result), "a", offr);
6783 #ifdef BETTER_LITERAL_SHIFT
6784 /*-----------------------------------------------------------------*/
6785 /* shiftL1Left2Result - shift left one byte from left to result */
6786 /*-----------------------------------------------------------------*/
6788 shiftL1Left2Result (operand * left, int offl,
6789 operand * result, int offr, int shCount)
6791 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6792 /* shift left accumulator */
6794 aopPut (AOP (result), "a", offr);
6798 #ifdef BETTER_LITERAL_SHIFT
6799 /*-----------------------------------------------------------------*/
6800 /* movLeft2Result - move byte from left to result */
6801 /*-----------------------------------------------------------------*/
6803 movLeft2Result (operand * left, int offl,
6804 operand * result, int offr, int sign)
6807 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6809 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6811 if (*l == '@' && (IS_AOP_PREG (result)))
6813 emitcode ("mov", "a,%s", l);
6814 aopPut (AOP (result), "a", offr);
6820 aopPut (AOP (result), l, offr);
6824 /* MSB sign in acc.7 ! */
6825 if (getDataSize (left) == offl + 1)
6827 emitcode ("mov", "a,%s", l);
6828 aopPut (AOP (result), "a", offr);
6836 #ifdef BETTER_LITERAL_SHIFT
6837 /*-----------------------------------------------------------------*/
6838 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6839 /*-----------------------------------------------------------------*/
6843 emitcode ("rrc", "a");
6844 emitcode ("xch", "a,%s", x);
6845 emitcode ("rrc", "a");
6846 emitcode ("xch", "a,%s", x);
6850 #ifdef BETTER_LITERAL_SHIFT
6852 /*-----------------------------------------------------------------*/
6853 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6854 /*-----------------------------------------------------------------*/
6858 emitcode ("xch", "a,%s", x);
6859 emitcode ("rlc", "a");
6860 emitcode ("xch", "a,%s", x);
6861 emitcode ("rlc", "a");
6865 #ifdef BETTER_LITERAL_SHIFT
6866 /*-----------------------------------------------------------------*/
6867 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6868 /*-----------------------------------------------------------------*/
6872 emitcode ("xch", "a,%s", x);
6873 emitcode ("add", "a,acc");
6874 emitcode ("xch", "a,%s", x);
6875 emitcode ("rlc", "a");
6879 #ifdef BETTER_LITERAL_SHIFT
6880 /*-----------------------------------------------------------------*/
6881 /* AccAXLsh - left shift a:x by known count (0..7) */
6882 /*-----------------------------------------------------------------*/
6884 AccAXLsh (char *x, int shCount)
6899 case 5: // AAAAABBB:CCCCCDDD
6901 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6903 emitcode ("anl", "a,#0x%02x",
6904 SLMask[shCount]); // BBB00000:CCCCCDDD
6906 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6908 AccRol (shCount); // DDDCCCCC:BBB00000
6910 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6912 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6914 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6916 emitcode ("anl", "a,#0x%02x",
6917 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6919 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6921 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6924 case 6: // AAAAAABB:CCCCCCDD
6925 emitcode ("anl", "a,#0x%02x",
6926 SRMask[shCount]); // 000000BB:CCCCCCDD
6927 emitcode ("mov", "c,acc.0"); // c = B
6928 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6930 AccAXRrl1 (x); // BCCCCCCD:D000000B
6931 AccAXRrl1 (x); // BBCCCCCC:DD000000
6933 emitcode("rrc","a");
6934 emitcode("xch","a,%s", x);
6935 emitcode("rrc","a");
6936 emitcode("mov","c,acc.0"); //<< get correct bit
6937 emitcode("xch","a,%s", x);
6939 emitcode("rrc","a");
6940 emitcode("xch","a,%s", x);
6941 emitcode("rrc","a");
6942 emitcode("xch","a,%s", x);
6945 case 7: // a:x <<= 7
6947 emitcode ("anl", "a,#0x%02x",
6948 SRMask[shCount]); // 0000000B:CCCCCCCD
6950 emitcode ("mov", "c,acc.0"); // c = B
6952 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6954 AccAXRrl1 (x); // BCCCCCCC:D0000000
6963 #ifdef BETTER_LITERAL_SHIFT
6965 /*-----------------------------------------------------------------*/
6966 /* AccAXRsh - right shift a:x known count (0..7) */
6967 /*-----------------------------------------------------------------*/
6969 AccAXRsh (char *x, int shCount)
6977 AccAXRrl1 (x); // 0->a:x
6982 AccAXRrl1 (x); // 0->a:x
6985 AccAXRrl1 (x); // 0->a:x
6990 case 5: // AAAAABBB:CCCCCDDD = a:x
6992 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6994 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6996 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6998 emitcode ("anl", "a,#0x%02x",
6999 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7001 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7003 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7005 emitcode ("anl", "a,#0x%02x",
7006 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7008 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7010 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7012 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7015 case 6: // AABBBBBB:CCDDDDDD
7017 emitcode ("mov", "c,acc.7");
7018 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7020 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7022 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7024 emitcode ("anl", "a,#0x%02x",
7025 SRMask[shCount]); // 000000AA:BBBBBBCC
7028 case 7: // ABBBBBBB:CDDDDDDD
7030 emitcode ("mov", "c,acc.7"); // c = A
7032 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7034 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7036 emitcode ("anl", "a,#0x%02x",
7037 SRMask[shCount]); // 0000000A:BBBBBBBC
7046 #ifdef BETTER_LITERAL_SHIFT
7047 /*-----------------------------------------------------------------*/
7048 /* AccAXRshS - right shift signed a:x known count (0..7) */
7049 /*-----------------------------------------------------------------*/
7051 AccAXRshS (char *x, int shCount)
7059 emitcode ("mov", "c,acc.7");
7060 AccAXRrl1 (x); // s->a:x
7064 emitcode ("mov", "c,acc.7");
7065 AccAXRrl1 (x); // s->a:x
7067 emitcode ("mov", "c,acc.7");
7068 AccAXRrl1 (x); // s->a:x
7073 case 5: // AAAAABBB:CCCCCDDD = a:x
7075 tlbl = newiTempLabel (NULL);
7076 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7078 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7080 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7082 emitcode ("anl", "a,#0x%02x",
7083 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7085 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7087 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7089 emitcode ("anl", "a,#0x%02x",
7090 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7092 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7094 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7096 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7098 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7099 emitcode ("orl", "a,#0x%02x",
7100 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7102 emitcode ("", "%05d$:", tlbl->key + 100);
7103 break; // SSSSAAAA:BBBCCCCC
7105 case 6: // AABBBBBB:CCDDDDDD
7107 tlbl = newiTempLabel (NULL);
7108 emitcode ("mov", "c,acc.7");
7109 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7111 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7113 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7115 emitcode ("anl", "a,#0x%02x",
7116 SRMask[shCount]); // 000000AA:BBBBBBCC
7118 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7119 emitcode ("orl", "a,#0x%02x",
7120 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7122 emitcode ("", "%05d$:", tlbl->key + 100);
7124 case 7: // ABBBBBBB:CDDDDDDD
7126 tlbl = newiTempLabel (NULL);
7127 emitcode ("mov", "c,acc.7"); // c = A
7129 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7131 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7133 emitcode ("anl", "a,#0x%02x",
7134 SRMask[shCount]); // 0000000A:BBBBBBBC
7136 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7137 emitcode ("orl", "a,#0x%02x",
7138 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7140 emitcode ("", "%05d$:", tlbl->key + 100);
7148 #ifdef BETTER_LITERAL_SHIFT
7150 _loadLeftIntoAx(char **lsb,
7156 // Get the initial value from left into a pair of registers.
7157 // MSB must be in A, LSB can be any register.
7159 // If the result is held in registers, it is an optimization
7160 // if the LSB can be held in the register which will hold the,
7161 // result LSB since this saves us from having to copy it into
7162 // the result following AccAXLsh.
7164 // If the result is addressed indirectly, this is not a gain.
7165 if (AOP_NEEDSACC(result))
7169 _startLazyDPSEvaluation();
7170 if (AOP_TYPE(left) == AOP_DPTR2)
7173 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7174 // get LSB in DP2_RESULT_REG.
7175 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7176 assert(!strcmp(leftByte, DP2_RESULT_REG));
7180 // get LSB into DP2_RESULT_REG
7181 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7182 if (strcmp(leftByte, DP2_RESULT_REG))
7185 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7188 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7189 assert(strcmp(leftByte, DP2_RESULT_REG));
7192 _endLazyDPSEvaluation();
7193 *lsb = DP2_RESULT_REG;
7197 if (sameRegs (AOP (result), AOP (left)) &&
7198 ((offl + MSB16) == offr))
7200 /* don't crash result[offr] */
7201 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7202 emitcode ("xch", "a,%s",
7203 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7207 movLeft2Result (left, offl, result, offr, 0);
7208 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7210 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7211 assert(strcmp(*lsb,"a"));
7216 _storeAxResults(char *lsb,
7220 _startLazyDPSEvaluation();
7221 if (AOP_NEEDSACC(result))
7223 /* We have to explicitly update the result LSB.
7225 emitcode("xch","a,%s", lsb);
7226 aopPut(AOP(result), "a", offr);
7227 emitcode("mov","a,%s", lsb);
7229 if (getDataSize (result) > 1)
7231 aopPut (AOP (result), "a", offr + MSB16);
7233 _endLazyDPSEvaluation();
7236 /*-----------------------------------------------------------------*/
7237 /* shiftL2Left2Result - shift left two bytes from left to result */
7238 /*-----------------------------------------------------------------*/
7240 shiftL2Left2Result (operand * left, int offl,
7241 operand * result, int offr, int shCount)
7245 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7247 AccAXLsh (lsb, shCount);
7249 _storeAxResults(lsb, result, offr);
7253 #ifdef BETTER_LITERAL_SHIFT
7254 /*-----------------------------------------------------------------*/
7255 /* shiftR2Left2Result - shift right two bytes from left to result */
7256 /*-----------------------------------------------------------------*/
7258 shiftR2Left2Result (operand * left, int offl,
7259 operand * result, int offr,
7260 int shCount, int sign)
7264 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7266 /* a:x >> shCount (x = lsb(result)) */
7269 AccAXRshS(lsb, shCount);
7273 AccAXRsh(lsb, shCount);
7276 _storeAxResults(lsb, result, offr);
7282 /*-----------------------------------------------------------------*/
7283 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7284 /*-----------------------------------------------------------------*/
7286 shiftLLeftOrResult (operand * left, int offl,
7287 operand * result, int offr, int shCount)
7289 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7290 /* shift left accumulator */
7292 /* or with result */
7293 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7294 /* back to result */
7295 aopPut (AOP (result), "a", offr);
7301 /*-----------------------------------------------------------------*/
7302 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7303 /*-----------------------------------------------------------------*/
7305 shiftRLeftOrResult (operand * left, int offl,
7306 operand * result, int offr, int shCount)
7308 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7309 /* shift right accumulator */
7311 /* or with result */
7312 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7313 /* back to result */
7314 aopPut (AOP (result), "a", offr);
7318 #ifdef BETTER_LITERAL_SHIFT
7319 /*-----------------------------------------------------------------*/
7320 /* genlshOne - left shift a one byte quantity by known count */
7321 /*-----------------------------------------------------------------*/
7323 genlshOne (operand * result, operand * left, int shCount)
7325 D (emitcode (";", "genlshOne "););
7326 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7330 #ifdef BETTER_LITERAL_SHIFT
7331 /*-----------------------------------------------------------------*/
7332 /* genlshTwo - left shift two bytes by known amount != 0 */
7333 /*-----------------------------------------------------------------*/
7335 genlshTwo (operand * result, operand * left, int shCount)
7339 D (emitcode (";", "genlshTwo "););
7341 size = getDataSize (result);
7343 /* if shCount >= 8 */
7348 _startLazyDPSEvaluation();
7354 _endLazyDPSEvaluation();
7355 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7356 aopPut (AOP (result), zero, LSB);
7360 movLeft2Result (left, LSB, result, MSB16, 0);
7361 aopPut (AOP (result), zero, LSB);
7362 _endLazyDPSEvaluation();
7367 aopPut (AOP (result), zero, LSB);
7368 _endLazyDPSEvaluation();
7372 /* 1 <= shCount <= 7 */
7377 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7381 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7389 /*-----------------------------------------------------------------*/
7390 /* shiftLLong - shift left one long from left to result */
7391 /* offl = LSB or MSB16 */
7392 /*-----------------------------------------------------------------*/
7394 shiftLLong (operand * left, operand * result, int offr)
7397 int size = AOP_SIZE (result);
7399 if (size >= LSB + offr)
7401 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7403 emitcode ("add", "a,acc");
7404 if (sameRegs (AOP (left), AOP (result)) &&
7405 size >= MSB16 + offr && offr != LSB)
7406 emitcode ("xch", "a,%s",
7407 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7409 aopPut (AOP (result), "a", LSB + offr);
7412 if (size >= MSB16 + offr)
7414 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7416 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7419 emitcode ("rlc", "a");
7420 if (sameRegs (AOP (left), AOP (result)) &&
7421 size >= MSB24 + offr && offr != LSB)
7422 emitcode ("xch", "a,%s",
7423 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7425 aopPut (AOP (result), "a", MSB16 + offr);
7428 if (size >= MSB24 + offr)
7430 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7432 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7435 emitcode ("rlc", "a");
7436 if (sameRegs (AOP (left), AOP (result)) &&
7437 size >= MSB32 + offr && offr != LSB)
7438 emitcode ("xch", "a,%s",
7439 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7441 aopPut (AOP (result), "a", MSB24 + offr);
7444 if (size > MSB32 + offr)
7446 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7448 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7451 emitcode ("rlc", "a");
7452 aopPut (AOP (result), "a", MSB32 + offr);
7455 aopPut (AOP (result), zero, LSB);
7461 /*-----------------------------------------------------------------*/
7462 /* genlshFour - shift four byte by a known amount != 0 */
7463 /*-----------------------------------------------------------------*/
7465 genlshFour (operand * result, operand * left, int shCount)
7469 D (emitcode (";", "genlshFour ");
7472 size = AOP_SIZE (result);
7474 /* if shifting more that 3 bytes */
7479 /* lowest order of left goes to the highest
7480 order of the destination */
7481 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7483 movLeft2Result (left, LSB, result, MSB32, 0);
7484 aopPut (AOP (result), zero, LSB);
7485 aopPut (AOP (result), zero, MSB16);
7486 aopPut (AOP (result), zero, MSB24);
7490 /* more than two bytes */
7491 else if (shCount >= 16)
7493 /* lower order two bytes goes to higher order two bytes */
7495 /* if some more remaining */
7497 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7500 movLeft2Result (left, MSB16, result, MSB32, 0);
7501 movLeft2Result (left, LSB, result, MSB24, 0);
7503 aopPut (AOP (result), zero, MSB16);
7504 aopPut (AOP (result), zero, LSB);
7508 /* if more than 1 byte */
7509 else if (shCount >= 8)
7511 /* lower order three bytes goes to higher order three bytes */
7516 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7518 movLeft2Result (left, LSB, result, MSB16, 0);
7524 movLeft2Result (left, MSB24, result, MSB32, 0);
7525 movLeft2Result (left, MSB16, result, MSB24, 0);
7526 movLeft2Result (left, LSB, result, MSB16, 0);
7527 aopPut (AOP (result), zero, LSB);
7529 else if (shCount == 1)
7530 shiftLLong (left, result, MSB16);
7533 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7534 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7535 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7536 aopPut (AOP (result), zero, LSB);
7541 /* 1 <= shCount <= 7 */
7542 else if (shCount <= 2)
7544 shiftLLong (left, result, LSB);
7546 shiftLLong (result, result, LSB);
7548 /* 3 <= shCount <= 7, optimize */
7551 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7552 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7553 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7558 #ifdef BETTER_LITERAL_SHIFT
7559 /*-----------------------------------------------------------------*/
7560 /* genLeftShiftLiteral - left shifting by known count */
7561 /*-----------------------------------------------------------------*/
7563 genLeftShiftLiteral (operand * left,
7568 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7571 size = getSize (operandType (result));
7573 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7575 /* We only handle certain easy cases so far. */
7577 && (shCount < (size * 8))
7581 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7585 freeAsmop (right, NULL, ic, TRUE);
7587 aopOp(left, ic, FALSE, FALSE);
7588 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7591 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7593 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7594 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7596 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7599 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7601 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7602 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7604 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7610 emitcode ("; shift left ", "result %d, left %d", size,
7614 /* I suppose that the left size >= result size */
7617 _startLazyDPSEvaluation();
7620 movLeft2Result (left, size, result, size, 0);
7622 _endLazyDPSEvaluation();
7624 else if (shCount >= (size * 8))
7626 _startLazyDPSEvaluation();
7629 aopPut (AOP (result), zero, size);
7631 _endLazyDPSEvaluation();
7638 genlshOne (result, left, shCount);
7642 genlshTwo (result, left, shCount);
7646 genlshFour (result, left, shCount);
7650 fprintf(stderr, "*** ack! mystery literal shift!\n");
7654 freeAsmop (left, NULL, ic, TRUE);
7655 freeAsmop (result, NULL, ic, TRUE);
7660 /*-----------------------------------------------------------------*/
7661 /* genLeftShift - generates code for left shifting */
7662 /*-----------------------------------------------------------------*/
7664 genLeftShift (iCode * ic)
7666 operand *left, *right, *result;
7669 symbol *tlbl, *tlbl1;
7671 D (emitcode (";", "genLeftShift "););
7673 right = IC_RIGHT (ic);
7674 left = IC_LEFT (ic);
7675 result = IC_RESULT (ic);
7677 aopOp (right, ic, FALSE, FALSE);
7680 #ifdef BETTER_LITERAL_SHIFT
7681 /* if the shift count is known then do it
7682 as efficiently as possible */
7683 if (AOP_TYPE (right) == AOP_LIT)
7685 if (genLeftShiftLiteral (left, right, result, ic))
7692 /* shift count is unknown then we have to form
7693 a loop get the loop count in B : Note: we take
7694 only the lower order byte since shifting
7695 more that 32 bits make no sense anyway, ( the
7696 largest size of an object can be only 32 bits ) */
7698 if (AOP_TYPE (right) == AOP_LIT)
7700 /* Really should be handled by genLeftShiftLiteral,
7701 * but since I'm too lazy to fix that today, at least we can make
7702 * some small improvement.
7704 emitcode("mov", "b,#0x%02x",
7705 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7709 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7710 emitcode ("inc", "b");
7712 freeAsmop (right, NULL, ic, TRUE);
7713 aopOp (left, ic, FALSE, FALSE);
7714 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7716 /* now move the left to the result if they are not the
7718 if (!sameRegs (AOP (left), AOP (result)) &&
7719 AOP_SIZE (result) > 1)
7722 size = AOP_SIZE (result);
7724 _startLazyDPSEvaluation ();
7727 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7728 if (*l == '@' && (IS_AOP_PREG (result)))
7731 emitcode ("mov", "a,%s", l);
7732 aopPut (AOP (result), "a", offset);
7735 aopPut (AOP (result), l, offset);
7738 _endLazyDPSEvaluation ();
7741 tlbl = newiTempLabel (NULL);
7742 size = AOP_SIZE (result);
7744 tlbl1 = newiTempLabel (NULL);
7746 /* if it is only one byte then */
7749 symbol *tlbl1 = newiTempLabel (NULL);
7751 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7753 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7754 emitcode ("", "%05d$:", tlbl->key + 100);
7755 emitcode ("add", "a,acc");
7756 emitcode ("", "%05d$:", tlbl1->key + 100);
7757 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7758 aopPut (AOP (result), "a", 0);
7762 reAdjustPreg (AOP (result));
7764 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7765 emitcode ("", "%05d$:", tlbl->key + 100);
7766 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7768 emitcode ("add", "a,acc");
7769 aopPut (AOP (result), "a", offset++);
7770 _startLazyDPSEvaluation ();
7773 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7775 emitcode ("rlc", "a");
7776 aopPut (AOP (result), "a", offset++);
7778 _endLazyDPSEvaluation ();
7779 reAdjustPreg (AOP (result));
7781 emitcode ("", "%05d$:", tlbl1->key + 100);
7782 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7784 freeAsmop (left, NULL, ic, TRUE);
7785 freeAsmop (result, NULL, ic, TRUE);
7788 #ifdef BETTER_LITERAL_SHIFT
7789 /*-----------------------------------------------------------------*/
7790 /* genrshOne - right shift a one byte quantity by known count */
7791 /*-----------------------------------------------------------------*/
7793 genrshOne (operand * result, operand * left,
7794 int shCount, int sign)
7796 D (emitcode (";", "genrshOne"););
7797 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7801 #ifdef BETTER_LITERAL_SHIFT
7802 /*-----------------------------------------------------------------*/
7803 /* genrshTwo - right shift two bytes by known amount != 0 */
7804 /*-----------------------------------------------------------------*/
7806 genrshTwo (operand * result, operand * left,
7807 int shCount, int sign)
7809 D (emitcode (";", "genrshTwo"););
7811 /* if shCount >= 8 */
7815 _startLazyDPSEvaluation();
7818 shiftR1Left2Result (left, MSB16, result, LSB,
7823 movLeft2Result (left, MSB16, result, LSB, sign);
7825 addSign (result, MSB16, sign);
7826 _endLazyDPSEvaluation();
7829 /* 1 <= shCount <= 7 */
7832 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7839 /*-----------------------------------------------------------------*/
7840 /* shiftRLong - shift right one long from left to result */
7841 /* offl = LSB or MSB16 */
7842 /*-----------------------------------------------------------------*/
7844 shiftRLong (operand * left, int offl,
7845 operand * result, int sign)
7847 int isSameRegs=sameRegs(AOP(left),AOP(result));
7849 if (isSameRegs && offl>1) {
7850 // we are in big trouble, but this shouldn't happen
7851 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7854 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7859 emitcode ("rlc", "a");
7860 emitcode ("subb", "a,acc");
7861 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7863 aopPut (AOP(result), zero, MSB32);
7868 emitcode ("clr", "c");
7870 emitcode ("mov", "c,acc.7");
7873 emitcode ("rrc", "a");
7875 if (isSameRegs && offl==MSB16) {
7876 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7878 aopPut (AOP (result), "a", MSB32);
7879 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7882 emitcode ("rrc", "a");
7883 if (isSameRegs && offl==1) {
7884 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7886 aopPut (AOP (result), "a", MSB24);
7887 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7889 emitcode ("rrc", "a");
7890 aopPut (AOP (result), "a", MSB16 - offl);
7894 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7895 emitcode ("rrc", "a");
7896 aopPut (AOP (result), "a", LSB);
7903 /*-----------------------------------------------------------------*/
7904 /* genrshFour - shift four byte by a known amount != 0 */
7905 /*-----------------------------------------------------------------*/
7907 genrshFour (operand * result, operand * left,
7908 int shCount, int sign)
7910 D (emitcode (";", "genrshFour");
7913 /* if shifting more that 3 bytes */
7918 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7920 movLeft2Result (left, MSB32, result, LSB, sign);
7921 addSign (result, MSB16, sign);
7923 else if (shCount >= 16)
7927 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7930 movLeft2Result (left, MSB24, result, LSB, 0);
7931 movLeft2Result (left, MSB32, result, MSB16, sign);
7933 addSign (result, MSB24, sign);
7935 else if (shCount >= 8)
7939 shiftRLong (left, MSB16, result, sign);
7940 else if (shCount == 0)
7942 movLeft2Result (left, MSB16, result, LSB, 0);
7943 movLeft2Result (left, MSB24, result, MSB16, 0);
7944 movLeft2Result (left, MSB32, result, MSB24, sign);
7945 addSign (result, MSB32, sign);
7949 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7950 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7951 /* the last shift is signed */
7952 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7953 addSign (result, MSB32, sign);
7957 { /* 1 <= shCount <= 7 */
7960 shiftRLong (left, LSB, result, sign);
7962 shiftRLong (result, LSB, result, sign);
7966 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7967 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7968 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7974 #ifdef BETTER_LITERAL_SHIFT
7975 /*-----------------------------------------------------------------*/
7976 /* genRightShiftLiteral - right shifting by known count */
7977 /*-----------------------------------------------------------------*/
7979 genRightShiftLiteral (operand * left,
7985 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7988 size = getSize (operandType (result));
7990 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
7992 /* We only handle certain easy cases so far. */
7994 && (shCount < (size * 8))
7998 D(emitcode (";", "genRightShiftLiteral wimping out"););
8002 freeAsmop (right, NULL, ic, TRUE);
8004 aopOp (left, ic, FALSE, FALSE);
8005 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8008 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8012 /* test the LEFT size !!! */
8014 /* I suppose that the left size >= result size */
8017 size = getDataSize (result);
8018 _startLazyDPSEvaluation();
8021 movLeft2Result (left, size, result, size, 0);
8023 _endLazyDPSEvaluation();
8025 else if (shCount >= (size * 8))
8029 /* get sign in acc.7 */
8030 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8032 addSign (result, LSB, sign);
8039 genrshOne (result, left, shCount, sign);
8043 genrshTwo (result, left, shCount, sign);
8047 genrshFour (result, left, shCount, sign);
8054 freeAsmop (left, NULL, ic, TRUE);
8055 freeAsmop (result, NULL, ic, TRUE);
8061 /*-----------------------------------------------------------------*/
8062 /* genSignedRightShift - right shift of signed number */
8063 /*-----------------------------------------------------------------*/
8065 genSignedRightShift (iCode * ic)
8067 operand *right, *left, *result;
8070 symbol *tlbl, *tlbl1;
8072 D (emitcode (";", "genSignedRightShift "););
8074 /* we do it the hard way put the shift count in b
8075 and loop thru preserving the sign */
8077 right = IC_RIGHT (ic);
8078 left = IC_LEFT (ic);
8079 result = IC_RESULT (ic);
8081 aopOp (right, ic, FALSE, FALSE);
8083 #ifdef BETTER_LITERAL_SHIFT
8084 if (AOP_TYPE (right) == AOP_LIT)
8086 if (genRightShiftLiteral (left, right, result, ic, 1))
8092 /* shift count is unknown then we have to form
8093 a loop get the loop count in B : Note: we take
8094 only the lower order byte since shifting
8095 more that 32 bits make no sense anyway, ( the
8096 largest size of an object can be only 32 bits ) */
8098 if (AOP_TYPE (right) == AOP_LIT)
8100 /* Really should be handled by genRightShiftLiteral,
8101 * but since I'm too lazy to fix that today, at least we can make
8102 * some small improvement.
8104 emitcode("mov", "b,#0x%02x",
8105 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8109 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8110 emitcode ("inc", "b");
8112 freeAsmop (right, NULL, ic, TRUE);
8113 aopOp (left, ic, FALSE, FALSE);
8114 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8116 /* now move the left to the result if they are not the
8118 if (!sameRegs (AOP (left), AOP (result)) &&
8119 AOP_SIZE (result) > 1)
8122 size = AOP_SIZE (result);
8124 _startLazyDPSEvaluation ();
8127 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8128 if (*l == '@' && IS_AOP_PREG (result))
8131 emitcode ("mov", "a,%s", l);
8132 aopPut (AOP (result), "a", offset);
8135 aopPut (AOP (result), l, offset);
8138 _endLazyDPSEvaluation ();
8141 /* mov the highest order bit to OVR */
8142 tlbl = newiTempLabel (NULL);
8143 tlbl1 = newiTempLabel (NULL);
8145 size = AOP_SIZE (result);
8147 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8148 emitcode ("rlc", "a");
8149 emitcode ("mov", "ov,c");
8150 /* if it is only one byte then */
8153 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8155 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8156 emitcode ("", "%05d$:", tlbl->key + 100);
8157 emitcode ("mov", "c,ov");
8158 emitcode ("rrc", "a");
8159 emitcode ("", "%05d$:", tlbl1->key + 100);
8160 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8161 aopPut (AOP (result), "a", 0);
8165 reAdjustPreg (AOP (result));
8166 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8167 emitcode ("", "%05d$:", tlbl->key + 100);
8168 emitcode ("mov", "c,ov");
8169 _startLazyDPSEvaluation ();
8172 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8174 emitcode ("rrc", "a");
8175 aopPut (AOP (result), "a", offset--);
8177 _endLazyDPSEvaluation ();
8178 reAdjustPreg (AOP (result));
8179 emitcode ("", "%05d$:", tlbl1->key + 100);
8180 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8183 freeAsmop (left, NULL, ic, TRUE);
8184 freeAsmop (result, NULL, ic, TRUE);
8187 /*-----------------------------------------------------------------*/
8188 /* genRightShift - generate code for right shifting */
8189 /*-----------------------------------------------------------------*/
8191 genRightShift (iCode * ic)
8193 operand *right, *left, *result;
8197 symbol *tlbl, *tlbl1;
8199 D (emitcode (";", "genRightShift "););
8201 /* if signed then we do it the hard way preserve the
8202 sign bit moving it inwards */
8203 retype = getSpec (operandType (IC_RESULT (ic)));
8205 if (!SPEC_USIGN (retype))
8207 genSignedRightShift (ic);
8211 /* signed & unsigned types are treated the same : i.e. the
8212 signed is NOT propagated inwards : quoting from the
8213 ANSI - standard : "for E1 >> E2, is equivalent to division
8214 by 2**E2 if unsigned or if it has a non-negative value,
8215 otherwise the result is implementation defined ", MY definition
8216 is that the sign does not get propagated */
8218 right = IC_RIGHT (ic);
8219 left = IC_LEFT (ic);
8220 result = IC_RESULT (ic);
8222 aopOp (right, ic, FALSE, FALSE);
8224 #ifdef BETTER_LITERAL_SHIFT
8225 /* if the shift count is known then do it
8226 as efficiently as possible */
8227 if (AOP_TYPE (right) == AOP_LIT)
8229 if (genRightShiftLiteral (left, right, result, ic, 0))
8236 /* shift count is unknown then we have to form
8237 a loop get the loop count in B : Note: we take
8238 only the lower order byte since shifting
8239 more that 32 bits make no sense anyway, ( the
8240 largest size of an object can be only 32 bits ) */
8242 if (AOP_TYPE (right) == AOP_LIT)
8244 /* Really should be handled by genRightShiftLiteral,
8245 * but since I'm too lazy to fix that today, at least we can make
8246 * some small improvement.
8248 emitcode("mov", "b,#0x%02x",
8249 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8253 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8254 emitcode ("inc", "b");
8256 freeAsmop (right, NULL, ic, TRUE);
8257 aopOp (left, ic, FALSE, FALSE);
8258 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8260 /* now move the left to the result if they are not the
8262 if (!sameRegs (AOP (left), AOP (result)) &&
8263 AOP_SIZE (result) > 1)
8266 size = AOP_SIZE (result);
8268 _startLazyDPSEvaluation ();
8271 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8272 if (*l == '@' && IS_AOP_PREG (result))
8275 emitcode ("mov", "a,%s", l);
8276 aopPut (AOP (result), "a", offset);
8279 aopPut (AOP (result), l, offset);
8282 _endLazyDPSEvaluation ();
8285 tlbl = newiTempLabel (NULL);
8286 tlbl1 = newiTempLabel (NULL);
8287 size = AOP_SIZE (result);
8290 /* if it is only one byte then */
8293 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8295 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8296 emitcode ("", "%05d$:", tlbl->key + 100);
8298 emitcode ("rrc", "a");
8299 emitcode ("", "%05d$:", tlbl1->key + 100);
8300 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8301 aopPut (AOP (result), "a", 0);
8305 reAdjustPreg (AOP (result));
8306 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8307 emitcode ("", "%05d$:", tlbl->key + 100);
8309 _startLazyDPSEvaluation ();
8312 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8314 emitcode ("rrc", "a");
8315 aopPut (AOP (result), "a", offset--);
8317 _endLazyDPSEvaluation ();
8318 reAdjustPreg (AOP (result));
8320 emitcode ("", "%05d$:", tlbl1->key + 100);
8321 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8324 freeAsmop (left, NULL, ic, TRUE);
8325 freeAsmop (result, NULL, ic, TRUE);
8328 /*-----------------------------------------------------------------*/
8329 /* genUnpackBits - generates code for unpacking bits */
8330 /*-----------------------------------------------------------------*/
8332 genUnpackBits (operand * result, char *rname, int ptype)
8339 D (emitcode (";", "genUnpackBits ");
8342 etype = getSpec (operandType (result));
8344 /* read the first byte */
8350 emitcode ("mov", "a,@%s", rname);
8354 emitcode ("movx", "a,@%s", rname);
8358 emitcode ("movx", "a,@dptr");
8362 emitcode ("clr", "a");
8363 emitcode ("movc", "a,@a+dptr");
8367 emitcode ("lcall", "__gptrget");
8371 /* if we have bitdisplacement then it fits */
8372 /* into this byte completely or if length is */
8373 /* less than a byte */
8374 if ((shCnt = SPEC_BSTR (etype)) ||
8375 (SPEC_BLEN (etype) <= 8))
8378 /* shift right acc */
8381 emitcode ("anl", "a,#0x%02x",
8382 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8383 aopPut (AOP (result), "a", offset);
8387 /* bit field did not fit in a byte */
8388 rlen = SPEC_BLEN (etype) - 8;
8389 aopPut (AOP (result), "a", offset++);
8398 emitcode ("inc", "%s", rname);
8399 emitcode ("mov", "a,@%s", rname);
8403 emitcode ("inc", "%s", rname);
8404 emitcode ("movx", "a,@%s", rname);
8408 emitcode ("inc", "dptr");
8409 emitcode ("movx", "a,@dptr");
8413 emitcode ("clr", "a");
8414 emitcode ("inc", "dptr");
8415 emitcode ("movc", "a,@a+dptr");
8419 emitcode ("inc", "dptr");
8420 emitcode ("lcall", "__gptrget");
8425 /* if we are done */
8429 aopPut (AOP (result), "a", offset++);
8435 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
8436 aopPut (AOP (result), "a", offset);
8443 /*-----------------------------------------------------------------*/
8444 /* genDataPointerGet - generates code when ptr offset is known */
8445 /*-----------------------------------------------------------------*/
8447 genDataPointerGet (operand * left,
8453 int size, offset = 0;
8454 aopOp (result, ic, TRUE, FALSE);
8456 /* get the string representation of the name */
8457 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8458 size = AOP_SIZE (result);
8459 _startLazyDPSEvaluation ();
8463 sprintf (buffer, "(%s + %d)", l + 1, offset);
8465 sprintf (buffer, "%s", l + 1);
8466 aopPut (AOP (result), buffer, offset++);
8468 _endLazyDPSEvaluation ();
8470 freeAsmop (left, NULL, ic, TRUE);
8471 freeAsmop (result, NULL, ic, TRUE);
8474 /*-----------------------------------------------------------------*/
8475 /* genNearPointerGet - emitcode for near pointer fetch */
8476 /*-----------------------------------------------------------------*/
8478 genNearPointerGet (operand * left,
8485 sym_link *rtype, *retype, *letype;
8486 sym_link *ltype = operandType (left);
8489 rtype = operandType (result);
8490 retype = getSpec (rtype);
8491 letype = getSpec (ltype);
8493 aopOp (left, ic, FALSE, FALSE);
8495 /* if left is rematerialisable and
8496 result is not bit variable type and
8497 the left is pointer to data space i.e
8498 lower 128 bytes of space */
8499 if (AOP_TYPE (left) == AOP_IMMD &&
8500 !IS_BITVAR (retype) &&
8501 !IS_BITVAR (letype) &&
8502 DCL_TYPE (ltype) == POINTER)
8504 genDataPointerGet (left, result, ic);
8508 /* if the value is already in a pointer register
8509 then don't need anything more */
8510 if (!AOP_INPREG (AOP (left)))
8512 /* otherwise get a free pointer register */
8514 preg = getFreePtr (ic, &aop, FALSE);
8515 emitcode ("mov", "%s,%s",
8517 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8521 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8523 freeAsmop (left, NULL, ic, TRUE);
8524 aopOp (result, ic, FALSE, FALSE);
8526 /* if bitfield then unpack the bits */
8527 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8528 genUnpackBits (result, rname, POINTER);
8531 /* we have can just get the values */
8532 int size = AOP_SIZE (result);
8537 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8540 emitcode ("mov", "a,@%s", rname);
8541 aopPut (AOP (result), "a", offset);
8545 sprintf (buffer, "@%s", rname);
8546 aopPut (AOP (result), buffer, offset);
8550 emitcode ("inc", "%s", rname);
8554 /* now some housekeeping stuff */
8557 /* we had to allocate for this iCode */
8558 freeAsmop (NULL, aop, ic, TRUE);
8562 /* we did not allocate which means left
8563 already in a pointer register, then
8564 if size > 0 && this could be used again
8565 we have to point it back to where it
8567 if (AOP_SIZE (result) > 1 &&
8568 !OP_SYMBOL (left)->remat &&
8569 (OP_SYMBOL (left)->liveTo > ic->seq ||
8572 int size = AOP_SIZE (result) - 1;
8574 emitcode ("dec", "%s", rname);
8579 freeAsmop (result, NULL, ic, TRUE);
8583 /*-----------------------------------------------------------------*/
8584 /* genPagedPointerGet - emitcode for paged pointer fetch */
8585 /*-----------------------------------------------------------------*/
8587 genPagedPointerGet (operand * left,
8594 sym_link *rtype, *retype, *letype;
8596 rtype = operandType (result);
8597 retype = getSpec (rtype);
8598 letype = getSpec (operandType (left));
8599 aopOp (left, ic, FALSE, FALSE);
8601 /* if the value is already in a pointer register
8602 then don't need anything more */
8603 if (!AOP_INPREG (AOP (left)))
8605 /* otherwise get a free pointer register */
8607 preg = getFreePtr (ic, &aop, FALSE);
8608 emitcode ("mov", "%s,%s",
8610 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8614 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8616 freeAsmop (left, NULL, ic, TRUE);
8617 aopOp (result, ic, FALSE, FALSE);
8619 /* if bitfield then unpack the bits */
8620 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8621 genUnpackBits (result, rname, PPOINTER);
8624 /* we have can just get the values */
8625 int size = AOP_SIZE (result);
8631 emitcode ("movx", "a,@%s", rname);
8632 aopPut (AOP (result), "a", offset);
8637 emitcode ("inc", "%s", rname);
8641 /* now some housekeeping stuff */
8644 /* we had to allocate for this iCode */
8645 freeAsmop (NULL, aop, ic, TRUE);
8649 /* we did not allocate which means left
8650 already in a pointer register, then
8651 if size > 0 && this could be used again
8652 we have to point it back to where it
8654 if (AOP_SIZE (result) > 1 &&
8655 !OP_SYMBOL (left)->remat &&
8656 (OP_SYMBOL (left)->liveTo > ic->seq ||
8659 int size = AOP_SIZE (result) - 1;
8661 emitcode ("dec", "%s", rname);
8666 freeAsmop (result, NULL, ic, TRUE);
8671 /*-----------------------------------------------------------------*/
8672 /* genFarPointerGet - gget value from far space */
8673 /*-----------------------------------------------------------------*/
8675 genFarPointerGet (operand * left,
8676 operand * result, iCode * ic)
8679 sym_link *retype = getSpec (operandType (result));
8680 sym_link *letype = getSpec (operandType (left));
8681 D (emitcode (";", "genFarPointerGet");
8684 aopOp (left, ic, FALSE, FALSE);
8686 /* if the operand is already in dptr
8687 then we do nothing else we move the value to dptr */
8688 if (AOP_TYPE (left) != AOP_STR)
8690 /* if this is remateriazable */
8691 if (AOP_TYPE (left) == AOP_IMMD)
8693 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8697 /* we need to get it byte by byte */
8698 _startLazyDPSEvaluation ();
8699 if (AOP_TYPE (left) != AOP_DPTR)
8701 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8702 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8703 if (options.model == MODEL_FLAT24)
8704 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8708 /* We need to generate a load to DPTR indirect through DPTR. */
8709 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8711 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8712 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8713 if (options.model == MODEL_FLAT24)
8714 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8715 emitcode ("pop", "dph");
8716 emitcode ("pop", "dpl");
8718 _endLazyDPSEvaluation ();
8721 /* so dptr know contains the address */
8722 freeAsmop (left, NULL, ic, TRUE);
8723 aopOp (result, ic, FALSE, TRUE);
8725 /* if bit then unpack */
8726 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8727 genUnpackBits (result, "dptr", FPOINTER);
8730 size = AOP_SIZE (result);
8733 _startLazyDPSEvaluation ();
8740 emitcode ("movx", "a,@dptr");
8742 emitcode ("inc", "dptr");
8744 aopPut (AOP (result), "a", offset++);
8746 _endLazyDPSEvaluation ();
8749 freeAsmop (result, NULL, ic, TRUE);
8752 /*-----------------------------------------------------------------*/
8753 /* emitcodePointerGet - gget value from code space */
8754 /*-----------------------------------------------------------------*/
8756 emitcodePointerGet (operand * left,
8757 operand * result, iCode * ic)
8760 sym_link *retype = getSpec (operandType (result));
8762 aopOp (left, ic, FALSE, FALSE);
8764 /* if the operand is already in dptr
8765 then we do nothing else we move the value to dptr */
8766 if (AOP_TYPE (left) != AOP_STR)
8768 /* if this is remateriazable */
8769 if (AOP_TYPE (left) == AOP_IMMD)
8771 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8774 { /* we need to get it byte by byte */
8775 _startLazyDPSEvaluation ();
8776 if (AOP_TYPE (left) != AOP_DPTR)
8778 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8779 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8780 if (options.model == MODEL_FLAT24)
8781 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8785 /* We need to generate a load to DPTR indirect through DPTR. */
8786 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8788 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8789 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8790 if (options.model == MODEL_FLAT24)
8791 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8792 emitcode ("pop", "dph");
8793 emitcode ("pop", "dpl");
8795 _endLazyDPSEvaluation ();
8798 /* so dptr know contains the address */
8799 freeAsmop (left, NULL, ic, TRUE);
8800 aopOp (result, ic, FALSE, TRUE);
8802 /* if bit then unpack */
8803 if (IS_BITVAR (retype))
8804 genUnpackBits (result, "dptr", CPOINTER);
8807 size = AOP_SIZE (result);
8810 _startLazyDPSEvaluation ();
8816 emitcode ("clr", "a");
8817 emitcode ("movc", "a,@a+dptr");
8819 emitcode ("inc", "dptr");
8820 aopPut (AOP (result), "a", offset++);
8822 _endLazyDPSEvaluation ();
8825 freeAsmop (result, NULL, ic, TRUE);
8828 /*-----------------------------------------------------------------*/
8829 /* genGenPointerGet - gget value from generic pointer space */
8830 /*-----------------------------------------------------------------*/
8832 genGenPointerGet (operand * left,
8833 operand * result, iCode * ic)
8836 sym_link *retype = getSpec (operandType (result));
8837 sym_link *letype = getSpec (operandType (left));
8839 D (emitcode (";", "genGenPointerGet "); );
8841 aopOp (left, ic, FALSE, TRUE);
8843 /* if the operand is already in dptr
8844 then we do nothing else we move the value to dptr */
8845 if (AOP_TYPE (left) != AOP_STR)
8847 /* if this is remateriazable */
8848 if (AOP_TYPE (left) == AOP_IMMD)
8850 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8851 emitcode ("mov", "b,#%d", pointerCode (retype));
8854 { /* we need to get it byte by byte */
8855 _startLazyDPSEvaluation ();
8856 if (AOP(left)->type==AOP_DPTR2) {
8858 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8861 emitcode ("mov", "dpl,%s", l);
8862 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8865 emitcode ("mov", "dph,%s", l);
8866 if (options.model == MODEL_FLAT24) {
8867 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8870 emitcode ("mov", "dpx,%s", l);
8871 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8873 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8876 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8877 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8878 if (options.model == MODEL_FLAT24) {
8879 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8880 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8882 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8885 _endLazyDPSEvaluation ();
8888 /* so dptr know contains the address */
8889 freeAsmop (left, NULL, ic, TRUE);
8890 aopOp (result, ic, FALSE, TRUE);
8892 /* if bit then unpack */
8893 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8894 genUnpackBits (result, "dptr", GPOINTER);
8897 size = AOP_SIZE (result);
8902 emitcode ("lcall", "__gptrget");
8903 aopPut (AOP (result), "a", offset++);
8905 emitcode ("inc", "dptr");
8909 freeAsmop (result, NULL, ic, TRUE);
8912 /*-----------------------------------------------------------------*/
8913 /* genPointerGet - generate code for pointer get */
8914 /*-----------------------------------------------------------------*/
8916 genPointerGet (iCode * ic)
8918 operand *left, *result;
8919 sym_link *type, *etype;
8922 D (emitcode (";", "genPointerGet ");
8925 left = IC_LEFT (ic);
8926 result = IC_RESULT (ic);
8928 /* depending on the type of pointer we need to
8929 move it to the correct pointer register */
8930 type = operandType (left);
8931 etype = getSpec (type);
8932 /* if left is of type of pointer then it is simple */
8933 if (IS_PTR (type) && !IS_FUNC (type->next))
8934 p_type = DCL_TYPE (type);
8937 /* we have to go by the storage class */
8938 p_type = PTR_TYPE (SPEC_OCLS (etype));
8941 /* now that we have the pointer type we assign
8942 the pointer values */
8948 genNearPointerGet (left, result, ic);
8952 genPagedPointerGet (left, result, ic);
8956 genFarPointerGet (left, result, ic);
8960 emitcodePointerGet (left, result, ic);
8964 genGenPointerGet (left, result, ic);
8970 /*-----------------------------------------------------------------*/
8971 /* genPackBits - generates code for packed bit storage */
8972 /*-----------------------------------------------------------------*/
8974 genPackBits (sym_link * etype,
8976 char *rname, int p_type)
8984 blen = SPEC_BLEN (etype);
8985 bstr = SPEC_BSTR (etype);
8987 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8990 /* if the bit lenth is less than or */
8991 /* it exactly fits a byte then */
8992 if (SPEC_BLEN (etype) <= 8)
8994 shCount = SPEC_BSTR (etype);
8996 /* shift left acc */
8999 if (SPEC_BLEN (etype) < 8)
9000 { /* if smaller than a byte */
9006 emitcode ("mov", "b,a");
9007 emitcode ("mov", "a,@%s", rname);
9011 emitcode ("mov", "b,a");
9012 emitcode ("movx", "a,@dptr");
9016 emitcode ("push", "b");
9017 emitcode ("push", "acc");
9018 emitcode ("lcall", "__gptrget");
9019 emitcode ("pop", "b");
9023 emitcode ("anl", "a,#0x%02x", (unsigned char)
9024 ((unsigned char) (0xFF << (blen + bstr)) |
9025 (unsigned char) (0xFF >> (8 - bstr))));
9026 emitcode ("orl", "a,b");
9027 if (p_type == GPOINTER)
9028 emitcode ("pop", "b");
9035 emitcode ("mov", "@%s,a", rname);
9039 emitcode ("movx", "@dptr,a");
9043 emitcode ("lcall", "__gptrput");
9048 if (SPEC_BLEN (etype) <= 8)
9051 emitcode ("inc", "%s", rname);
9052 rLen = SPEC_BLEN (etype);
9054 /* now generate for lengths greater than one byte */
9058 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9070 emitcode ("mov", "@%s,a", rname);
9073 emitcode ("mov", "@%s,%s", rname, l);
9078 emitcode ("movx", "@dptr,a");
9083 emitcode ("lcall", "__gptrput");
9086 emitcode ("inc", "%s", rname);
9091 /* last last was not complete */
9094 /* save the byte & read byte */
9098 emitcode ("mov", "b,a");
9099 emitcode ("mov", "a,@%s", rname);
9103 emitcode ("mov", "b,a");
9104 emitcode ("movx", "a,@dptr");
9108 emitcode ("push", "b");
9109 emitcode ("push", "acc");
9110 emitcode ("lcall", "__gptrget");
9111 emitcode ("pop", "b");
9115 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
9116 emitcode ("orl", "a,b");
9119 if (p_type == GPOINTER)
9120 emitcode ("pop", "b");
9126 emitcode ("mov", "@%s,a", rname);
9130 emitcode ("movx", "@dptr,a");
9134 emitcode ("lcall", "__gptrput");
9138 /*-----------------------------------------------------------------*/
9139 /* genDataPointerSet - remat pointer to data space */
9140 /*-----------------------------------------------------------------*/
9142 genDataPointerSet (operand * right,
9146 int size, offset = 0;
9147 char *l, buffer[256];
9149 aopOp (right, ic, FALSE, FALSE);
9151 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9152 size = AOP_SIZE (right);
9156 sprintf (buffer, "(%s + %d)", l + 1, offset);
9158 sprintf (buffer, "%s", l + 1);
9159 emitcode ("mov", "%s,%s", buffer,
9160 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9163 freeAsmop (right, NULL, ic, TRUE);
9164 freeAsmop (result, NULL, ic, TRUE);
9167 /*-----------------------------------------------------------------*/
9168 /* genNearPointerSet - emitcode for near pointer put */
9169 /*-----------------------------------------------------------------*/
9171 genNearPointerSet (operand * right,
9178 sym_link *retype, *letype;
9179 sym_link *ptype = operandType (result);
9181 retype = getSpec (operandType (right));
9182 letype = getSpec (ptype);
9184 aopOp (result, ic, FALSE, FALSE);
9186 /* if the result is rematerializable &
9187 in data space & not a bit variable */
9188 if (AOP_TYPE (result) == AOP_IMMD &&
9189 DCL_TYPE (ptype) == POINTER &&
9190 !IS_BITVAR (retype) &&
9191 !IS_BITVAR (letype))
9193 genDataPointerSet (right, result, ic);
9197 /* if the value is already in a pointer register
9198 then don't need anything more */
9199 if (!AOP_INPREG (AOP (result)))
9201 /* otherwise get a free pointer register */
9203 preg = getFreePtr (ic, &aop, FALSE);
9204 emitcode ("mov", "%s,%s",
9206 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9210 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9212 freeAsmop (result, NULL, ic, TRUE);
9213 aopOp (right, ic, FALSE, FALSE);
9215 /* if bitfield then unpack the bits */
9216 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9217 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9220 /* we have can just get the values */
9221 int size = AOP_SIZE (right);
9226 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9230 emitcode ("mov", "@%s,a", rname);
9233 emitcode ("mov", "@%s,%s", rname, l);
9235 emitcode ("inc", "%s", rname);
9240 /* now some housekeeping stuff */
9243 /* we had to allocate for this iCode */
9244 freeAsmop (NULL, aop, ic, TRUE);
9248 /* we did not allocate which means left
9249 already in a pointer register, then
9250 if size > 0 && this could be used again
9251 we have to point it back to where it
9253 if (AOP_SIZE (right) > 1 &&
9254 !OP_SYMBOL (result)->remat &&
9255 (OP_SYMBOL (result)->liveTo > ic->seq ||
9258 int size = AOP_SIZE (right) - 1;
9260 emitcode ("dec", "%s", rname);
9265 freeAsmop (right, NULL, ic, TRUE);
9270 /*-----------------------------------------------------------------*/
9271 /* genPagedPointerSet - emitcode for Paged pointer put */
9272 /*-----------------------------------------------------------------*/
9274 genPagedPointerSet (operand * right,
9281 sym_link *retype, *letype;
9283 retype = getSpec (operandType (right));
9284 letype = getSpec (operandType (result));
9286 aopOp (result, ic, FALSE, FALSE);
9288 /* if the value is already in a pointer register
9289 then don't need anything more */
9290 if (!AOP_INPREG (AOP (result)))
9292 /* otherwise get a free pointer register */
9294 preg = getFreePtr (ic, &aop, FALSE);
9295 emitcode ("mov", "%s,%s",
9297 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9301 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9303 freeAsmop (result, NULL, ic, TRUE);
9304 aopOp (right, ic, FALSE, FALSE);
9306 /* if bitfield then unpack the bits */
9307 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9308 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9311 /* we have can just get the values */
9312 int size = AOP_SIZE (right);
9317 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9320 emitcode ("movx", "@%s,a", rname);
9323 emitcode ("inc", "%s", rname);
9329 /* now some housekeeping stuff */
9332 /* we had to allocate for this iCode */
9333 freeAsmop (NULL, aop, ic, TRUE);
9337 /* we did not allocate which means left
9338 already in a pointer register, then
9339 if size > 0 && this could be used again
9340 we have to point it back to where it
9342 if (AOP_SIZE (right) > 1 &&
9343 !OP_SYMBOL (result)->remat &&
9344 (OP_SYMBOL (result)->liveTo > ic->seq ||
9347 int size = AOP_SIZE (right) - 1;
9349 emitcode ("dec", "%s", rname);
9354 freeAsmop (right, NULL, ic, TRUE);
9359 /*-----------------------------------------------------------------*/
9360 /* genFarPointerSet - set value from far space */
9361 /*-----------------------------------------------------------------*/
9363 genFarPointerSet (operand * right,
9364 operand * result, iCode * ic)
9367 sym_link *retype = getSpec (operandType (right));
9368 sym_link *letype = getSpec (operandType (result));
9370 aopOp (result, ic, FALSE, FALSE);
9372 /* if the operand is already in dptr
9373 then we do nothing else we move the value to dptr */
9374 if (AOP_TYPE (result) != AOP_STR)
9376 /* if this is remateriazable */
9377 if (AOP_TYPE (result) == AOP_IMMD)
9378 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9381 /* we need to get it byte by byte */
9382 _startLazyDPSEvaluation ();
9383 if (AOP_TYPE (result) != AOP_DPTR)
9385 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9386 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9387 if (options.model == MODEL_FLAT24)
9388 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9392 /* We need to generate a load to DPTR indirect through DPTR. */
9393 D (emitcode (";", "genFarPointerSet -- indirection special case.");
9395 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9396 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9397 if (options.model == MODEL_FLAT24)
9398 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9399 emitcode ("pop", "dph");
9400 emitcode ("pop", "dpl");
9402 _endLazyDPSEvaluation ();
9405 /* so dptr know contains the address */
9406 freeAsmop (result, NULL, ic, TRUE);
9407 aopOp (right, ic, FALSE, TRUE);
9409 /* if bit then unpack */
9410 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9411 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9414 size = AOP_SIZE (right);
9417 _startLazyDPSEvaluation ();
9420 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9426 emitcode ("movx", "@dptr,a");
9428 emitcode ("inc", "dptr");
9430 _endLazyDPSEvaluation ();
9433 freeAsmop (right, NULL, ic, TRUE);
9436 /*-----------------------------------------------------------------*/
9437 /* genGenPointerSet - set value from generic pointer space */
9438 /*-----------------------------------------------------------------*/
9440 genGenPointerSet (operand * right,
9441 operand * result, iCode * ic)
9444 sym_link *retype = getSpec (operandType (right));
9445 sym_link *letype = getSpec (operandType (result));
9447 aopOp (result, ic, FALSE, TRUE);
9449 /* if the operand is already in dptr
9450 then we do nothing else we move the value to dptr */
9451 if (AOP_TYPE (result) != AOP_STR)
9453 _startLazyDPSEvaluation ();
9454 /* if this is remateriazable */
9455 if (AOP_TYPE (result) == AOP_IMMD)
9457 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9458 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9461 { /* we need to get it byte by byte */
9462 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9463 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9464 if (options.model == MODEL_FLAT24) {
9465 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9466 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9468 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9471 _endLazyDPSEvaluation ();
9473 /* so dptr know contains the address */
9474 freeAsmop (result, NULL, ic, TRUE);
9475 aopOp (right, ic, FALSE, TRUE);
9477 /* if bit then unpack */
9478 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9479 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9482 size = AOP_SIZE (right);
9485 _startLazyDPSEvaluation ();
9488 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9494 emitcode ("lcall", "__gptrput");
9496 emitcode ("inc", "dptr");
9498 _endLazyDPSEvaluation ();
9501 freeAsmop (right, NULL, ic, TRUE);
9504 /*-----------------------------------------------------------------*/
9505 /* genPointerSet - stores the value into a pointer location */
9506 /*-----------------------------------------------------------------*/
9508 genPointerSet (iCode * ic)
9510 operand *right, *result;
9511 sym_link *type, *etype;
9514 D (emitcode (";", "genPointerSet ");
9517 right = IC_RIGHT (ic);
9518 result = IC_RESULT (ic);
9520 /* depending on the type of pointer we need to
9521 move it to the correct pointer register */
9522 type = operandType (result);
9523 etype = getSpec (type);
9524 /* if left is of type of pointer then it is simple */
9525 if (IS_PTR (type) && !IS_FUNC (type->next))
9527 p_type = DCL_TYPE (type);
9531 /* we have to go by the storage class */
9532 p_type = PTR_TYPE (SPEC_OCLS (etype));
9535 /* now that we have the pointer type we assign
9536 the pointer values */
9542 genNearPointerSet (right, result, ic);
9546 genPagedPointerSet (right, result, ic);
9550 genFarPointerSet (right, result, ic);
9554 genGenPointerSet (right, result, ic);
9560 /*-----------------------------------------------------------------*/
9561 /* genIfx - generate code for Ifx statement */
9562 /*-----------------------------------------------------------------*/
9564 genIfx (iCode * ic, iCode * popIc)
9566 operand *cond = IC_COND (ic);
9569 D (emitcode (";", "genIfx "););
9571 aopOp (cond, ic, FALSE, FALSE);
9573 /* get the value into acc */
9574 if (AOP_TYPE (cond) != AOP_CRY)
9578 /* the result is now in the accumulator */
9579 freeAsmop (cond, NULL, ic, TRUE);
9581 /* if there was something to be popped then do it */
9585 /* if the condition is a bit variable */
9586 if (isbit && IS_ITEMP (cond) &&
9588 genIfxJump (ic, SPIL_LOC (cond)->rname);
9589 else if (isbit && !IS_ITEMP (cond))
9590 genIfxJump (ic, OP_SYMBOL (cond)->rname);
9592 genIfxJump (ic, "a");
9597 /*-----------------------------------------------------------------*/
9598 /* genAddrOf - generates code for address of */
9599 /*-----------------------------------------------------------------*/
9601 genAddrOf (iCode * ic)
9603 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9606 D (emitcode (";", "genAddrOf ");
9609 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9611 /* if the operand is on the stack then we
9612 need to get the stack offset of this
9616 /* if it has an offset then we need to compute
9620 emitcode ("mov", "a,_bp");
9621 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9622 aopPut (AOP (IC_RESULT (ic)), "a", 0);
9626 /* we can just move _bp */
9627 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9629 /* fill the result with zero */
9630 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9633 if (options.stack10bit && size < (FPTRSIZE - 1))
9636 "*** warning: pointer to stack var truncated.\n");
9643 if (options.stack10bit && offset == 2)
9645 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
9649 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9656 /* object not on stack then we need the name */
9657 size = AOP_SIZE (IC_RESULT (ic));
9662 char s[SDCC_NAME_MAX];
9664 sprintf (s, "#(%s >> %d)",
9668 sprintf (s, "#%s", sym->rname);
9669 aopPut (AOP (IC_RESULT (ic)), s, offset++);
9673 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9677 /*-----------------------------------------------------------------*/
9678 /* genArrayInit - generates code for address of */
9679 /*-----------------------------------------------------------------*/
9681 genArrayInit (iCode * ic)
9685 int elementSize = 0, eIndex;
9686 unsigned val, lastVal;
9688 operand *left=IC_LEFT(ic);
9690 D (emitcode (";", "genArrayInit "););
9692 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
9694 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
9696 // Load immediate value into DPTR.
9697 emitcode("mov", "dptr, %s",
9698 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
9700 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
9703 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9704 "Unexpected operand to genArrayInit.\n");
9707 // a regression because of SDCCcse.c:1.52
9708 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9709 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9710 if (options.model == MODEL_FLAT24)
9711 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9715 type = operandType(IC_LEFT(ic));
9717 if (type && type->next)
9719 elementSize = getSize(type->next);
9723 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9724 "can't determine element size in genArrayInit.\n");
9728 iLoop = IC_ARRAYILIST(ic);
9733 bool firstpass = TRUE;
9735 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
9736 iLoop->count, (int)iLoop->literalValue, elementSize);
9742 symbol *tlbl = NULL;
9744 count = ix > 256 ? 256 : ix;
9748 tlbl = newiTempLabel (NULL);
9749 if (firstpass || (count & 0xff))
9751 emitcode("mov", "b, #0x%x", count & 0xff);
9754 emitcode ("", "%05d$:", tlbl->key + 100);
9759 for (eIndex = 0; eIndex < elementSize; eIndex++)
9761 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
9764 emitcode("mov", "a, #0x%x", val);
9768 emitcode("movx", "@dptr, a");
9769 emitcode("inc", "dptr");
9774 emitcode("djnz", "b, %05d$", tlbl->key + 100);
9780 iLoop = iLoop->next;
9783 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
9786 /*-----------------------------------------------------------------*/
9787 /* genFarFarAssign - assignment when both are in far space */
9788 /*-----------------------------------------------------------------*/
9790 genFarFarAssign (operand * result, operand * right, iCode * ic)
9792 int size = AOP_SIZE (right);
9794 symbol *rSym = NULL;
9798 /* quick & easy case. */
9799 D(emitcode(";","genFarFarAssign (1 byte case)"););
9800 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9801 freeAsmop (right, NULL, ic, FALSE);
9802 /* now assign DPTR to result */
9804 aopOp(result, ic, FALSE, FALSE);
9806 aopPut(AOP(result), "a", 0);
9807 freeAsmop(result, NULL, ic, FALSE);
9811 /* See if we've got an underlying symbol to abuse. */
9812 if (IS_SYMOP(result) && OP_SYMBOL(result))
9814 if (IS_TRUE_SYMOP(result))
9816 rSym = OP_SYMBOL(result);
9818 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9820 rSym = OP_SYMBOL(result)->usl.spillLoc;
9824 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9826 /* We can use the '390 auto-toggle feature to good effect here. */
9828 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
9829 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
9830 emitcode ("mov", "dptr,#%s", rSym->rname);
9831 /* DP2 = result, DP1 = right, DP1 is current. */
9834 emitcode("movx", "a,@dptr");
9835 emitcode("movx", "@dptr,a");
9838 emitcode("inc", "dptr");
9839 emitcode("inc", "dptr");
9842 emitcode("mov", "dps, #0");
9843 freeAsmop (right, NULL, ic, FALSE);
9845 some alternative code for processors without auto-toggle
9846 no time to test now, so later well put in...kpb
9847 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
9848 emitcode("mov", "dps, #0x01"); /* Select DPTR2. */
9849 emitcode ("mov", "dptr,#%s", rSym->rname);
9850 /* DP2 = result, DP1 = right, DP1 is current. */
9854 emitcode("movx", "a,@dptr");
9856 emitcode("inc", "dptr");
9857 emitcode("inc", "dps");
9858 emitcode("movx", "@dptr,a");
9860 emitcode("inc", "dptr");
9861 emitcode("inc", "dps");
9863 emitcode("mov", "dps, #0");
9864 freeAsmop (right, NULL, ic, FALSE);
9869 D (emitcode (";", "genFarFarAssign"););
9870 aopOp (result, ic, TRUE, TRUE);
9872 _startLazyDPSEvaluation ();
9876 aopPut (AOP (result),
9877 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9880 _endLazyDPSEvaluation ();
9881 freeAsmop (result, NULL, ic, FALSE);
9882 freeAsmop (right, NULL, ic, FALSE);
9886 /*-----------------------------------------------------------------*/
9887 /* genAssign - generate code for assignment */
9888 /*-----------------------------------------------------------------*/
9890 genAssign (iCode * ic)
9892 operand *result, *right;
9894 unsigned long lit = 0L;
9896 D (emitcode (";", "genAssign ");
9899 result = IC_RESULT (ic);
9900 right = IC_RIGHT (ic);
9902 /* if they are the same */
9903 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9906 aopOp (right, ic, FALSE, FALSE);
9908 emitcode (";", "genAssign: resultIsFar = %s",
9909 isOperandInFarSpace (result) ?
9912 /* special case both in far space */
9913 if ((AOP_TYPE (right) == AOP_DPTR ||
9914 AOP_TYPE (right) == AOP_DPTR2) &&
9915 /* IS_TRUE_SYMOP(result) && */
9916 isOperandInFarSpace (result))
9918 genFarFarAssign (result, right, ic);
9922 aopOp (result, ic, TRUE, FALSE);
9924 /* if they are the same registers */
9925 if (sameRegs (AOP (right), AOP (result)))
9928 /* if the result is a bit */
9929 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
9931 /* if the right size is a literal then
9932 we know what the value is */
9933 if (AOP_TYPE (right) == AOP_LIT)
9935 if (((int) operandLitValue (right)))
9936 aopPut (AOP (result), one, 0);
9938 aopPut (AOP (result), zero, 0);
9942 /* the right is also a bit variable */
9943 if (AOP_TYPE (right) == AOP_CRY)
9945 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9946 aopPut (AOP (result), "c", 0);
9952 aopPut (AOP (result), "a", 0);
9956 /* bit variables done */
9958 size = AOP_SIZE (result);
9960 if (AOP_TYPE (right) == AOP_LIT)
9961 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9964 (AOP_TYPE (result) != AOP_REG) &&
9965 (AOP_TYPE (right) == AOP_LIT) &&
9966 !IS_FLOAT (operandType (right)))
9968 _startLazyDPSEvaluation ();
9969 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9971 aopPut (AOP (result),
9972 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9977 /* And now fill the rest with zeros. */
9980 emitcode ("clr", "a");
9984 aopPut (AOP (result), "a", offset++);
9986 _endLazyDPSEvaluation ();
9990 _startLazyDPSEvaluation ();
9993 aopPut (AOP (result),
9994 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9998 _endLazyDPSEvaluation ();
10002 freeAsmop (right, NULL, ic, FALSE);
10003 freeAsmop (result, NULL, ic, TRUE);
10006 /*-----------------------------------------------------------------*/
10007 /* genJumpTab - generates code for jump table */
10008 /*-----------------------------------------------------------------*/
10010 genJumpTab (iCode * ic)
10015 D (emitcode (";", "genJumpTab ");
10018 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10019 /* get the condition into accumulator */
10020 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10022 /* multiply by four! */
10023 emitcode ("add", "a,acc");
10024 emitcode ("add", "a,acc");
10025 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10027 jtab = newiTempLabel (NULL);
10028 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10029 emitcode ("jmp", "@a+dptr");
10030 emitcode ("", "%05d$:", jtab->key + 100);
10031 /* now generate the jump labels */
10032 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10033 jtab = setNextItem (IC_JTLABELS (ic)))
10034 emitcode ("ljmp", "%05d$", jtab->key + 100);
10038 /*-----------------------------------------------------------------*/
10039 /* genCast - gen code for casting */
10040 /*-----------------------------------------------------------------*/
10042 genCast (iCode * ic)
10044 operand *result = IC_RESULT (ic);
10045 sym_link *ctype = operandType (IC_LEFT (ic));
10046 sym_link *rtype = operandType (IC_RIGHT (ic));
10047 operand *right = IC_RIGHT (ic);
10050 D (emitcode (";", "genCast ");
10053 /* if they are equivalent then do nothing */
10054 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10057 aopOp (right, ic, FALSE, FALSE);
10058 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10060 /* if the result is a bit */
10061 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10062 if (IS_BITVAR(OP_SYMBOL(result)->type))
10064 /* if the right size is a literal then
10065 we know what the value is */
10066 if (AOP_TYPE (right) == AOP_LIT)
10068 if (((int) operandLitValue (right)))
10069 aopPut (AOP (result), one, 0);
10071 aopPut (AOP (result), zero, 0);
10076 /* the right is also a bit variable */
10077 if (AOP_TYPE (right) == AOP_CRY)
10079 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10080 aopPut (AOP (result), "c", 0);
10084 /* we need to or */
10086 aopPut (AOP (result), "a", 0);
10090 /* if they are the same size : or less */
10091 if (AOP_SIZE (result) <= AOP_SIZE (right))
10094 /* if they are in the same place */
10095 if (sameRegs (AOP (right), AOP (result)))
10098 /* if they in different places then copy */
10099 size = AOP_SIZE (result);
10101 _startLazyDPSEvaluation ();
10104 aopPut (AOP (result),
10105 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10109 _endLazyDPSEvaluation ();
10114 /* if the result is of type pointer */
10115 if (IS_PTR (ctype))
10119 sym_link *type = operandType (right);
10121 /* pointer to generic pointer */
10122 if (IS_GENPTR (ctype))
10128 p_type = DCL_TYPE (type);
10132 #if OLD_CAST_BEHAVIOR
10133 /* KV: we are converting a non-pointer type to
10134 * a generic pointer. This (ifdef'd out) code
10135 * says that the resulting generic pointer
10136 * should have the same class as the storage
10137 * location of the non-pointer variable.
10139 * For example, converting an int (which happens
10140 * to be stored in DATA space) to a pointer results
10141 * in a DATA generic pointer; if the original int
10142 * in XDATA space, so will be the resulting pointer.
10144 * I don't like that behavior, and thus this change:
10145 * all such conversions will be forced to XDATA and
10146 * throw a warning. If you want some non-XDATA
10147 * type, or you want to suppress the warning, you
10148 * must go through an intermediate cast, like so:
10150 * char _generic *gp = (char _xdata *)(intVar);
10152 sym_link *etype = getSpec (type);
10154 /* we have to go by the storage class */
10155 if (SPEC_OCLS (etype) != generic)
10157 p_type = PTR_TYPE (SPEC_OCLS (etype));
10162 /* Converting unknown class (i.e. register variable)
10163 * to generic pointer. This is not good, but
10164 * we'll make a guess (and throw a warning).
10167 werror (W_INT_TO_GEN_PTR_CAST);
10171 /* the first two bytes are known */
10172 size = GPTRSIZE - 1;
10174 _startLazyDPSEvaluation ();
10177 aopPut (AOP (result),
10178 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10182 _endLazyDPSEvaluation ();
10184 /* the last byte depending on type */
10202 /* this should never happen */
10203 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10204 "got unknown pointer type");
10207 aopPut (AOP (result), l, GPTRSIZE - 1);
10211 /* just copy the pointers */
10212 size = AOP_SIZE (result);
10214 _startLazyDPSEvaluation ();
10217 aopPut (AOP (result),
10218 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10222 _endLazyDPSEvaluation ();
10226 /* so we now know that the size of destination is greater
10227 than the size of the source */
10228 /* we move to result for the size of source */
10229 size = AOP_SIZE (right);
10231 _startLazyDPSEvaluation ();
10234 aopPut (AOP (result),
10235 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10239 _endLazyDPSEvaluation ();
10241 /* now depending on the sign of the source && destination */
10242 size = AOP_SIZE (result) - AOP_SIZE (right);
10243 /* if unsigned or not an integral type */
10244 /* also, if the source is a bit, we don't need to sign extend, because
10245 * it can't possibly have set the sign bit.
10247 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10251 aopPut (AOP (result), zero, offset++);
10256 /* we need to extend the sign :{ */
10257 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10258 FALSE, FALSE, TRUE);
10260 emitcode ("rlc", "a");
10261 emitcode ("subb", "a,acc");
10263 aopPut (AOP (result), "a", offset++);
10266 /* we are done hurray !!!! */
10269 freeAsmop (right, NULL, ic, TRUE);
10270 freeAsmop (result, NULL, ic, TRUE);
10274 /*-----------------------------------------------------------------*/
10275 /* genDjnz - generate decrement & jump if not zero instrucion */
10276 /*-----------------------------------------------------------------*/
10278 genDjnz (iCode * ic, iCode * ifx)
10280 symbol *lbl, *lbl1;
10284 /* if the if condition has a false label
10285 then we cannot save */
10286 if (IC_FALSE (ifx))
10289 /* if the minus is not of the form
10291 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10292 !IS_OP_LITERAL (IC_RIGHT (ic)))
10295 if (operandLitValue (IC_RIGHT (ic)) != 1)
10298 /* if the size of this greater than one then no
10300 if (getSize (operandType (IC_RESULT (ic))) > 1)
10303 /* otherwise we can save BIG */
10304 D(emitcode(";", "genDjnz"););
10306 lbl = newiTempLabel (NULL);
10307 lbl1 = newiTempLabel (NULL);
10309 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10311 if (AOP_NEEDSACC(IC_RESULT(ic)))
10313 /* If the result is accessed indirectly via
10314 * the accumulator, we must explicitly write
10315 * it back after the decrement.
10317 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10319 if (strcmp(rByte, "a"))
10321 /* Something is hopelessly wrong */
10322 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10323 __FILE__, __LINE__);
10324 /* We can just give up; the generated code will be inefficient,
10325 * but what the hey.
10327 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10330 emitcode ("dec", "%s", rByte);
10331 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10332 emitcode ("jnz", "%05d$", lbl->key + 100);
10334 else if (IS_AOP_PREG (IC_RESULT (ic)))
10336 emitcode ("dec", "%s",
10337 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10338 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10339 emitcode ("jnz", "%05d$", lbl->key + 100);
10343 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10346 emitcode ("sjmp", "%05d$", lbl1->key + 100);
10347 emitcode ("", "%05d$:", lbl->key + 100);
10348 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10349 emitcode ("", "%05d$:", lbl1->key + 100);
10351 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10352 ifx->generated = 1;
10356 /*-----------------------------------------------------------------*/
10357 /* genReceive - generate code for a receive iCode */
10358 /*-----------------------------------------------------------------*/
10360 genReceive (iCode * ic)
10363 D (emitcode (";", "genReceive ");
10366 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10367 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10368 IS_TRUE_SYMOP (IC_RESULT (ic))))
10370 int size = getSize (operandType (IC_RESULT (ic)));
10371 int offset = fReturnSizeDS390 - size;
10374 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10375 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10378 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10379 size = AOP_SIZE (IC_RESULT (ic));
10383 emitcode ("pop", "acc");
10384 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10391 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10393 assignResultValue (IC_RESULT (ic));
10396 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10399 /*-----------------------------------------------------------------*/
10400 /* gen390Code - generate code for Dallas 390 based controllers */
10401 /*-----------------------------------------------------------------*/
10403 gen390Code (iCode * lic)
10408 lineHead = lineCurr = NULL;
10410 if (options.model == MODEL_FLAT24) {
10411 fReturnSizeDS390 = 5;
10412 fReturn = fReturn24;
10414 fReturnSizeDS390 = 4;
10415 fReturn = fReturn16;
10416 options.stack10bit=0;
10420 /* print the allocation information */
10422 printAllocInfo (currFunc, codeOutFile);
10424 /* if debug information required */
10425 if (options.debug && currFunc)
10427 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
10429 if (IS_STATIC (currFunc->etype))
10430 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
10432 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
10435 /* stack pointer name */
10436 if (options.useXstack)
10442 for (ic = lic; ic; ic = ic->next)
10445 if (cln != ic->lineno)
10450 emitcode ("", "C$%s$%d$%d$%d ==.",
10451 FileBaseName (ic->filename), ic->lineno,
10452 ic->level, ic->block);
10455 emitcode (";", "%s %d", ic->filename, ic->lineno);
10458 /* if the result is marked as
10459 spilt and rematerializable or code for
10460 this has already been generated then
10462 if (resultRemat (ic) || ic->generated)
10465 /* depending on the operation */
10485 /* IPOP happens only when trying to restore a
10486 spilt live range, if there is an ifx statement
10487 following this pop then the if statement might
10488 be using some of the registers being popped which
10489 would destory the contents of the register so
10490 we need to check for this condition and handle it */
10492 ic->next->op == IFX &&
10493 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10494 genIfx (ic->next, ic);
10512 genEndFunction (ic);
10532 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10549 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10553 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10560 /* note these two are xlated by algebraic equivalence
10561 during parsing SDCC.y */
10562 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10563 "got '>=' or '<=' shouldn't have come here");
10567 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10579 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10583 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10587 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10611 genRightShift (ic);
10614 case GET_VALUE_AT_ADDRESS:
10615 genPointerGet (ic);
10619 if (POINTER_SET (ic))
10620 genPointerSet (ic);
10646 addSet (&_G.sendSet, ic);
10659 /* now we are ready to call the
10660 peep hole optimizer */
10661 if (!options.nopeep)
10662 peepHole (&lineHead);
10664 /* now do the actual printing */
10665 printLine (lineHead, codeOutFile);