1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for DS80C390
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 DS390 adaptation by Kevin Vigor <kevin@vigor.nu>
9 This program is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 In other words, you are welcome to use, share and improve this program.
24 You are forbidden to forbid anyone else to use, share and improve
25 what you give them. Help stamp out software-hoarding!
26 -------------------------------------------------------------------------*/
36 #include "SDCCglobl.h"
39 #ifdef HAVE_SYS_ISA_DEFS_H
40 #include <sys/isa_defs.h>
42 #ifdef HAVE_MACHINE_ENDIAN_H
43 #include <machine/endian.h>
48 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
49 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
50 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
56 #define BETTER_LITERAL_SHIFT
58 char *aopLiteral (value * val, int offset);
60 /* this is the down and dirty file with all kinds of
61 kludgy & hacky stuff. This is what it is all about
62 CODE GENERATION for a specific MCU . some of the
63 routines may be reusable, will have to see */
65 static char *zero = "#0x00";
66 static char *one = "#0x01";
71 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
72 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
74 unsigned fReturnSizeDS390 = 5; /* shared with ralloc.c */
75 static char *fReturn24[] =
76 {"dpl", "dph", "dpx", "b", "a"};
77 static char *fReturn16[] =
78 {"dpl", "dph", "b", "a"};
79 static char **fReturn = fReturn24;
80 static char *accUse[] =
83 static short rbank = -1;
97 static void saveRBank (int, iCode *, bool);
99 #define RESULTONSTACK(x) \
100 (IC_RESULT(x) && IC_RESULT(x)->aop && \
101 IC_RESULT(x)->aop->type == AOP_STK )
103 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
104 #define MOVA(x) { char *_mova_tmp = strdup(x); \
105 if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
107 emitcode("mov","a,%s",_mova_tmp); \
111 #define CLRC emitcode("clr","c")
112 #define SETC emitcode("setb","c")
114 // A scratch register which will be used to hold
115 // result bytes from operands in far space via DPTR2.
116 #define DP2_RESULT_REG "ap"
118 static lineNode *lineHead = NULL;
119 static lineNode *lineCurr = NULL;
121 static unsigned char SLMask[] =
122 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
123 0xE0, 0xC0, 0x80, 0x00};
124 static unsigned char SRMask[] =
125 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
126 0x07, 0x03, 0x01, 0x00};
133 /*-----------------------------------------------------------------*/
134 /* emitcode - writes the code into a file : for now it is simple */
135 /*-----------------------------------------------------------------*/
137 emitcode (char *inst, char *fmt,...)
140 char lb[INITIAL_INLINEASM];
148 sprintf (lb, "%s\t", inst);
150 sprintf (lb, "%s", inst);
151 vsprintf (lb + (strlen (lb)), fmt, ap);
154 vsprintf (lb, fmt, ap);
156 while (isspace (*lbp))
160 lineCurr = (lineCurr ?
161 connectLine (lineCurr, newLineNode (lb)) :
162 (lineHead = newLineNode (lb)));
163 lineCurr->isInline = _G.inLine;
164 lineCurr->isDebug = _G.debugLine;
168 /*-----------------------------------------------------------------*/
169 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
170 /*-----------------------------------------------------------------*/
172 getFreePtr (iCode * ic, asmop ** aopp, bool result)
174 bool r0iu = FALSE, r1iu = FALSE;
175 bool r0ou = FALSE, r1ou = FALSE;
177 /* the logic: if r0 & r1 used in the instruction
178 then we are in trouble otherwise */
180 /* first check if r0 & r1 are used by this
181 instruction, in which case we are in trouble */
182 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
183 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
188 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
189 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
191 /* if no usage of r0 then return it */
194 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
195 (*aopp)->type = AOP_R0;
197 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
200 /* if no usage of r1 then return it */
203 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
204 (*aopp)->type = AOP_R1;
206 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
209 /* now we know they both have usage */
210 /* if r0 not used in this instruction */
213 /* push it if not already pushed */
216 emitcode ("push", "%s",
217 ds390_regWithIdx (R0_IDX)->dname);
221 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
222 (*aopp)->type = AOP_R0;
224 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
227 /* if r1 not used then */
231 /* push it if not already pushed */
234 emitcode ("push", "%s",
235 ds390_regWithIdx (R1_IDX)->dname);
239 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
240 (*aopp)->type = AOP_R1;
241 return ds390_regWithIdx (R1_IDX);
245 /* I said end of world but not quite end of world yet */
246 /* if this is a result then we can push it on the stack */
249 (*aopp)->type = AOP_STK;
253 /* other wise this is true end of the world */
254 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
255 "getFreePtr should never reach here");
259 /*-----------------------------------------------------------------*/
260 /* newAsmop - creates a new asmOp */
261 /*-----------------------------------------------------------------*/
263 newAsmop (short type)
267 aop = Safe_calloc (1, sizeof (asmop));
272 static int _currentDPS; /* Current processor DPS. */
273 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
274 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
276 /*-----------------------------------------------------------------*/
277 /* genSetDPTR: generate code to select which DPTR is in use (zero */
278 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
279 /* alternate DPTR (DPL1/DPH1/DPX1). */
280 /*-----------------------------------------------------------------*/
285 /* If we are doing lazy evaluation, simply note the desired
286 * change, but don't emit any code yet.
296 emitcode ("mov", "dps, #0x00");
301 emitcode ("mov", "dps, #0x01");
305 /*-----------------------------------------------------------------*/
306 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
308 /* Any code that operates on DPTR (NB: not on the individual */
309 /* components, like DPH) *must* call _flushLazyDPS() before using */
310 /* DPTR within a lazy DPS evaluation block. */
312 /* Note that aopPut and aopGet already contain the proper calls to */
313 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
314 /* DPS evaluation block. */
316 /* Also, _flushLazyDPS must be called before any flow control */
317 /* operations that could potentially branch out of the block. */
319 /* Lazy DPS evaluation is simply an optimization (though an */
320 /* important one), so if in doubt, leave it out. */
321 /*-----------------------------------------------------------------*/
323 _startLazyDPSEvaluation (void)
327 #ifdef BETTER_LITERAL_SHIFT
334 /*-----------------------------------------------------------------*/
335 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
336 /* desired one. Call before using DPTR within a lazy DPS evaluation */
338 /*-----------------------------------------------------------------*/
348 if (_desiredDPS != _currentDPS)
352 emitcode ("inc", "dps");
356 emitcode ("dec", "dps");
358 _currentDPS = _desiredDPS;
362 /*-----------------------------------------------------------------*/
363 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
365 /* Forces us back to the safe state (standard DPTR selected). */
366 /*-----------------------------------------------------------------*/
368 _endLazyDPSEvaluation (void)
370 #ifdef BETTER_LITERAL_SHIFT
389 /*-----------------------------------------------------------------*/
390 /* pointerCode - returns the code for a pointer type */
391 /*-----------------------------------------------------------------*/
393 pointerCode (sym_link * etype)
396 return PTR_TYPE (SPEC_OCLS (etype));
400 /*-----------------------------------------------------------------*/
401 /* aopForSym - for a true symbol */
402 /*-----------------------------------------------------------------*/
404 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
407 memmap *space = SPEC_OCLS (sym->etype);
409 /* if already has one */
413 /* assign depending on the storage class */
414 /* if it is on the stack or indirectly addressable */
415 /* space we need to assign either r0 or r1 to it */
416 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
418 sym->aop = aop = newAsmop (0);
419 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
420 aop->size = getSize (sym->type);
422 /* now assign the address of the variable to
423 the pointer register */
424 if (aop->type != AOP_STK)
430 emitcode ("push", "acc");
432 emitcode ("mov", "a,_bp");
433 emitcode ("add", "a,#0x%02x",
435 ((char) (sym->stack - _G.nRegsSaved)) :
436 ((char) sym->stack)) & 0xff);
437 emitcode ("mov", "%s,a",
438 aop->aopu.aop_ptr->name);
441 emitcode ("pop", "acc");
444 emitcode ("mov", "%s,#%s",
445 aop->aopu.aop_ptr->name,
447 aop->paged = space->paged;
450 aop->aopu.aop_stk = sym->stack;
454 if (sym->onStack && options.stack10bit)
456 /* It's on the 10 bit stack, which is located in
461 emitcode ("push", "acc");
463 emitcode ("mov", "a,_bp");
464 emitcode ("add", "a,#0x%02x",
466 ((char) (sym->stack - _G.nRegsSaved)) :
467 ((char) sym->stack)) & 0xff);
471 if (options.model == MODEL_FLAT24)
472 emitcode ("mov", "dpx1,#0x40");
474 emitcode ("mov", "dph1,#0x00");
475 emitcode ("mov", "dpl1, a");
479 if (options.model == MODEL_FLAT24)
480 emitcode ("mov", "dpx,#0x40");
481 emitcode ("mov", "dph,#0x00");
482 emitcode ("mov", "dpl, a");
486 emitcode ("pop", "acc");
488 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
489 aop->size = getSize (sym->type);
493 /* if in bit space */
494 if (IN_BITSPACE (space))
496 sym->aop = aop = newAsmop (AOP_CRY);
497 aop->aopu.aop_dir = sym->rname;
498 aop->size = getSize (sym->type);
501 /* if it is in direct space */
502 if (IN_DIRSPACE (space))
504 sym->aop = aop = newAsmop (AOP_DIR);
505 aop->aopu.aop_dir = sym->rname;
506 aop->size = getSize (sym->type);
510 /* special case for a function */
511 if (IS_FUNC (sym->type))
513 sym->aop = aop = newAsmop (AOP_IMMD);
514 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
515 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
516 aop->size = FPTRSIZE;
520 /* only remaining is far space */
521 /* in which case DPTR gets the address */
522 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
527 emitcode ("mov", "dptr,#%s", sym->rname);
532 emitcode ("mov", "dptr,#%s", sym->rname);
534 aop->size = getSize (sym->type);
536 /* if it is in code space */
537 if (IN_CODESPACE (space))
543 /*-----------------------------------------------------------------*/
544 /* aopForRemat - rematerialzes an object */
545 /*-----------------------------------------------------------------*/
547 aopForRemat (symbol * sym)
549 iCode *ic = sym->rematiCode;
550 asmop *aop = newAsmop (AOP_IMMD);
557 val += (int) operandLitValue (IC_RIGHT (ic));
558 else if (ic->op == '-')
559 val -= (int) operandLitValue (IC_RIGHT (ic));
560 else if (IS_CAST_ICODE(ic)) {
561 sym_link *from_type = operandType(IC_RIGHT(ic));
562 aop->aopu.aop_immd.from_cast_remat = 1;
563 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
564 ptr_type = DCL_TYPE(from_type);
568 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
572 sprintf (buffer, "(%s %c 0x%04x)",
573 OP_SYMBOL (IC_LEFT (ic))->rname,
574 val >= 0 ? '+' : '-',
577 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
579 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
580 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
581 /* set immd2 field if required */
582 if (aop->aopu.aop_immd.from_cast_remat) {
583 sprintf(buffer,"#0x%02x",ptr_type);
584 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
585 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
591 /*-----------------------------------------------------------------*/
592 /* regsInCommon - two operands have some registers in common */
593 /*-----------------------------------------------------------------*/
595 regsInCommon (operand * op1, operand * op2)
600 /* if they have registers in common */
601 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
604 sym1 = OP_SYMBOL (op1);
605 sym2 = OP_SYMBOL (op2);
607 if (sym1->nRegs == 0 || sym2->nRegs == 0)
610 for (i = 0; i < sym1->nRegs; i++)
616 for (j = 0; j < sym2->nRegs; j++)
621 if (sym2->regs[j] == sym1->regs[i])
629 /*-----------------------------------------------------------------*/
630 /* operandsEqu - equivalent */
631 /*-----------------------------------------------------------------*/
633 operandsEqu (operand * op1, operand * op2)
637 /* if they not symbols */
638 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
641 sym1 = OP_SYMBOL (op1);
642 sym2 = OP_SYMBOL (op2);
644 /* if both are itemps & one is spilt
645 and the other is not then false */
646 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
647 sym1->isspilt != sym2->isspilt)
650 /* if they are the same */
654 if (strcmp (sym1->rname, sym2->rname) == 0)
658 /* if left is a tmp & right is not */
659 if (IS_ITEMP (op1) &&
662 (sym1->usl.spillLoc == sym2))
665 if (IS_ITEMP (op2) &&
669 (sym2->usl.spillLoc == sym1))
675 /*-----------------------------------------------------------------*/
676 /* sameRegs - two asmops have the same registers */
677 /*-----------------------------------------------------------------*/
679 sameRegs (asmop * aop1, asmop * aop2)
685 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
692 if (aop1->type != AOP_REG ||
693 aop2->type != AOP_REG)
696 if (aop1->size != aop2->size)
699 for (i = 0; i < aop1->size; i++)
700 if (aop1->aopu.aop_reg[i] !=
701 aop2->aopu.aop_reg[i])
707 /*-----------------------------------------------------------------*/
708 /* aopOp - allocates an asmop for an operand : */
709 /*-----------------------------------------------------------------*/
711 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
720 /* if this a literal */
721 if (IS_OP_LITERAL (op))
723 op->aop = aop = newAsmop (AOP_LIT);
724 aop->aopu.aop_lit = op->operand.valOperand;
725 aop->size = getSize (operandType (op));
729 /* if already has a asmop then continue */
733 /* if the underlying symbol has a aop */
734 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
736 op->aop = OP_SYMBOL (op)->aop;
740 /* if this is a true symbol */
741 if (IS_TRUE_SYMOP (op))
743 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
747 /* this is a temporary : this has
753 e) can be a return use only */
755 sym = OP_SYMBOL (op);
758 /* if the type is a conditional */
759 if (sym->regType == REG_CND)
761 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
766 /* if it is spilt then two situations
768 b) has a spill location */
769 if (sym->isspilt || sym->nRegs == 0)
772 /* rematerialize it NOW */
775 sym->aop = op->aop = aop =
777 aop->size = getSize (sym->type);
784 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
785 aop->size = getSize (sym->type);
786 for (i = 0; i < 2; i++)
787 aop->aopu.aop_str[i] = accUse[i];
797 /* a AOP_STR uses DPTR, but DPTR is already in use;
800 fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use!\n");
803 aop = op->aop = sym->aop = newAsmop (AOP_STR);
804 aop->size = getSize (sym->type);
805 for (i = 0; i < (int) fReturnSizeDS390; i++)
806 aop->aopu.aop_str[i] = fReturn[i];
810 /* else spill location */
811 sym->aop = op->aop = aop =
812 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
813 aop->size = getSize (sym->type);
817 /* must be in a register */
818 sym->aop = op->aop = aop = newAsmop (AOP_REG);
819 aop->size = sym->nRegs;
820 for (i = 0; i < sym->nRegs; i++)
821 aop->aopu.aop_reg[i] = sym->regs[i];
824 /*-----------------------------------------------------------------*/
825 /* freeAsmop - free up the asmop given to an operand */
826 /*----------------------------------------------------------------*/
828 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
845 /* depending on the asmop type only three cases need work AOP_RO
846 , AOP_R1 && AOP_STK */
854 emitcode ("pop", "ar0");
858 bitVectUnSetBit (ic->rUsed, R0_IDX);
866 emitcode ("pop", "ar1");
870 bitVectUnSetBit (ic->rUsed, R1_IDX);
876 int stk = aop->aopu.aop_stk + aop->size;
877 bitVectUnSetBit (ic->rUsed, R0_IDX);
878 bitVectUnSetBit (ic->rUsed, R1_IDX);
880 getFreePtr (ic, &aop, FALSE);
882 if (options.stack10bit)
884 /* I'm not sure what to do here yet... */
887 "*** Warning: probably generating bad code for "
888 "10 bit stack mode.\n");
893 emitcode ("mov", "a,_bp");
894 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
895 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
899 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
904 emitcode ("pop", "acc");
905 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
908 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
911 freeAsmop (op, NULL, ic, TRUE);
914 emitcode ("pop", "ar0");
920 emitcode ("pop", "ar1");
927 /* all other cases just dealloc */
933 OP_SYMBOL (op)->aop = NULL;
934 /* if the symbol has a spill */
936 SPIL_LOC (op)->aop = NULL;
941 /*------------------------------------------------------------------*/
942 /* aopGet - for fetching value of the aop */
944 /* Set canClobberACC if you are sure it is OK to clobber the value */
945 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
946 /* just less efficient. */
947 /*------------------------------------------------------------------*/
959 /* offset is greater than
961 if (offset > (aop->size - 1) &&
962 aop->type != AOP_LIT)
965 /* depending on type */
971 /* if we need to increment it */
972 while (offset > aop->coff)
974 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
978 while (offset < aop->coff)
980 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
987 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
988 return (dname ? "acc" : "a");
990 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
991 rs = Safe_calloc (1, strlen (s) + 1);
998 if (aop->type == AOP_DPTR2)
1004 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1010 while (offset > aop->coff)
1012 emitcode ("inc", "dptr");
1016 while (offset < aop->coff)
1018 emitcode ("lcall", "__decdptr");
1025 emitcode ("clr", "a");
1026 emitcode ("movc", "a,@a+dptr");
1030 emitcode ("movx", "a,@dptr");
1033 if (aop->type == AOP_DPTR2)
1039 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1040 return DP2_RESULT_REG;
1043 return (dname ? "acc" : "a");
1046 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1047 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1049 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1051 sprintf (s, "#(%s >> %d)",
1052 aop->aopu.aop_immd.aop_immd1,
1056 aop->aopu.aop_immd.aop_immd1);
1057 rs = Safe_calloc (1, strlen (s) + 1);
1063 sprintf (s, "(%s + %d)",
1067 sprintf (s, "%s", aop->aopu.aop_dir);
1068 rs = Safe_calloc (1, strlen (s) + 1);
1074 return aop->aopu.aop_reg[offset]->dname;
1076 return aop->aopu.aop_reg[offset]->name;
1079 emitcode ("clr", "a");
1080 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1081 emitcode ("rlc", "a");
1082 return (dname ? "acc" : "a");
1085 if (!offset && dname)
1087 return aop->aopu.aop_str[offset];
1090 return aopLiteral (aop->aopu.aop_lit, offset);
1094 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1098 return aop->aopu.aop_str[offset];
1102 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1103 "aopget got unsupported aop->type");
1106 /*-----------------------------------------------------------------*/
1107 /* aopPut - puts a string for a aop */
1108 /*-----------------------------------------------------------------*/
1110 aopPut (asmop * aop, char *s, int offset)
1114 if (aop->size && offset > (aop->size - 1))
1116 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1117 "aopPut got offset > aop->size");
1121 /* will assign value to value */
1122 /* depending on where it is ofcourse */
1127 sprintf (d, "(%s + %d)",
1128 aop->aopu.aop_dir, offset);
1130 sprintf (d, "%s", aop->aopu.aop_dir);
1133 emitcode ("mov", "%s,%s", d, s);
1138 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1139 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1142 strcmp (s, "r0") == 0 ||
1143 strcmp (s, "r1") == 0 ||
1144 strcmp (s, "r2") == 0 ||
1145 strcmp (s, "r3") == 0 ||
1146 strcmp (s, "r4") == 0 ||
1147 strcmp (s, "r5") == 0 ||
1148 strcmp (s, "r6") == 0 ||
1149 strcmp (s, "r7") == 0)
1150 emitcode ("mov", "%s,%s",
1151 aop->aopu.aop_reg[offset]->dname, s);
1153 emitcode ("mov", "%s,%s",
1154 aop->aopu.aop_reg[offset]->name, s);
1161 if (aop->type == AOP_DPTR2)
1169 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1170 "aopPut writting to code space");
1174 while (offset > aop->coff)
1177 emitcode ("inc", "dptr");
1180 while (offset < aop->coff)
1183 emitcode ("lcall", "__decdptr");
1188 /* if not in accumulater */
1191 emitcode ("movx", "@dptr,a");
1193 if (aop->type == AOP_DPTR2)
1201 while (offset > aop->coff)
1204 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1206 while (offset < aop->coff)
1209 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1216 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1222 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1224 else if (strcmp (s, "r0") == 0 ||
1225 strcmp (s, "r1") == 0 ||
1226 strcmp (s, "r2") == 0 ||
1227 strcmp (s, "r3") == 0 ||
1228 strcmp (s, "r4") == 0 ||
1229 strcmp (s, "r5") == 0 ||
1230 strcmp (s, "r6") == 0 ||
1231 strcmp (s, "r7") == 0)
1234 sprintf (buffer, "a%s", s);
1235 emitcode ("mov", "@%s,%s",
1236 aop->aopu.aop_ptr->name, buffer);
1239 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1244 if (strcmp (s, "a") == 0)
1245 emitcode ("push", "acc");
1249 emitcode ("push", "acc");
1251 emitcode ("push", s);
1257 /* if bit variable */
1258 if (!aop->aopu.aop_dir)
1260 emitcode ("clr", "a");
1261 emitcode ("rlc", "a");
1266 emitcode ("clr", "%s", aop->aopu.aop_dir);
1268 emitcode ("setb", "%s", aop->aopu.aop_dir);
1269 else if (!strcmp (s, "c"))
1270 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1273 if (strcmp (s, "a"))
1278 symbol *lbl = newiTempLabel (NULL);
1279 emitcode ("clr", "c");
1280 emitcode ("jz", "%05d$", lbl->key + 100);
1281 emitcode ("cpl", "c");
1282 emitcode ("", "%05d$:", lbl->key + 100);
1283 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1291 if (strcmp (aop->aopu.aop_str[offset], s))
1292 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1297 if (!offset && (strcmp (s, "acc") == 0))
1300 if (strcmp (aop->aopu.aop_str[offset], s))
1301 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1305 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1306 "aopPut got unsupported aop->type");
1313 /*--------------------------------------------------------------------*/
1314 /* reAdjustPreg - points a register back to where it should (coff==0) */
1315 /*--------------------------------------------------------------------*/
1317 reAdjustPreg (asmop * aop)
1319 if ((aop->coff==0) || (aop->size <= 1)) {
1328 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1332 if (aop->type == AOP_DPTR2)
1339 emitcode ("lcall", "__decdptr");
1342 if (aop->type == AOP_DPTR2)
1352 #define AOP(op) op->aop
1353 #define AOP_TYPE(op) AOP(op)->type
1354 #define AOP_SIZE(op) AOP(op)->size
1355 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1356 AOP_TYPE(x) == AOP_R0))
1358 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1359 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1362 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1363 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1364 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1366 /* Workaround for DS80C390 bug: div ab may return bogus results
1367 * if A is accessed in instruction immediately before the div.
1369 * Will be fixed in B4 rev of processor, Dallas claims.
1372 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1373 if (!AOP_NEEDSACC(RIGHT)) \
1375 /* We can load A first, then B, since \
1376 * B (the RIGHT operand) won't clobber A, \
1377 * thus avoiding touching A right before the div. \
1379 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1380 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1382 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1386 /* Just stuff in a nop after loading A. */ \
1387 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1388 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1390 emitcode("nop", "; workaround for DS80C390 div bug."); \
1393 /*-----------------------------------------------------------------*/
1394 /* genNotFloat - generates not for float operations */
1395 /*-----------------------------------------------------------------*/
1397 genNotFloat (operand * op, operand * res)
1403 D (emitcode (";", "genNotFloat ");
1406 /* we will put 127 in the first byte of
1408 aopPut (AOP (res), "#127", 0);
1409 size = AOP_SIZE (op) - 1;
1412 _startLazyDPSEvaluation ();
1413 l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1418 emitcode ("orl", "a,%s",
1420 offset++, FALSE, FALSE, FALSE));
1422 _endLazyDPSEvaluation ();
1424 tlbl = newiTempLabel (NULL);
1425 aopPut (res->aop, one, 1);
1426 emitcode ("jz", "%05d$", (tlbl->key + 100));
1427 aopPut (res->aop, zero, 1);
1428 emitcode ("", "%05d$:", (tlbl->key + 100));
1430 size = res->aop->size - 2;
1432 /* put zeros in the rest */
1434 aopPut (res->aop, zero, offset++);
1437 /*-----------------------------------------------------------------*/
1438 /* opIsGptr: returns non-zero if the passed operand is */
1439 /* a generic pointer type. */
1440 /*-----------------------------------------------------------------*/
1442 opIsGptr (operand * op)
1444 sym_link *type = operandType (op);
1446 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1453 /*-----------------------------------------------------------------*/
1454 /* getDataSize - get the operand data size */
1455 /*-----------------------------------------------------------------*/
1457 getDataSize (operand * op)
1460 size = AOP_SIZE (op);
1461 if (size == GPTRSIZE)
1463 sym_link *type = operandType (op);
1464 if (IS_GENPTR (type))
1466 /* generic pointer; arithmetic operations
1467 * should ignore the high byte (pointer type).
1475 /*-----------------------------------------------------------------*/
1476 /* outAcc - output Acc */
1477 /*-----------------------------------------------------------------*/
1479 outAcc (operand * result)
1482 size = getDataSize (result);
1485 aopPut (AOP (result), "a", 0);
1488 /* unsigned or positive */
1491 aopPut (AOP (result), zero, offset++);
1496 /*-----------------------------------------------------------------*/
1497 /* outBitC - output a bit C */
1498 /*-----------------------------------------------------------------*/
1500 outBitC (operand * result)
1502 /* if the result is bit */
1503 if (AOP_TYPE (result) == AOP_CRY)
1505 aopPut (AOP (result), "c", 0);
1509 emitcode ("clr", "a");
1510 emitcode ("rlc", "a");
1515 /*-----------------------------------------------------------------*/
1516 /* toBoolean - emit code for orl a,operator(sizeop) */
1517 /*-----------------------------------------------------------------*/
1519 toBoolean (operand * oper)
1521 int size = AOP_SIZE (oper) - 1;
1525 /* The generic part of a generic pointer should
1526 * not participate in it's truth value.
1528 * i.e. 0x10000000 is zero.
1530 if (opIsGptr (oper))
1532 D (emitcode (";", "toBoolean: generic ptr special case.");
1537 _startLazyDPSEvaluation ();
1538 if (AOP_NEEDSACC (oper) && size)
1541 emitcode ("push", "b");
1542 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1546 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1552 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1556 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1559 _endLazyDPSEvaluation ();
1563 emitcode ("mov", "a,b");
1564 emitcode ("pop", "b");
1569 /*-----------------------------------------------------------------*/
1570 /* genNot - generate code for ! operation */
1571 /*-----------------------------------------------------------------*/
1576 sym_link *optype = operandType (IC_LEFT (ic));
1578 D (emitcode (";", "genNot ");
1581 /* assign asmOps to operand & result */
1582 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1583 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1585 /* if in bit space then a special case */
1586 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1588 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1589 emitcode ("cpl", "c");
1590 outBitC (IC_RESULT (ic));
1594 /* if type float then do float */
1595 if (IS_FLOAT (optype))
1597 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1601 toBoolean (IC_LEFT (ic));
1603 tlbl = newiTempLabel (NULL);
1604 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1605 emitcode ("", "%05d$:", tlbl->key + 100);
1606 outBitC (IC_RESULT (ic));
1609 /* release the aops */
1610 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1611 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1615 /*-----------------------------------------------------------------*/
1616 /* genCpl - generate code for complement */
1617 /*-----------------------------------------------------------------*/
1624 D (emitcode (";", "genCpl ");
1628 /* assign asmOps to operand & result */
1629 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1630 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1632 /* if both are in bit space then
1634 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1635 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1638 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1639 emitcode ("cpl", "c");
1640 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1644 size = AOP_SIZE (IC_RESULT (ic));
1645 _startLazyDPSEvaluation ();
1648 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1650 emitcode ("cpl", "a");
1651 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1653 _endLazyDPSEvaluation ();
1657 /* release the aops */
1658 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1659 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1662 /*-----------------------------------------------------------------*/
1663 /* genUminusFloat - unary minus for floating points */
1664 /*-----------------------------------------------------------------*/
1666 genUminusFloat (operand * op, operand * result)
1668 int size, offset = 0;
1670 /* for this we just need to flip the
1671 first it then copy the rest in place */
1672 D (emitcode (";", "genUminusFloat");
1675 _startLazyDPSEvaluation ();
1676 size = AOP_SIZE (op) - 1;
1677 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1680 emitcode ("cpl", "acc.7");
1681 aopPut (AOP (result), "a", 3);
1685 aopPut (AOP (result),
1686 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1690 _endLazyDPSEvaluation ();
1693 /*-----------------------------------------------------------------*/
1694 /* genUminus - unary minus code generation */
1695 /*-----------------------------------------------------------------*/
1697 genUminus (iCode * ic)
1700 sym_link *optype, *rtype;
1702 D (emitcode (";", "genUminus ");
1707 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1708 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1710 /* if both in bit space then special
1712 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1713 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1716 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1717 emitcode ("cpl", "c");
1718 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1722 optype = operandType (IC_LEFT (ic));
1723 rtype = operandType (IC_RESULT (ic));
1725 /* if float then do float stuff */
1726 if (IS_FLOAT (optype))
1728 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1732 /* otherwise subtract from zero */
1733 size = AOP_SIZE (IC_LEFT (ic));
1735 _startLazyDPSEvaluation ();
1738 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1739 if (!strcmp (l, "a"))
1743 emitcode ("cpl", "a");
1744 emitcode ("addc", "a,#0");
1750 emitcode ("clr", "a");
1751 emitcode ("subb", "a,%s", l);
1753 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1755 _endLazyDPSEvaluation ();
1757 /* if any remaining bytes in the result */
1758 /* we just need to propagate the sign */
1759 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1761 emitcode ("rlc", "a");
1762 emitcode ("subb", "a,acc");
1764 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1768 /* release the aops */
1769 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1770 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1773 /*-----------------------------------------------------------------*/
1774 /* saveRegisters - will look for a call and save the registers */
1775 /*-----------------------------------------------------------------*/
1777 saveRegisters (iCode * lic)
1785 for (ic = lic; ic; ic = ic->next)
1786 if (ic->op == CALL || ic->op == PCALL)
1791 fprintf (stderr, "found parameter push with no function call\n");
1795 /* if the registers have been saved already then
1797 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type) ||
1798 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))))
1801 /* find the registers in use at this time
1802 and push them away to safety */
1803 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1807 if (options.useXstack)
1809 if (bitVectBitValue (rsave, R0_IDX))
1810 emitcode ("mov", "b,r0");
1811 emitcode ("mov", "r0,%s", spname);
1812 for (i = 0; i < ds390_nRegs; i++)
1814 if (bitVectBitValue (rsave, i))
1817 emitcode ("mov", "a,b");
1819 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1820 emitcode ("movx", "@r0,a");
1821 emitcode ("inc", "r0");
1824 emitcode ("mov", "%s,r0", spname);
1825 if (bitVectBitValue (rsave, R0_IDX))
1826 emitcode ("mov", "r0,b");
1829 for (i = 0; i < ds390_nRegs; i++)
1831 if (bitVectBitValue (rsave, i))
1832 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1835 detype = getSpec (operandType (IC_LEFT (ic)));
1838 /*-----------------------------------------------------------------*/
1839 /* unsaveRegisters - pop the pushed registers */
1840 /*-----------------------------------------------------------------*/
1842 unsaveRegisters (iCode * ic)
1846 /* find the registers in use at this time
1847 and push them away to safety */
1848 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1851 if (options.useXstack)
1853 emitcode ("mov", "r0,%s", spname);
1854 for (i = ds390_nRegs; i >= 0; i--)
1856 if (bitVectBitValue (rsave, i))
1858 emitcode ("dec", "r0");
1859 emitcode ("movx", "a,@r0");
1861 emitcode ("mov", "b,a");
1863 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1867 emitcode ("mov", "%s,r0", spname);
1868 if (bitVectBitValue (rsave, R0_IDX))
1869 emitcode ("mov", "r0,b");
1872 for (i = ds390_nRegs; i >= 0; i--)
1874 if (bitVectBitValue (rsave, i))
1875 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1881 /*-----------------------------------------------------------------*/
1883 /*-----------------------------------------------------------------*/
1885 pushSide (operand * oper, int size)
1888 _startLazyDPSEvaluation ();
1891 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1892 if (AOP_TYPE (oper) != AOP_REG &&
1893 AOP_TYPE (oper) != AOP_DIR &&
1896 emitcode ("mov", "a,%s", l);
1897 emitcode ("push", "acc");
1900 emitcode ("push", "%s", l);
1902 _endLazyDPSEvaluation ();
1905 /*-----------------------------------------------------------------*/
1906 /* assignResultValue - */
1907 /*-----------------------------------------------------------------*/
1909 assignResultValue (operand * oper)
1912 int size = AOP_SIZE (oper);
1914 _startLazyDPSEvaluation ();
1917 aopPut (AOP (oper), fReturn[offset], offset);
1920 _endLazyDPSEvaluation ();
1924 /*-----------------------------------------------------------------*/
1925 /* genXpush - pushes onto the external stack */
1926 /*-----------------------------------------------------------------*/
1928 genXpush (iCode * ic)
1930 asmop *aop = newAsmop (0);
1932 int size, offset = 0;
1934 D (emitcode (";", "genXpush ");
1937 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1938 r = getFreePtr (ic, &aop, FALSE);
1941 emitcode ("mov", "%s,_spx", r->name);
1943 size = AOP_SIZE (IC_LEFT (ic));
1944 _startLazyDPSEvaluation ();
1948 char *l = aopGet (AOP (IC_LEFT (ic)),
1949 offset++, FALSE, FALSE, TRUE);
1951 emitcode ("movx", "@%s,a", r->name);
1952 emitcode ("inc", "%s", r->name);
1955 _endLazyDPSEvaluation ();
1958 emitcode ("mov", "_spx,%s", r->name);
1960 freeAsmop (NULL, aop, ic, TRUE);
1961 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1964 /*-----------------------------------------------------------------*/
1965 /* genIpush - genrate code for pushing this gets a little complex */
1966 /*-----------------------------------------------------------------*/
1968 genIpush (iCode * ic)
1970 int size, offset = 0;
1973 D (emitcode (";", "genIpush ");
1976 /* if this is not a parm push : ie. it is spill push
1977 and spill push is always done on the local stack */
1981 /* and the item is spilt then do nothing */
1982 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1985 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1986 size = AOP_SIZE (IC_LEFT (ic));
1987 /* push it on the stack */
1988 _startLazyDPSEvaluation ();
1991 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1997 emitcode ("push", "%s", l);
1999 _endLazyDPSEvaluation ();
2003 /* this is a paramter push: in this case we call
2004 the routine to find the call and save those
2005 registers that need to be saved */
2008 /* if use external stack then call the external
2009 stack pushing routine */
2010 if (options.useXstack)
2016 /* then do the push */
2017 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2019 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2020 size = AOP_SIZE (IC_LEFT (ic));
2022 _startLazyDPSEvaluation ();
2025 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2026 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2027 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2030 emitcode ("mov", "a,%s", l);
2031 emitcode ("push", "acc");
2034 emitcode ("push", "%s", l);
2036 _endLazyDPSEvaluation ();
2038 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2041 /*-----------------------------------------------------------------*/
2042 /* genIpop - recover the registers: can happen only for spilling */
2043 /*-----------------------------------------------------------------*/
2045 genIpop (iCode * ic)
2049 D (emitcode (";", "genIpop ");
2053 /* if the temp was not pushed then */
2054 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2057 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2058 size = AOP_SIZE (IC_LEFT (ic));
2059 offset = (size - 1);
2060 _startLazyDPSEvaluation ();
2063 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2064 FALSE, TRUE, TRUE));
2066 _endLazyDPSEvaluation ();
2068 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2071 /*-----------------------------------------------------------------*/
2072 /* unsaveRBank - restores the resgister bank from stack */
2073 /*-----------------------------------------------------------------*/
2075 unsaveRBank (int bank, iCode * ic, bool popPsw)
2081 if (options.useXstack)
2085 /* Assume r0 is available for use. */
2086 r = ds390_regWithIdx (R0_IDX);;
2091 r = getFreePtr (ic, &aop, FALSE);
2093 emitcode ("mov", "%s,_spx", r->name);
2098 if (options.useXstack)
2100 emitcode ("movx", "a,@%s", r->name);
2101 emitcode ("mov", "psw,a");
2102 emitcode ("dec", "%s", r->name);
2106 emitcode ("pop", "psw");
2110 for (i = (ds390_nRegs - 1); i >= 0; i--)
2112 if (options.useXstack)
2114 emitcode ("movx", "a,@%s", r->name);
2115 emitcode ("mov", "(%s+%d),a",
2116 regs390[i].base, 8 * bank + regs390[i].offset);
2117 emitcode ("dec", "%s", r->name);
2121 emitcode ("pop", "(%s+%d)",
2122 regs390[i].base, 8 * bank + regs390[i].offset);
2125 if (options.useXstack)
2127 emitcode ("mov", "_spx,%s", r->name);
2132 freeAsmop (NULL, aop, ic, TRUE);
2136 /*-----------------------------------------------------------------*/
2137 /* saveRBank - saves an entire register bank on the stack */
2138 /*-----------------------------------------------------------------*/
2140 saveRBank (int bank, iCode * ic, bool pushPsw)
2146 if (options.useXstack)
2150 /* Assume r0 is available for use. */
2151 r = ds390_regWithIdx (R0_IDX);;
2156 r = getFreePtr (ic, &aop, FALSE);
2158 emitcode ("mov", "%s,_spx", r->name);
2161 for (i = 0; i < ds390_nRegs; i++)
2163 if (options.useXstack)
2165 emitcode ("inc", "%s", r->name);
2166 emitcode ("mov", "a,(%s+%d)",
2167 regs390[i].base, 8 * bank + regs390[i].offset);
2168 emitcode ("movx", "@%s,a", r->name);
2171 emitcode ("push", "(%s+%d)",
2172 regs390[i].base, 8 * bank + regs390[i].offset);
2177 if (options.useXstack)
2179 emitcode ("mov", "a,psw");
2180 emitcode ("movx", "@%s,a", r->name);
2181 emitcode ("inc", "%s", r->name);
2182 emitcode ("mov", "_spx,%s", r->name);
2186 emitcode ("push", "psw");
2189 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2194 freeAsmop (NULL, aop, ic, TRUE);
2203 /*-----------------------------------------------------------------*/
2204 /* genCall - generates a call statement */
2205 /*-----------------------------------------------------------------*/
2207 genCall (iCode * ic)
2210 bool restoreBank = FALSE;
2211 bool swapBanks = FALSE;
2213 D (emitcode (";", "genCall "););
2215 /* if we are calling a not _naked function that is not using
2216 the same register bank then we need to save the
2217 destination registers on the stack */
2218 dtype = operandType (IC_LEFT (ic));
2219 if (dtype && !IFFUNC_ISNAKED(dtype) &&
2220 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2221 IFFUNC_ISISR (currFunc->type))
2225 /* This is unexpected; the bank should have been saved in
2228 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2234 /* if caller saves & we have not saved then */
2238 /* if send set is not empty the assign */
2239 /* We've saved all the registers we care about;
2240 * therefore, we may clobber any register not used
2241 * in the calling convention (i.e. anything not in
2248 for (sic = setFirstItem (_G.sendSet); sic;
2249 sic = setNextItem (_G.sendSet))
2251 int size, offset = 0;
2253 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2254 size = AOP_SIZE (IC_LEFT (sic));
2256 _startLazyDPSEvaluation ();
2259 char *l = aopGet (AOP(IC_LEFT(sic)), offset,
2260 FALSE, FALSE, TRUE);
2261 if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size)
2263 emitcode("mov", "%s,%s", regs390[offset].name, l);
2265 else if (strcmp (l, fReturn[offset]))
2267 emitcode ("mov", "%s,%s",
2273 _endLazyDPSEvaluation ();
2274 if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR)
2276 size = AOP_SIZE (IC_LEFT (sic));
2284 emitcode("mov", "%s,%s",
2285 fReturn[size], regs390[size].name);
2288 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2295 emitcode ("mov", "psw,#0x%02x",
2296 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2300 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2301 OP_SYMBOL (IC_LEFT (ic))->rname :
2302 OP_SYMBOL (IC_LEFT (ic))->name));
2306 emitcode ("mov", "psw,#0x%02x",
2307 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2310 /* if we need assign a result value */
2311 if ((IS_ITEMP (IC_RESULT (ic)) &&
2312 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2313 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2314 IS_TRUE_SYMOP (IC_RESULT (ic)))
2316 if (isOperandInFarSpace (IC_RESULT (ic))
2317 && getSize (operandType (IC_RESULT (ic))) <= 2)
2319 int size = getSize (operandType (IC_RESULT (ic)));
2321 /* Special case for 1 or 2 byte return in far space. */
2325 emitcode ("mov", "b,%s", fReturn[1]);
2328 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2329 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2333 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2335 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2340 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2343 assignResultValue (IC_RESULT (ic));
2345 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2349 /* adjust the stack for parameters if
2354 if (ic->parmBytes > 3)
2356 emitcode ("mov", "a,%s", spname);
2357 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2358 emitcode ("mov", "%s,a", spname);
2361 for (i = 0; i < ic->parmBytes; i++)
2362 emitcode ("dec", "%s", spname);
2365 /* if we hade saved some registers then unsave them */
2366 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2367 unsaveRegisters (ic);
2369 /* if register bank was saved then pop them */
2371 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2374 /*-----------------------------------------------------------------*/
2375 /* genPcall - generates a call by pointer statement */
2376 /*-----------------------------------------------------------------*/
2378 genPcall (iCode * ic)
2381 symbol *rlbl = newiTempLabel (NULL);
2382 bool restoreBank=FALSE;
2384 D (emitcode (";", "genPcall ");
2388 /* if caller saves & we have not saved then */
2392 /* if we are calling a function that is not using
2393 the same register bank then we need to save the
2394 destination registers on the stack */
2395 dtype = operandType (IC_LEFT (ic));
2396 if (dtype && !IFFUNC_ISNAKED(dtype) &&
2397 IFFUNC_ISISR (currFunc->type) &&
2398 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2399 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2403 /* push the return address on to the stack */
2404 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2405 emitcode ("push", "acc");
2406 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2407 emitcode ("push", "acc");
2409 if (options.model == MODEL_FLAT24)
2411 emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2412 emitcode ("push", "acc");
2415 /* now push the calling address */
2416 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2418 pushSide (IC_LEFT (ic), FPTRSIZE);
2420 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2422 /* if send set is not empty the assign */
2427 for (sic = setFirstItem (_G.sendSet); sic;
2428 sic = setNextItem (_G.sendSet))
2430 int size, offset = 0;
2432 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2433 size = AOP_SIZE (IC_LEFT (sic));
2434 _startLazyDPSEvaluation ();
2437 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2438 FALSE, FALSE, TRUE);
2439 if (strcmp (l, fReturn[offset]))
2441 emitcode ("mov", "%s,%s",
2447 _endLazyDPSEvaluation ();
2448 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2453 emitcode ("ret", "");
2454 emitcode ("", "%05d$:", (rlbl->key + 100));
2457 /* if we need assign a result value */
2458 if ((IS_ITEMP (IC_RESULT (ic)) &&
2459 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2460 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2461 IS_TRUE_SYMOP (IC_RESULT (ic)))
2465 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2468 assignResultValue (IC_RESULT (ic));
2470 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2473 /* adjust the stack for parameters if
2478 if (ic->parmBytes > 3)
2480 emitcode ("mov", "a,%s", spname);
2481 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2482 emitcode ("mov", "%s,a", spname);
2485 for (i = 0; i < ic->parmBytes; i++)
2486 emitcode ("dec", "%s", spname);
2490 /* if register bank was saved then unsave them */
2492 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2494 /* if we hade saved some registers then
2496 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2497 unsaveRegisters (ic);
2501 /*-----------------------------------------------------------------*/
2502 /* resultRemat - result is rematerializable */
2503 /*-----------------------------------------------------------------*/
2505 resultRemat (iCode * ic)
2507 if (SKIP_IC (ic) || ic->op == IFX)
2510 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2512 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2513 if (sym->remat && !POINTER_SET (ic))
2520 #if defined(__BORLANDC__) || defined(_MSC_VER)
2521 #define STRCASECMP stricmp
2523 #define STRCASECMP strcasecmp
2526 /*-----------------------------------------------------------------*/
2527 /* inExcludeList - return 1 if the string is in exclude Reg list */
2528 /*-----------------------------------------------------------------*/
2530 inExcludeList (char *s)
2534 if (options.excludeRegs[i] &&
2535 STRCASECMP (options.excludeRegs[i], "none") == 0)
2538 for (i = 0; options.excludeRegs[i]; i++)
2540 if (options.excludeRegs[i] &&
2541 STRCASECMP (s, options.excludeRegs[i]) == 0)
2547 /*-----------------------------------------------------------------*/
2548 /* genFunction - generated code for function entry */
2549 /*-----------------------------------------------------------------*/
2551 genFunction (iCode * ic)
2555 bool switchedPSW = FALSE;
2557 D (emitcode (";", "genFunction "););
2560 /* create the function header */
2561 emitcode (";", "-----------------------------------------");
2562 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2563 emitcode (";", "-----------------------------------------");
2565 emitcode ("", "%s:", sym->rname);
2566 ftype = operandType (IC_LEFT (ic));
2568 if (IFFUNC_ISNAKED(ftype))
2570 emitcode(";", "naked function: no prologue.");
2574 /* if critical function then turn interrupts off */
2575 if (IFFUNC_ISCRITICAL (ftype))
2576 emitcode ("clr", "ea");
2578 /* here we need to generate the equates for the
2579 register bank if required */
2580 if (FUNC_REGBANK (ftype) != rbank)
2584 rbank = FUNC_REGBANK (ftype);
2585 for (i = 0; i < ds390_nRegs; i++)
2587 if (strcmp (regs390[i].base, "0") == 0)
2588 emitcode ("", "%s = 0x%02x",
2590 8 * rbank + regs390[i].offset);
2592 emitcode ("", "%s = %s + 0x%02x",
2595 8 * rbank + regs390[i].offset);
2599 /* if this is an interrupt service routine then
2600 save acc, b, dpl, dph */
2601 if (IFFUNC_ISISR (sym->type))
2604 if (!inExcludeList ("acc"))
2605 emitcode ("push", "acc");
2606 if (!inExcludeList ("b"))
2607 emitcode ("push", "b");
2608 if (!inExcludeList ("dpl"))
2609 emitcode ("push", "dpl");
2610 if (!inExcludeList ("dph"))
2611 emitcode ("push", "dph");
2612 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2614 emitcode ("push", "dpx");
2615 /* Make sure we're using standard DPTR */
2616 emitcode ("push", "dps");
2617 emitcode ("mov", "dps, #0x00");
2618 if (options.stack10bit)
2620 /* This ISR could conceivably use DPTR2. Better save it. */
2621 emitcode ("push", "dpl1");
2622 emitcode ("push", "dph1");
2623 emitcode ("push", "dpx1");
2624 emitcode ("push", DP2_RESULT_REG);
2627 /* if this isr has no bank i.e. is going to
2628 run with bank 0 , then we need to save more
2630 if (!FUNC_REGBANK (sym->type))
2633 /* if this function does not call any other
2634 function then we can be economical and
2635 save only those registers that are used */
2636 if (!IFFUNC_HASFCALL(sym->type))
2640 /* if any registers used */
2643 /* save the registers used */
2644 for (i = 0; i < sym->regsUsed->size; i++)
2646 if (bitVectBitValue (sym->regsUsed, i) ||
2647 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2648 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2655 /* this function has a function call cannot
2656 determines register usage so we will have to push the
2658 saveRBank (0, ic, FALSE);
2663 /* This ISR uses a non-zero bank.
2665 * We assume that the bank is available for our
2668 * However, if this ISR calls a function which uses some
2669 * other bank, we must save that bank entirely.
2671 unsigned long banksToSave = 0;
2673 if (IFFUNC_HASFCALL(sym->type))
2676 #define MAX_REGISTER_BANKS 4
2681 for (i = ic; i; i = i->next)
2683 if (i->op == ENDFUNCTION)
2685 /* we got to the end OK. */
2693 dtype = operandType (IC_LEFT(i));
2695 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2697 /* Mark this bank for saving. */
2698 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2700 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2704 banksToSave |= (1 << FUNC_REGBANK(dtype));
2707 /* And note that we don't need to do it in
2715 /* This is a mess; we have no idea what
2716 * register bank the called function might
2719 * The only thing I can think of to do is
2720 * throw a warning and hope.
2722 werror(W_FUNCPTR_IN_USING_ISR);
2726 if (banksToSave && options.useXstack)
2728 /* Since we aren't passing it an ic,
2729 * saveRBank will assume r0 is available to abuse.
2731 * So switch to our (trashable) bank now, so
2732 * the caller's R0 isn't trashed.
2734 emitcode ("push", "psw");
2735 emitcode ("mov", "psw,#0x%02x",
2736 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2740 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2742 if (banksToSave & (1 << ix))
2744 saveRBank(ix, NULL, FALSE);
2748 // jwk: this needs a closer look
2749 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2754 /* if callee-save to be used for this function
2755 then save the registers being used in this function */
2756 if (IFFUNC_CALLEESAVES(sym->type))
2760 /* if any registers used */
2763 /* save the registers used */
2764 for (i = 0; i < sym->regsUsed->size; i++)
2766 if (bitVectBitValue (sym->regsUsed, i) ||
2767 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2769 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2777 /* set the register bank to the desired value */
2778 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2781 emitcode ("push", "psw");
2782 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2785 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2788 if (options.useXstack)
2790 emitcode ("mov", "r0,%s", spname);
2791 emitcode ("mov", "a,_bp");
2792 emitcode ("movx", "@r0,a");
2793 emitcode ("inc", "%s", spname);
2797 /* set up the stack */
2798 emitcode ("push", "_bp"); /* save the callers stack */
2800 emitcode ("mov", "_bp,%s", spname);
2803 /* adjust the stack for the function */
2809 werror (W_STACK_OVERFLOW, sym->name);
2811 if (i > 3 && sym->recvSize < 4)
2814 emitcode ("mov", "a,sp");
2815 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2816 emitcode ("mov", "sp,a");
2821 emitcode ("inc", "sp");
2827 emitcode ("mov", "a,_spx");
2828 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2829 emitcode ("mov", "_spx,a");
2834 /*-----------------------------------------------------------------*/
2835 /* genEndFunction - generates epilogue for functions */
2836 /*-----------------------------------------------------------------*/
2838 genEndFunction (iCode * ic)
2840 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2842 D (emitcode (";", "genEndFunction "););
2844 if (IFFUNC_ISNAKED(sym->type))
2846 emitcode(";", "naked function: no epilogue.");
2850 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2852 emitcode ("mov", "%s,_bp", spname);
2855 /* if use external stack but some variables were
2856 added to the local stack then decrement the
2858 if (options.useXstack && sym->stack)
2860 emitcode ("mov", "a,sp");
2861 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2862 emitcode ("mov", "sp,a");
2866 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2868 if (options.useXstack)
2870 emitcode ("mov", "r0,%s", spname);
2871 emitcode ("movx", "a,@r0");
2872 emitcode ("mov", "_bp,a");
2873 emitcode ("dec", "%s", spname);
2877 emitcode ("pop", "_bp");
2881 /* restore the register bank */
2882 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2884 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
2885 || !options.useXstack)
2887 /* Special case of ISR using non-zero bank with useXstack
2890 emitcode ("pop", "psw");
2894 if (IFFUNC_ISISR (sym->type))
2897 /* now we need to restore the registers */
2898 /* if this isr has no bank i.e. is going to
2899 run with bank 0 , then we need to save more
2901 if (!FUNC_REGBANK (sym->type))
2903 /* if this function does not call any other
2904 function then we can be economical and
2905 save only those registers that are used */
2906 if (!IFFUNC_HASFCALL(sym->type))
2910 /* if any registers used */
2913 /* save the registers used */
2914 for (i = sym->regsUsed->size; i >= 0; i--)
2916 if (bitVectBitValue (sym->regsUsed, i) ||
2917 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2918 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2925 /* this function has a function call cannot
2926 determines register usage so we will have to pop the
2928 unsaveRBank (0, ic, FALSE);
2933 /* This ISR uses a non-zero bank.
2935 * Restore any register banks saved by genFunction
2938 // jwk: this needs a closer look
2939 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2942 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2944 if (savedBanks & (1 << ix))
2946 unsaveRBank(ix, NULL, FALSE);
2950 if (options.useXstack)
2952 /* Restore bank AFTER calling unsaveRBank,
2953 * since it can trash r0.
2955 emitcode ("pop", "psw");
2959 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2961 if (options.stack10bit)
2963 emitcode ("pop", DP2_RESULT_REG);
2964 emitcode ("pop", "dpx1");
2965 emitcode ("pop", "dph1");
2966 emitcode ("pop", "dpl1");
2968 emitcode ("pop", "dps");
2969 emitcode ("pop", "dpx");
2971 if (!inExcludeList ("dph"))
2972 emitcode ("pop", "dph");
2973 if (!inExcludeList ("dpl"))
2974 emitcode ("pop", "dpl");
2975 if (!inExcludeList ("b"))
2976 emitcode ("pop", "b");
2977 if (!inExcludeList ("acc"))
2978 emitcode ("pop", "acc");
2980 if (IFFUNC_ISCRITICAL (sym->type))
2981 emitcode ("setb", "ea");
2983 /* if debug then send end of function */
2984 if (options.debug && currFunc) {
2986 emitcode ("", "C$%s$%d$%d$%d ==.",
2987 FileBaseName (ic->filename), currFunc->lastLine,
2988 ic->level, ic->block);
2989 if (IS_STATIC (currFunc->etype))
2990 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2992 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2996 emitcode ("reti", "");
3000 if (IFFUNC_ISCRITICAL (sym->type))
3001 emitcode ("setb", "ea");
3003 if (IFFUNC_CALLEESAVES(sym->type))
3007 /* if any registers used */
3010 /* save the registers used */
3011 for (i = sym->regsUsed->size; i >= 0; i--)
3013 if (bitVectBitValue (sym->regsUsed, i) ||
3014 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3015 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3021 /* if debug then send end of function */
3022 if (options.debug && currFunc)
3025 emitcode ("", "C$%s$%d$%d$%d ==.",
3026 FileBaseName (ic->filename), currFunc->lastLine,
3027 ic->level, ic->block);
3028 if (IS_STATIC (currFunc->etype))
3029 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3031 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3035 emitcode ("ret", "");
3040 /*-----------------------------------------------------------------*/
3041 /* genRet - generate code for return statement */
3042 /*-----------------------------------------------------------------*/
3046 int size, offset = 0, pushed = 0;
3048 D (emitcode (";", "genRet ");
3051 /* if we have no return value then
3052 just generate the "ret" */
3056 /* we have something to return then
3057 move the return value into place */
3058 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
3059 size = AOP_SIZE (IC_LEFT (ic));
3061 _startLazyDPSEvaluation ();
3065 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3067 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3068 FALSE, TRUE, FALSE);
3069 emitcode ("push", "%s", l);
3074 /* Since A is the last element of fReturn,
3075 * is is OK to clobber it in the aopGet.
3077 l = aopGet (AOP (IC_LEFT (ic)), offset,
3078 FALSE, FALSE, TRUE);
3079 if (strcmp (fReturn[offset], l))
3080 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3083 _endLazyDPSEvaluation ();
3090 if (strcmp (fReturn[pushed], "a"))
3091 emitcode ("pop", fReturn[pushed]);
3093 emitcode ("pop", "acc");
3096 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3099 /* generate a jump to the return label
3100 if the next is not the return statement */
3101 if (!(ic->next && ic->next->op == LABEL &&
3102 IC_LABEL (ic->next) == returnLabel))
3104 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3108 /*-----------------------------------------------------------------*/
3109 /* genLabel - generates a label */
3110 /*-----------------------------------------------------------------*/
3112 genLabel (iCode * ic)
3114 /* special case never generate */
3115 if (IC_LABEL (ic) == entryLabel)
3118 D (emitcode (";", "genLabel ");
3121 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3124 /*-----------------------------------------------------------------*/
3125 /* genGoto - generates a ljmp */
3126 /*-----------------------------------------------------------------*/
3128 genGoto (iCode * ic)
3130 D (emitcode (";", "genGoto ");
3132 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3135 /*-----------------------------------------------------------------*/
3136 /* findLabelBackwards: walks back through the iCode chain looking */
3137 /* for the given label. Returns number of iCode instructions */
3138 /* between that label and given ic. */
3139 /* Returns zero if label not found. */
3140 /*-----------------------------------------------------------------*/
3142 findLabelBackwards (iCode * ic, int key)
3151 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3153 /* printf("findLabelBackwards = %d\n", count); */
3161 /*-----------------------------------------------------------------*/
3162 /* genPlusIncr :- does addition with increment if possible */
3163 /*-----------------------------------------------------------------*/
3165 genPlusIncr (iCode * ic)
3167 unsigned int icount;
3168 unsigned int size = getDataSize (IC_RESULT (ic));
3170 /* will try to generate an increment */
3171 /* if the right side is not a literal
3173 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3176 /* if the literal value of the right hand side
3177 is greater than 4 then it is not worth it */
3178 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3181 /* if increment 16 bits in register */
3183 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3184 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3185 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3193 /* If the next instruction is a goto and the goto target
3194 * is <= 5 instructions previous to this, we can generate
3195 * jumps straight to that target.
3197 if (ic->next && ic->next->op == GOTO
3198 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3201 emitcode (";", "tail increment optimized (range %d)", labelRange);
3202 tlbl = IC_LABEL (ic->next);
3207 tlbl = newiTempLabel (NULL);
3210 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3211 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3212 IS_AOP_PREG (IC_RESULT (ic)))
3213 emitcode ("cjne", "%s,#0x00,%05d$"
3214 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3218 emitcode ("clr", "a");
3219 emitcode ("cjne", "a,%s,%05d$"
3220 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3224 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3227 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3228 IS_AOP_PREG (IC_RESULT (ic)))
3229 emitcode ("cjne", "%s,#0x00,%05d$"
3230 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3233 emitcode ("cjne", "a,%s,%05d$"
3234 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3237 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3241 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3242 IS_AOP_PREG (IC_RESULT (ic)))
3243 emitcode ("cjne", "%s,#0x00,%05d$"
3244 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3248 emitcode ("cjne", "a,%s,%05d$"
3249 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3252 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3257 emitcode ("", "%05d$:", tlbl->key + 100);
3262 /* if the sizes are greater than 1 then we cannot */
3263 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3264 AOP_SIZE (IC_LEFT (ic)) > 1)
3267 /* we can if the aops of the left & result match or
3268 if they are in registers and the registers are the
3271 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3272 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3273 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3278 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3279 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3280 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3285 _startLazyDPSEvaluation ();
3288 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3290 _endLazyDPSEvaluation ();
3299 /*-----------------------------------------------------------------*/
3300 /* outBitAcc - output a bit in acc */
3301 /*-----------------------------------------------------------------*/
3303 outBitAcc (operand * result)
3305 symbol *tlbl = newiTempLabel (NULL);
3306 /* if the result is a bit */
3307 if (AOP_TYPE (result) == AOP_CRY)
3309 aopPut (AOP (result), "a", 0);
3313 emitcode ("jz", "%05d$", tlbl->key + 100);
3314 emitcode ("mov", "a,%s", one);
3315 emitcode ("", "%05d$:", tlbl->key + 100);
3320 /*-----------------------------------------------------------------*/
3321 /* genPlusBits - generates code for addition of two bits */
3322 /*-----------------------------------------------------------------*/
3324 genPlusBits (iCode * ic)
3326 D (emitcode (";", "genPlusBits ");
3328 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3330 symbol *lbl = newiTempLabel (NULL);
3331 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3332 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3333 emitcode ("cpl", "c");
3334 emitcode ("", "%05d$:", (lbl->key + 100));
3335 outBitC (IC_RESULT (ic));
3339 emitcode ("clr", "a");
3340 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3341 emitcode ("rlc", "a");
3342 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3343 emitcode ("addc", "a,#0x00");
3344 outAcc (IC_RESULT (ic));
3349 adjustArithmeticResult (iCode * ic)
3351 if (opIsGptr (IC_RESULT (ic)) &&
3352 opIsGptr (IC_LEFT (ic)) &&
3353 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3355 aopPut (AOP (IC_RESULT (ic)),
3356 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3360 if (opIsGptr (IC_RESULT (ic)) &&
3361 opIsGptr (IC_RIGHT (ic)) &&
3362 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3364 aopPut (AOP (IC_RESULT (ic)),
3365 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3369 if (opIsGptr (IC_RESULT (ic)) &&
3370 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3371 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3372 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3373 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3376 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3377 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3381 #if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
3382 // Please don't bring it back without a really good reason.
3383 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3384 // (because all three operands are in far space).
3385 #define AOP_OP_3(ic) \
3386 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3387 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3388 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3389 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3390 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3391 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3393 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3395 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3399 // Macro to aopOp all three operands of an ic. If this cannot be done,
3400 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3401 // will be set TRUE. The caller must then handle the case specially, noting
3402 // that the IC_RESULT operand is not aopOp'd.
3403 #define AOP_OP_3_NOFATAL(ic, rc) \
3404 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3405 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3406 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3407 isOperandInFarSpace(IC_RESULT(ic))) \
3409 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3414 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3415 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3417 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3418 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3420 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3422 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3426 // aopOp the left & right operands of an ic.
3427 #define AOP_OP_2(ic) \
3428 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3429 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3431 // convienience macro.
3432 #define AOP_SET_LOCALS(ic) \
3433 left = IC_LEFT(ic); \
3434 right = IC_RIGHT(ic); \
3435 result = IC_RESULT(ic);
3438 // Given an integer value of pushedSize bytes on the stack,
3439 // adjust it to be resultSize bytes, either by discarding
3440 // the most significant bytes or by zero-padding.
3442 // On exit from this macro, pushedSize will have been adjusted to
3443 // equal resultSize, and ACC may be trashed.
3444 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3445 /* If the pushed data is bigger than the result, \
3446 * simply discard unused bytes. Icky, but works. \
3448 while (pushedSize > resultSize) \
3450 D (emitcode (";", "discarding unused result byte."););\
3451 emitcode ("pop", "acc"); \
3454 if (pushedSize < resultSize) \
3456 emitcode ("clr", "a"); \
3457 /* Conversly, we haven't pushed enough here. \
3458 * just zero-pad, and all is well. \
3460 while (pushedSize < resultSize) \
3462 emitcode("push", "acc"); \
3466 assert(pushedSize == resultSize);
3468 /*-----------------------------------------------------------------*/
3469 /* genPlus - generates code for addition */
3470 /*-----------------------------------------------------------------*/
3472 genPlus (iCode * ic)
3474 int size, offset = 0;
3475 bool pushResult = FALSE;
3478 D (emitcode (";", "genPlus "););
3480 /* special cases :- */
3482 AOP_OP_3_NOFATAL (ic, pushResult);
3485 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3490 /* if literal, literal on the right or
3491 if left requires ACC or right is already
3493 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3494 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3495 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3497 operand *t = IC_RIGHT (ic);
3498 IC_RIGHT (ic) = IC_LEFT (ic);
3500 emitcode (";", "Swapped plus args.");
3503 /* if both left & right are in bit
3505 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3506 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3512 /* if left in bit space & right literal */
3513 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3514 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3516 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3517 /* if result in bit space */
3518 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3520 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3521 emitcode ("cpl", "c");
3522 outBitC (IC_RESULT (ic));
3526 size = getDataSize (IC_RESULT (ic));
3527 _startLazyDPSEvaluation ();
3530 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3531 emitcode ("addc", "a,#00");
3532 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3534 _endLazyDPSEvaluation ();
3539 /* if I can do an increment instead
3540 of add then GOOD for ME */
3541 if (genPlusIncr (ic) == TRUE)
3543 emitcode (";", "did genPlusIncr");
3548 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3550 _startLazyDPSEvaluation ();
3553 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3555 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3557 emitcode ("add", "a,%s",
3558 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3560 emitcode ("addc", "a,%s",
3561 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3565 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3567 /* right is going to use ACC or we would have taken the
3570 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3572 D(emitcode(";", "+ AOP_ACC special case."););
3573 emitcode("xch", "a, %s", DP2_RESULT_REG);
3575 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3578 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3581 emitcode("add", "a, %s", DP2_RESULT_REG);
3585 emitcode ("add", "a,%s",
3586 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3591 emitcode ("addc", "a,%s",
3592 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3597 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3601 emitcode ("push", "acc");
3605 _endLazyDPSEvaluation ();
3609 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3611 size = getDataSize (IC_LEFT (ic));
3612 rSize = getDataSize (IC_RESULT (ic));
3614 ADJUST_PUSHED_RESULT(size, rSize);
3616 _startLazyDPSEvaluation ();
3619 emitcode ("pop", "acc");
3620 aopPut (AOP (IC_RESULT (ic)), "a", size);
3622 _endLazyDPSEvaluation ();
3625 adjustArithmeticResult (ic);
3628 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3629 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3630 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3633 /*-----------------------------------------------------------------*/
3634 /* genMinusDec :- does subtraction with deccrement if possible */
3635 /*-----------------------------------------------------------------*/
3637 genMinusDec (iCode * ic)
3639 unsigned int icount;
3640 unsigned int size = getDataSize (IC_RESULT (ic));
3642 /* will try to generate an increment */
3643 /* if the right side is not a literal
3645 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3648 /* if the literal value of the right hand side
3649 is greater than 4 then it is not worth it */
3650 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3653 /* if decrement 16 bits in register */
3654 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3655 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3656 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3664 /* If the next instruction is a goto and the goto target
3665 * is <= 5 instructions previous to this, we can generate
3666 * jumps straight to that target.
3668 if (ic->next && ic->next->op == GOTO
3669 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3672 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3673 tlbl = IC_LABEL (ic->next);
3678 tlbl = newiTempLabel (NULL);
3682 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3683 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3684 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3685 IS_AOP_PREG (IC_RESULT (ic)))
3686 emitcode ("cjne", "%s,#0xff,%05d$"
3687 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3691 emitcode ("mov", "a,#0xff");
3692 emitcode ("cjne", "a,%s,%05d$"
3693 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3696 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3699 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3700 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3701 IS_AOP_PREG (IC_RESULT (ic)))
3702 emitcode ("cjne", "%s,#0xff,%05d$"
3703 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3707 emitcode ("cjne", "a,%s,%05d$"
3708 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3711 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3715 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3716 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3717 IS_AOP_PREG (IC_RESULT (ic)))
3718 emitcode ("cjne", "%s,#0xff,%05d$"
3719 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3723 emitcode ("cjne", "a,%s,%05d$"
3724 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3727 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3731 emitcode ("", "%05d$:", tlbl->key + 100);
3736 /* if the sizes are greater than 1 then we cannot */
3737 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3738 AOP_SIZE (IC_LEFT (ic)) > 1)
3741 /* we can if the aops of the left & result match or
3742 if they are in registers and the registers are the
3745 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3746 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3747 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3750 _startLazyDPSEvaluation ();
3753 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3755 _endLazyDPSEvaluation ();
3763 /*-----------------------------------------------------------------*/
3764 /* addSign - complete with sign */
3765 /*-----------------------------------------------------------------*/
3767 addSign (operand * result, int offset, int sign)
3769 int size = (getDataSize (result) - offset);
3772 _startLazyDPSEvaluation();
3775 emitcode ("rlc", "a");
3776 emitcode ("subb", "a,acc");
3779 aopPut (AOP (result), "a", offset++);
3786 aopPut (AOP (result), zero, offset++);
3789 _endLazyDPSEvaluation();
3793 /*-----------------------------------------------------------------*/
3794 /* genMinusBits - generates code for subtraction of two bits */
3795 /*-----------------------------------------------------------------*/
3797 genMinusBits (iCode * ic)
3799 symbol *lbl = newiTempLabel (NULL);
3801 D (emitcode (";", "genMinusBits "););
3803 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3805 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3806 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3807 emitcode ("cpl", "c");
3808 emitcode ("", "%05d$:", (lbl->key + 100));
3809 outBitC (IC_RESULT (ic));
3813 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3814 emitcode ("subb", "a,acc");
3815 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3816 emitcode ("inc", "a");
3817 emitcode ("", "%05d$:", (lbl->key + 100));
3818 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3819 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3823 /*-----------------------------------------------------------------*/
3824 /* genMinus - generates code for subtraction */
3825 /*-----------------------------------------------------------------*/
3827 genMinus (iCode * ic)
3829 int size, offset = 0;
3831 unsigned long lit = 0L;
3832 bool pushResult = FALSE;
3834 D (emitcode (";", "genMinus "););
3836 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3837 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3838 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3839 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3845 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3847 /* special cases :- */
3848 /* if both left & right are in bit space */
3849 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3850 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3856 /* if I can do an decrement instead
3857 of subtract then GOOD for ME */
3858 if (genMinusDec (ic) == TRUE)
3863 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3865 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3871 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3876 /* if literal, add a,#-lit, else normal subb */
3877 _startLazyDPSEvaluation ();
3880 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3881 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3882 emitcode ("subb", "a,%s",
3883 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3886 /* first add without previous c */
3888 if (!size && lit==-1) {
3889 emitcode ("dec", "a");
3891 emitcode ("add", "a,#0x%02x",
3892 (unsigned int) (lit & 0x0FFL));
3895 emitcode ("addc", "a,#0x%02x",
3896 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3902 emitcode ("push", "acc");
3906 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3910 _endLazyDPSEvaluation ();
3914 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3916 size = getDataSize (IC_LEFT (ic));
3917 rSize = getDataSize (IC_RESULT (ic));
3919 ADJUST_PUSHED_RESULT(size, rSize);
3921 _startLazyDPSEvaluation ();
3924 emitcode ("pop", "acc");
3925 aopPut (AOP (IC_RESULT (ic)), "a", size);
3927 _endLazyDPSEvaluation ();
3930 adjustArithmeticResult (ic);
3933 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3934 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3935 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3939 /*-----------------------------------------------------------------*/
3940 /* genMultbits :- multiplication of bits */
3941 /*-----------------------------------------------------------------*/
3943 genMultbits (operand * left,
3948 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3949 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3950 aopOp(result, ic, TRUE, FALSE);
3955 /*-----------------------------------------------------------------*/
3956 /* genMultOneByte : 8*8=8/16 bit multiplication */
3957 /*-----------------------------------------------------------------*/
3959 genMultOneByte (operand * left,
3964 sym_link *opetype = operandType (result);
3968 /* (if two literals: the value is computed before) */
3969 /* if one literal, literal on the right */
3970 if (AOP_TYPE (left) == AOP_LIT)
3975 emitcode (";", "swapped left and right");
3978 if (SPEC_USIGN(opetype)
3979 // ignore the sign of left and right, what else can we do?
3980 || (SPEC_USIGN(operandType(left)) &&
3981 SPEC_USIGN(operandType(right)))) {
3982 // just an unsigned 8*8=8/16 multiply
3983 //emitcode (";","unsigned");
3984 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3985 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3986 emitcode ("mul", "ab");
3989 aopOp(result, ic, TRUE, FALSE);
3991 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
3993 // this should never happen
3994 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3995 AOP_SIZE(result), __FILE__, lineno);
3999 aopPut (AOP (result), "a", 0);
4001 if (AOP_SIZE(result)==2)
4003 aopPut (AOP (result), "b", 1);
4008 // we have to do a signed multiply
4010 emitcode (";", "signed");
4011 emitcode ("clr", "F0"); // reset sign flag
4012 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4014 lbl=newiTempLabel(NULL);
4015 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
4016 // left side is negative, 8-bit two's complement, this fails for -128
4017 emitcode ("setb", "F0"); // set sign flag
4018 emitcode ("cpl", "a");
4019 emitcode ("inc", "a");
4021 emitcode ("", "%05d$:", lbl->key+100);
4024 if (AOP_TYPE(right)==AOP_LIT) {
4025 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4026 /* AND literal negative */
4027 if ((int) val < 0) {
4028 emitcode ("cpl", "F0"); // complement sign flag
4029 emitcode ("mov", "b,#0x%02x", -val);
4031 emitcode ("mov", "b,#0x%02x", val);
4034 lbl=newiTempLabel(NULL);
4035 emitcode ("mov", "b,a");
4036 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4037 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
4038 // right side is negative, 8-bit two's complement
4039 emitcode ("cpl", "F0"); // complement sign flag
4040 emitcode ("cpl", "a");
4041 emitcode ("inc", "a");
4042 emitcode ("", "%05d$:", lbl->key+100);
4044 emitcode ("mul", "ab");
4047 aopOp(result, ic, TRUE, FALSE);
4049 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4051 // this should never happen
4052 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4053 AOP_SIZE(result), __FILE__, lineno);
4057 lbl=newiTempLabel(NULL);
4058 emitcode ("jnb", "F0,%05d$", lbl->key+100);
4059 // only ONE op was negative, we have to do a 8/16-bit two's complement
4060 emitcode ("cpl", "a"); // lsb
4061 if (AOP_SIZE(result)==1) {
4062 emitcode ("inc", "a");
4064 emitcode ("add", "a,#1");
4065 emitcode ("xch", "a,b");
4066 emitcode ("cpl", "a"); // msb
4067 emitcode ("addc", "a,#0");
4068 emitcode ("xch", "a,b");
4071 emitcode ("", "%05d$:", lbl->key+100);
4072 aopPut (AOP (result), "a", 0);
4074 if (AOP_SIZE(result)==2) {
4075 aopPut (AOP (result), "b", 1);
4079 /*-----------------------------------------------------------------*/
4080 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4081 /*-----------------------------------------------------------------*/
4082 static void genMultTwoByte (operand *left, operand *right,
4083 operand *result, iCode *ic)
4085 sym_link *retype = getSpec(operandType(right));
4086 sym_link *letype = getSpec(operandType(left));
4087 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4090 if (AOP_TYPE (left) == AOP_LIT) {
4095 /* load up MB with right */
4097 emitcode("clr","F0");
4098 if (AOP_TYPE(right) == AOP_LIT) {
4099 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4101 emitcode("setb","F0");
4104 emitcode ("mov","mb,#0x%02x",val & 0xff);
4105 emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4107 lbl = newiTempLabel(NULL);
4108 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4109 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4110 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4111 emitcode ("xch", "a,b");
4112 emitcode ("cpl","a");
4113 emitcode ("add", "a,#1");
4114 emitcode ("xch", "a,b");
4115 emitcode ("cpl", "a"); // msb
4116 emitcode ("addc", "a,#0");
4117 emitcode ("setb","F0");
4118 emitcode ("","%05d$:",lbl->key+100);
4119 emitcode ("mov","mb,b");
4120 emitcode ("mov","mb,a");
4123 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4124 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4126 /* load up MA with left */
4128 lbl = newiTempLabel(NULL);
4129 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4130 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4131 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4132 emitcode ("xch", "a,b");
4133 emitcode ("cpl","a");
4134 emitcode ("add", "a,#1");
4135 emitcode ("xch", "a,b");
4136 emitcode ("cpl", "a"); // msb
4137 emitcode ("addc","a,#0");
4138 emitcode ("jbc","F0,%05d$",lbl->key+100);
4139 emitcode ("setb","F0");
4140 emitcode ("","%05d$:",lbl->key+100);
4141 emitcode ("mov","ma,b");
4142 emitcode ("mov","ma,a");
4144 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4145 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4147 /* wait for multiplication to finish */
4148 lbl = newiTempLabel(NULL);
4149 emitcode("","%05d$:", lbl->key+100);
4150 emitcode("mov","a,mcnt1");
4151 emitcode("anl","a,#0x80");
4152 emitcode("jnz","%05d$",lbl->key+100);
4154 freeAsmop (left, NULL, ic, TRUE);
4155 freeAsmop (right, NULL, ic,TRUE);
4156 aopOp(result, ic, TRUE, FALSE);
4158 /* if unsigned then simple */
4160 emitcode ("mov","a,ma");
4161 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4162 emitcode ("mov","a,ma");
4163 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4164 aopPut(AOP(result),"ma",1);
4165 aopPut(AOP(result),"ma",0);
4167 emitcode("push","ma");
4168 emitcode("push","ma");
4169 emitcode("push","ma");
4171 /* negate result if needed */
4172 lbl = newiTempLabel(NULL);
4173 emitcode("jnb","F0,%05d$",lbl->key+100);
4174 emitcode("cpl","a");
4175 emitcode("add","a,#1");
4176 emitcode("","%05d$:", lbl->key+100);
4177 if (AOP_TYPE(result) == AOP_ACC)
4179 D(emitcode(";", "ACC special case."););
4180 /* We know result is the only live aop, and
4181 * it's obviously not a DPTR2, so AP is available.
4183 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4187 aopPut(AOP(result),"a",0);
4190 emitcode("pop","acc");
4191 lbl = newiTempLabel(NULL);
4192 emitcode("jnb","F0,%05d$",lbl->key+100);
4193 emitcode("cpl","a");
4194 emitcode("addc","a,#0");
4195 emitcode("","%05d$:", lbl->key+100);
4196 aopPut(AOP(result),"a",1);
4197 emitcode("pop","acc");
4198 if (AOP_SIZE(result) >= 3) {
4199 lbl = newiTempLabel(NULL);
4200 emitcode("jnb","F0,%05d$",lbl->key+100);
4201 emitcode("cpl","a");
4202 emitcode("addc","a,#0");
4203 emitcode("","%05d$:", lbl->key+100);
4204 aopPut(AOP(result),"a",2);
4206 emitcode("pop","acc");
4207 if (AOP_SIZE(result) >= 4) {
4208 lbl = newiTempLabel(NULL);
4209 emitcode("jnb","F0,%05d$",lbl->key+100);
4210 emitcode("cpl","a");
4211 emitcode("addc","a,#0");
4212 emitcode("","%05d$:", lbl->key+100);
4213 aopPut(AOP(result),"a",3);
4215 if (AOP_TYPE(result) == AOP_ACC)
4217 /* We stashed the result away above. */
4218 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4222 freeAsmop (result, NULL, ic, TRUE);
4226 /*-----------------------------------------------------------------*/
4227 /* genMult - generates code for multiplication */
4228 /*-----------------------------------------------------------------*/
4230 genMult (iCode * ic)
4232 operand *left = IC_LEFT (ic);
4233 operand *right = IC_RIGHT (ic);
4234 operand *result = IC_RESULT (ic);
4236 D (emitcode (";", "genMult "););
4238 /* assign the amsops */
4241 /* special cases first */
4243 if (AOP_TYPE (left) == AOP_CRY &&
4244 AOP_TYPE (right) == AOP_CRY)
4246 genMultbits (left, right, result, ic);
4250 /* if both are of size == 1 */
4251 if (AOP_SIZE (left) == 1 &&
4252 AOP_SIZE (right) == 1)
4254 genMultOneByte (left, right, result, ic);
4258 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4259 /* use the ds390 ARITHMETIC accel UNIT */
4260 genMultTwoByte (left, right, result, ic);
4263 /* should have been converted to function call */
4267 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4268 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4269 freeAsmop (result, NULL, ic, TRUE);
4272 /*-----------------------------------------------------------------*/
4273 /* genDivbits :- division of bits */
4274 /*-----------------------------------------------------------------*/
4276 genDivbits (operand * left,
4284 /* the result must be bit */
4285 LOAD_AB_FOR_DIV (left, right, l);
4286 emitcode ("div", "ab");
4287 emitcode ("rrc", "a");
4288 aopOp(result, ic, TRUE, FALSE);
4290 aopPut (AOP (result), "c", 0);
4293 /*-----------------------------------------------------------------*/
4294 /* genDivOneByte : 8 bit division */
4295 /*-----------------------------------------------------------------*/
4297 genDivOneByte (operand * left,
4302 sym_link *opetype = operandType (result);
4308 /* signed or unsigned */
4309 if (SPEC_USIGN (opetype))
4311 /* unsigned is easy */
4312 LOAD_AB_FOR_DIV (left, right, l);
4313 emitcode ("div", "ab");
4316 aopOp(result, ic, TRUE, FALSE);
4317 aopPut (AOP (result), "a", 0);
4320 size = AOP_SIZE (result) - 1;
4324 aopPut (AOP (result), zero, offset++);
4329 /* signed is a little bit more difficult */
4331 /* save the signs of the operands */
4332 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4334 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4335 emitcode ("push", "acc"); /* save it on the stack */
4337 /* now sign adjust for both left & right */
4338 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4340 lbl = newiTempLabel (NULL);
4341 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4342 emitcode ("cpl", "a");
4343 emitcode ("inc", "a");
4344 emitcode ("", "%05d$:", (lbl->key + 100));
4345 emitcode ("mov", "b,a");
4347 /* sign adjust left side */
4348 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4351 lbl = newiTempLabel (NULL);
4352 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4353 emitcode ("cpl", "a");
4354 emitcode ("inc", "a");
4355 emitcode ("", "%05d$:", (lbl->key + 100));
4357 /* now the division */
4358 emitcode ("nop", "; workaround for DS80C390 div bug.");
4359 emitcode ("div", "ab");
4360 /* we are interested in the lower order
4362 emitcode ("mov", "b,a");
4363 lbl = newiTempLabel (NULL);
4364 emitcode ("pop", "acc");
4365 /* if there was an over flow we don't
4366 adjust the sign of the result */
4367 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4368 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4370 emitcode ("clr", "a");
4371 emitcode ("subb", "a,b");
4372 emitcode ("mov", "b,a");
4373 emitcode ("", "%05d$:", (lbl->key + 100));
4375 /* now we are done */
4377 aopOp(result, ic, TRUE, FALSE);
4379 aopPut (AOP (result), "b", 0);
4381 size = AOP_SIZE (result) - 1;
4385 emitcode ("mov", "c,b.7");
4386 emitcode ("subb", "a,acc");
4390 aopPut (AOP (result), "a", offset++);
4396 /*-----------------------------------------------------------------*/
4397 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4398 /*-----------------------------------------------------------------*/
4399 static void genDivTwoByte (operand *left, operand *right,
4400 operand *result, iCode *ic)
4402 sym_link *retype = getSpec(operandType(right));
4403 sym_link *letype = getSpec(operandType(left));
4404 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4407 /* load up MA with left */
4409 emitcode("clr","F0");
4410 lbl = newiTempLabel(NULL);
4411 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4412 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4413 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4414 emitcode ("xch", "a,b");
4415 emitcode ("cpl","a");
4416 emitcode ("add", "a,#1");
4417 emitcode ("xch", "a,b");
4418 emitcode ("cpl", "a"); // msb
4419 emitcode ("addc","a,#0");
4420 emitcode ("setb","F0");
4421 emitcode ("","%05d$:",lbl->key+100);
4422 emitcode ("mov","ma,b");
4423 emitcode ("mov","ma,a");
4425 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4426 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4429 /* load up MB with right */
4431 if (AOP_TYPE(right) == AOP_LIT) {
4432 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4434 lbl = newiTempLabel(NULL);
4435 emitcode ("jbc","F0,%05d$",lbl->key+100);
4436 emitcode("setb","F0");
4437 emitcode ("","%05d$:",lbl->key+100);
4440 emitcode ("mov","mb,#0x%02x",val & 0xff);
4441 emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4443 lbl = newiTempLabel(NULL);
4444 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4445 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4446 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4447 emitcode ("xch", "a,b");
4448 emitcode ("cpl","a");
4449 emitcode ("add", "a,#1");
4450 emitcode ("xch", "a,b");
4451 emitcode ("cpl", "a"); // msb
4452 emitcode ("addc", "a,#0");
4453 emitcode ("jbc","F0,%05d$",lbl->key+100);
4454 emitcode ("setb","F0");
4455 emitcode ("","%05d$:",lbl->key+100);
4456 emitcode ("mov","mb,b");
4457 emitcode ("mov","mb,a");
4460 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4461 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4464 /* wait for multiplication to finish */
4465 lbl = newiTempLabel(NULL);
4466 emitcode("","%05d$:", lbl->key+100);
4467 emitcode("mov","a,mcnt1");
4468 emitcode("anl","a,#0x80");
4469 emitcode("jnz","%05d$",lbl->key+100);
4471 freeAsmop (left, NULL, ic, TRUE);
4472 freeAsmop (right, NULL, ic,TRUE);
4473 aopOp(result, ic, TRUE, FALSE);
4475 /* if unsigned then simple */
4477 aopPut(AOP(result),"ma",1);
4478 aopPut(AOP(result),"ma",0);
4480 emitcode("push","ma");
4482 /* negate result if needed */
4483 lbl = newiTempLabel(NULL);
4484 emitcode("jnb","F0,%05d$",lbl->key+100);
4485 emitcode("cpl","a");
4486 emitcode("add","a,#1");
4487 emitcode("","%05d$:", lbl->key+100);
4488 aopPut(AOP(result),"a",0);
4489 emitcode("pop","acc");
4490 lbl = newiTempLabel(NULL);
4491 emitcode("jnb","F0,%05d$",lbl->key+100);
4492 emitcode("cpl","a");
4493 emitcode("addc","a,#0");
4494 emitcode("","%05d$:", lbl->key+100);
4495 aopPut(AOP(result),"a",1);
4497 freeAsmop (result, NULL, ic, TRUE);
4501 /*-----------------------------------------------------------------*/
4502 /* genDiv - generates code for division */
4503 /*-----------------------------------------------------------------*/
4507 operand *left = IC_LEFT (ic);
4508 operand *right = IC_RIGHT (ic);
4509 operand *result = IC_RESULT (ic);
4511 D (emitcode (";", "genDiv "););
4513 /* assign the amsops */
4516 /* special cases first */
4518 if (AOP_TYPE (left) == AOP_CRY &&
4519 AOP_TYPE (right) == AOP_CRY)
4521 genDivbits (left, right, result, ic);
4525 /* if both are of size == 1 */
4526 if (AOP_SIZE (left) == 1 &&
4527 AOP_SIZE (right) == 1)
4529 genDivOneByte (left, right, result, ic);
4533 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4534 /* use the ds390 ARITHMETIC accel UNIT */
4535 genDivTwoByte (left, right, result, ic);
4538 /* should have been converted to function call */
4541 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4542 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4543 freeAsmop (result, NULL, ic, TRUE);
4546 /*-----------------------------------------------------------------*/
4547 /* genModbits :- modulus of bits */
4548 /*-----------------------------------------------------------------*/
4550 genModbits (operand * left,
4558 /* the result must be bit */
4559 LOAD_AB_FOR_DIV (left, right, l);
4560 emitcode ("div", "ab");
4561 emitcode ("mov", "a,b");
4562 emitcode ("rrc", "a");
4563 aopOp(result, ic, TRUE, FALSE);
4564 aopPut (AOP (result), "c", 0);
4567 /*-----------------------------------------------------------------*/
4568 /* genModOneByte : 8 bit modulus */
4569 /*-----------------------------------------------------------------*/
4571 genModOneByte (operand * left,
4576 sym_link *opetype = operandType (result);
4580 /* signed or unsigned */
4581 if (SPEC_USIGN (opetype))
4583 /* unsigned is easy */
4584 LOAD_AB_FOR_DIV (left, right, l);
4585 emitcode ("div", "ab");
4586 aopOp(result, ic, TRUE, FALSE);
4587 aopPut (AOP (result), "b", 0);
4591 /* signed is a little bit more difficult */
4593 /* save the signs of the operands */
4594 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4597 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4598 emitcode ("push", "acc"); /* save it on the stack */
4600 /* now sign adjust for both left & right */
4601 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4604 lbl = newiTempLabel (NULL);
4605 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4606 emitcode ("cpl", "a");
4607 emitcode ("inc", "a");
4608 emitcode ("", "%05d$:", (lbl->key + 100));
4609 emitcode ("mov", "b,a");
4611 /* sign adjust left side */
4612 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4615 lbl = newiTempLabel (NULL);
4616 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4617 emitcode ("cpl", "a");
4618 emitcode ("inc", "a");
4619 emitcode ("", "%05d$:", (lbl->key + 100));
4621 /* now the multiplication */
4622 emitcode ("nop", "; workaround for DS80C390 div bug.");
4623 emitcode ("div", "ab");
4624 /* we are interested in the lower order
4626 lbl = newiTempLabel (NULL);
4627 emitcode ("pop", "acc");
4628 /* if there was an over flow we don't
4629 adjust the sign of the result */
4630 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4631 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4633 emitcode ("clr", "a");
4634 emitcode ("subb", "a,b");
4635 emitcode ("mov", "b,a");
4636 emitcode ("", "%05d$:", (lbl->key + 100));
4638 /* now we are done */
4639 aopOp(result, ic, TRUE, FALSE);
4640 aopPut (AOP (result), "b", 0);
4644 /*-----------------------------------------------------------------*/
4645 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
4646 /*-----------------------------------------------------------------*/
4647 static void genModTwoByte (operand *left, operand *right,
4648 operand *result, iCode *ic)
4650 sym_link *retype = getSpec(operandType(right));
4651 sym_link *letype = getSpec(operandType(left));
4652 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4655 /* load up MA with left */
4657 lbl = newiTempLabel(NULL);
4658 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4659 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4660 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4661 emitcode ("xch", "a,b");
4662 emitcode ("cpl","a");
4663 emitcode ("add", "a,#1");
4664 emitcode ("xch", "a,b");
4665 emitcode ("cpl", "a"); // msb
4666 emitcode ("addc","a,#0");
4667 emitcode ("","%05d$:",lbl->key+100);
4668 emitcode ("mov","ma,b");
4669 emitcode ("mov","ma,a");
4671 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4672 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4675 /* load up MB with right */
4677 if (AOP_TYPE(right) == AOP_LIT) {
4678 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4682 emitcode ("mov","mb,#0x%02x",val & 0xff);
4683 emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4685 lbl = newiTempLabel(NULL);
4686 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4687 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4688 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4689 emitcode ("xch", "a,b");
4690 emitcode ("cpl","a");
4691 emitcode ("add", "a,#1");
4692 emitcode ("xch", "a,b");
4693 emitcode ("cpl", "a"); // msb
4694 emitcode ("addc", "a,#0");
4695 emitcode ("","%05d$:",lbl->key+100);
4696 emitcode ("mov","mb,b");
4697 emitcode ("mov","mb,a");
4700 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4701 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4704 /* wait for multiplication to finish */
4705 lbl = newiTempLabel(NULL);
4706 emitcode("","%05d$:", lbl->key+100);
4707 emitcode("mov","a,mcnt1");
4708 emitcode("anl","a,#0x80");
4709 emitcode("jnz","%05d$",lbl->key+100);
4711 freeAsmop (left, NULL, ic, TRUE);
4712 freeAsmop (right, NULL, ic,TRUE);
4713 aopOp(result, ic, TRUE, FALSE);
4715 aopPut(AOP(result),"mb",1);
4716 aopPut(AOP(result),"mb",0);
4717 freeAsmop (result, NULL, ic, TRUE);
4721 /*-----------------------------------------------------------------*/
4722 /* genMod - generates code for division */
4723 /*-----------------------------------------------------------------*/
4727 operand *left = IC_LEFT (ic);
4728 operand *right = IC_RIGHT (ic);
4729 operand *result = IC_RESULT (ic);
4731 D (emitcode (";", "genMod "); );
4733 /* assign the amsops */
4736 /* special cases first */
4738 if (AOP_TYPE (left) == AOP_CRY &&
4739 AOP_TYPE (right) == AOP_CRY)
4741 genModbits (left, right, result, ic);
4745 /* if both are of size == 1 */
4746 if (AOP_SIZE (left) == 1 &&
4747 AOP_SIZE (right) == 1)
4749 genModOneByte (left, right, result, ic);
4753 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4754 /* use the ds390 ARITHMETIC accel UNIT */
4755 genModTwoByte (left, right, result, ic);
4759 /* should have been converted to function call */
4763 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4764 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4765 freeAsmop (result, NULL, ic, TRUE);
4768 /*-----------------------------------------------------------------*/
4769 /* genIfxJump :- will create a jump depending on the ifx */
4770 /*-----------------------------------------------------------------*/
4772 genIfxJump (iCode * ic, char *jval)
4775 symbol *tlbl = newiTempLabel (NULL);
4778 D (emitcode (";", "genIfxJump ");
4781 /* if true label then we jump if condition
4785 jlbl = IC_TRUE (ic);
4786 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4787 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4791 /* false label is present */
4792 jlbl = IC_FALSE (ic);
4793 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4794 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4796 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4797 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4799 emitcode (inst, "%05d$", tlbl->key + 100);
4800 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4801 emitcode ("", "%05d$:", tlbl->key + 100);
4803 /* mark the icode as generated */
4807 /*-----------------------------------------------------------------*/
4808 /* genCmp :- greater or less than comparison */
4809 /*-----------------------------------------------------------------*/
4811 genCmp (operand * left, operand * right,
4812 iCode * ic, iCode * ifx, int sign)
4814 int size, offset = 0;
4815 unsigned long lit = 0L;
4818 D (emitcode (";", "genCmp");
4821 result = IC_RESULT (ic);
4823 /* if left & right are bit variables */
4824 if (AOP_TYPE (left) == AOP_CRY &&
4825 AOP_TYPE (right) == AOP_CRY)
4827 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4828 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4832 /* subtract right from left if at the
4833 end the carry flag is set then we know that
4834 left is greater than right */
4835 size = max (AOP_SIZE (left), AOP_SIZE (right));
4837 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4838 if ((size == 1) && !sign &&
4839 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4841 symbol *lbl = newiTempLabel (NULL);
4842 emitcode ("cjne", "%s,%s,%05d$",
4843 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4844 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4846 emitcode ("", "%05d$:", lbl->key + 100);
4850 if (AOP_TYPE (right) == AOP_LIT)
4852 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4853 /* optimize if(x < 0) or if(x >= 0) */
4862 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4864 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4865 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4867 aopOp (result, ic, FALSE, FALSE);
4869 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4871 freeAsmop (result, NULL, ic, TRUE);
4872 genIfxJump (ifx, "acc.7");
4877 emitcode ("rlc", "a");
4879 goto release_freedLR;
4887 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4888 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4889 emitcode (";", "genCmp #2");
4890 if (sign && (size == 0))
4892 emitcode (";", "genCmp #3");
4893 emitcode ("xrl", "a,#0x80");
4894 if (AOP_TYPE (right) == AOP_LIT)
4896 unsigned long lit = (unsigned long)
4897 floatFromVal (AOP (right)->aopu.aop_lit);
4898 emitcode (";", "genCmp #3.1");
4899 emitcode ("subb", "a,#0x%02x",
4900 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4904 emitcode (";", "genCmp #3.2");
4905 if (AOP_NEEDSACC (right))
4907 emitcode ("push", "acc");
4909 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4910 FALSE, FALSE, FALSE));
4911 emitcode ("xrl", "b,#0x80");
4912 if (AOP_NEEDSACC (right))
4914 emitcode ("pop", "acc");
4916 emitcode ("subb", "a,b");
4923 emitcode (";", "genCmp #4");
4924 if (AOP_NEEDSACC (right))
4927 emitcode (";", "genCmp #4.1");
4928 emitcode ("xch", "a, b");
4929 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4930 emitcode ("xch", "a, b");
4935 emitcode (";", "genCmp #4.2");
4936 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4939 emitcode ("subb", "a,%s", s);
4946 /* Don't need the left & right operands any more; do need the result. */
4947 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4948 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4950 aopOp (result, ic, FALSE, FALSE);
4954 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4960 /* if the result is used in the next
4961 ifx conditional branch then generate
4962 code a little differently */
4965 genIfxJump (ifx, "c");
4971 /* leave the result in acc */
4973 freeAsmop (result, NULL, ic, TRUE);
4976 /*-----------------------------------------------------------------*/
4977 /* genCmpGt :- greater than comparison */
4978 /*-----------------------------------------------------------------*/
4980 genCmpGt (iCode * ic, iCode * ifx)
4982 operand *left, *right;
4983 sym_link *letype, *retype;
4986 D (emitcode (";", "genCmpGt ");
4989 left = IC_LEFT (ic);
4990 right = IC_RIGHT (ic);
4992 letype = getSpec (operandType (left));
4993 retype = getSpec (operandType (right));
4994 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4996 /* assign the left & right amsops */
4999 genCmp (right, left, ic, ifx, sign);
5002 /*-----------------------------------------------------------------*/
5003 /* genCmpLt - less than comparisons */
5004 /*-----------------------------------------------------------------*/
5006 genCmpLt (iCode * ic, iCode * ifx)
5008 operand *left, *right;
5009 sym_link *letype, *retype;
5012 D (emitcode (";", "genCmpLt "););
5014 left = IC_LEFT (ic);
5015 right = IC_RIGHT (ic);
5017 letype = getSpec (operandType (left));
5018 retype = getSpec (operandType (right));
5019 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5021 /* assign the left & right amsops */
5024 genCmp (left, right, ic, ifx, sign);
5027 /*-----------------------------------------------------------------*/
5028 /* gencjneshort - compare and jump if not equal */
5029 /*-----------------------------------------------------------------*/
5031 gencjneshort (operand * left, operand * right, symbol * lbl)
5033 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5035 unsigned long lit = 0L;
5037 D (emitcode (";", "gencjneshort");
5040 /* if the left side is a literal or
5041 if the right is in a pointer register and left
5043 if ((AOP_TYPE (left) == AOP_LIT) ||
5044 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5051 if (AOP_TYPE (right) == AOP_LIT)
5052 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5054 if (opIsGptr (left) || opIsGptr (right))
5056 /* We are comparing a generic pointer to something.
5057 * Exclude the generic type byte from the comparison.
5060 D (emitcode (";", "cjneshort: generic ptr special case.");
5065 /* if the right side is a literal then anything goes */
5066 if (AOP_TYPE (right) == AOP_LIT &&
5067 AOP_TYPE (left) != AOP_DIR)
5071 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5073 emitcode ("cjne", "a,%s,%05d$",
5074 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5080 /* if the right side is in a register or in direct space or
5081 if the left is a pointer register & right is not */
5082 else if (AOP_TYPE (right) == AOP_REG ||
5083 AOP_TYPE (right) == AOP_DIR ||
5084 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5085 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5089 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5090 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5091 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5092 emitcode ("jnz", "%05d$", lbl->key + 100);
5094 emitcode ("cjne", "a,%s,%05d$",
5095 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5102 /* right is a pointer reg need both a & b */
5105 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5106 if (strcmp (l, "b"))
5107 emitcode ("mov", "b,%s", l);
5108 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5109 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5115 /*-----------------------------------------------------------------*/
5116 /* gencjne - compare and jump if not equal */
5117 /*-----------------------------------------------------------------*/
5119 gencjne (operand * left, operand * right, symbol * lbl)
5121 symbol *tlbl = newiTempLabel (NULL);
5123 D (emitcode (";", "gencjne");
5126 gencjneshort (left, right, lbl);
5128 emitcode ("mov", "a,%s", one);
5129 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5130 emitcode ("", "%05d$:", lbl->key + 100);
5131 emitcode ("clr", "a");
5132 emitcode ("", "%05d$:", tlbl->key + 100);
5135 /*-----------------------------------------------------------------*/
5136 /* genCmpEq - generates code for equal to */
5137 /*-----------------------------------------------------------------*/
5139 genCmpEq (iCode * ic, iCode * ifx)
5141 operand *left, *right, *result;
5143 D (emitcode (";", "genCmpEq ");
5147 AOP_SET_LOCALS (ic);
5149 /* if literal, literal on the right or
5150 if the right is in a pointer register and left
5152 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5153 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5155 operand *t = IC_RIGHT (ic);
5156 IC_RIGHT (ic) = IC_LEFT (ic);
5160 if (ifx && /* !AOP_SIZE(result) */
5161 OP_SYMBOL (result) &&
5162 OP_SYMBOL (result)->regType == REG_CND)
5165 /* if they are both bit variables */
5166 if (AOP_TYPE (left) == AOP_CRY &&
5167 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5169 if (AOP_TYPE (right) == AOP_LIT)
5171 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5174 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5175 emitcode ("cpl", "c");
5179 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5183 emitcode ("clr", "c");
5185 /* AOP_TYPE(right) == AOP_CRY */
5189 symbol *lbl = newiTempLabel (NULL);
5190 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5191 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5192 emitcode ("cpl", "c");
5193 emitcode ("", "%05d$:", (lbl->key + 100));
5195 /* if true label then we jump if condition
5197 tlbl = newiTempLabel (NULL);
5200 emitcode ("jnc", "%05d$", tlbl->key + 100);
5201 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5205 emitcode ("jc", "%05d$", tlbl->key + 100);
5206 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5208 emitcode ("", "%05d$:", tlbl->key + 100);
5212 tlbl = newiTempLabel (NULL);
5213 gencjneshort (left, right, tlbl);
5216 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5217 emitcode ("", "%05d$:", tlbl->key + 100);
5221 symbol *lbl = newiTempLabel (NULL);
5222 emitcode ("sjmp", "%05d$", lbl->key + 100);
5223 emitcode ("", "%05d$:", tlbl->key + 100);
5224 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5225 emitcode ("", "%05d$:", lbl->key + 100);
5228 /* mark the icode as generated */
5231 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5232 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5236 /* if they are both bit variables */
5237 if (AOP_TYPE (left) == AOP_CRY &&
5238 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5240 if (AOP_TYPE (right) == AOP_LIT)
5242 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5245 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5246 emitcode ("cpl", "c");
5250 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5254 emitcode ("clr", "c");
5256 /* AOP_TYPE(right) == AOP_CRY */
5260 symbol *lbl = newiTempLabel (NULL);
5261 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5262 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5263 emitcode ("cpl", "c");
5264 emitcode ("", "%05d$:", (lbl->key + 100));
5267 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5268 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5270 aopOp (result, ic, TRUE, FALSE);
5273 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5280 genIfxJump (ifx, "c");
5283 /* if the result is used in an arithmetic operation
5284 then put the result in place */
5289 gencjne (left, right, newiTempLabel (NULL));
5291 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5292 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5294 aopOp (result, ic, TRUE, FALSE);
5296 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5298 aopPut (AOP (result), "a", 0);
5303 genIfxJump (ifx, "a");
5306 /* if the result is used in an arithmetic operation
5307 then put the result in place */
5308 if (AOP_TYPE (result) != AOP_CRY)
5310 /* leave the result in acc */
5314 freeAsmop (result, NULL, ic, TRUE);
5317 /*-----------------------------------------------------------------*/
5318 /* ifxForOp - returns the icode containing the ifx for operand */
5319 /*-----------------------------------------------------------------*/
5321 ifxForOp (operand * op, iCode * ic)
5323 /* if true symbol then needs to be assigned */
5324 if (IS_TRUE_SYMOP (op))
5327 /* if this has register type condition and
5328 the next instruction is ifx with the same operand
5329 and live to of the operand is upto the ifx only then */
5331 ic->next->op == IFX &&
5332 IC_COND (ic->next)->key == op->key &&
5333 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5338 /*-----------------------------------------------------------------*/
5339 /* genAndOp - for && operation */
5340 /*-----------------------------------------------------------------*/
5342 genAndOp (iCode * ic)
5344 operand *left, *right, *result;
5347 D (emitcode (";", "genAndOp "););
5349 /* note here that && operations that are in an
5350 if statement are taken away by backPatchLabels
5351 only those used in arthmetic operations remain */
5353 AOP_SET_LOCALS (ic);
5355 /* if both are bit variables */
5356 if (AOP_TYPE (left) == AOP_CRY &&
5357 AOP_TYPE (right) == AOP_CRY)
5359 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5360 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5361 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5362 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5364 aopOp (result,ic,FALSE, FALSE);
5369 tlbl = newiTempLabel (NULL);
5371 emitcode ("jz", "%05d$", tlbl->key + 100);
5373 emitcode ("", "%05d$:", tlbl->key + 100);
5374 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5375 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5377 aopOp (result,ic,FALSE, FALSE);
5380 freeAsmop (result, NULL, ic, TRUE);
5384 /*-----------------------------------------------------------------*/
5385 /* genOrOp - for || operation */
5386 /*-----------------------------------------------------------------*/
5388 genOrOp (iCode * ic)
5390 operand *left, *right, *result;
5393 D (emitcode (";", "genOrOp "););
5395 /* note here that || operations that are in an
5396 if statement are taken away by backPatchLabels
5397 only those used in arthmetic operations remain */
5399 AOP_SET_LOCALS (ic);
5401 /* if both are bit variables */
5402 if (AOP_TYPE (left) == AOP_CRY &&
5403 AOP_TYPE (right) == AOP_CRY)
5405 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5406 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5407 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5408 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5410 aopOp (result,ic,FALSE, FALSE);
5416 tlbl = newiTempLabel (NULL);
5418 emitcode ("jnz", "%05d$", tlbl->key + 100);
5420 emitcode ("", "%05d$:", tlbl->key + 100);
5421 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5422 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5424 aopOp (result,ic,FALSE, FALSE);
5429 freeAsmop (result, NULL, ic, TRUE);
5432 /*-----------------------------------------------------------------*/
5433 /* isLiteralBit - test if lit == 2^n */
5434 /*-----------------------------------------------------------------*/
5436 isLiteralBit (unsigned long lit)
5438 unsigned long pw[32] =
5439 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5440 0x100L, 0x200L, 0x400L, 0x800L,
5441 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5442 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5443 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5444 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5445 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5448 for (idx = 0; idx < 32; idx++)
5454 /*-----------------------------------------------------------------*/
5455 /* continueIfTrue - */
5456 /*-----------------------------------------------------------------*/
5458 continueIfTrue (iCode * ic)
5461 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5465 /*-----------------------------------------------------------------*/
5467 /*-----------------------------------------------------------------*/
5469 jumpIfTrue (iCode * ic)
5472 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5476 /*-----------------------------------------------------------------*/
5477 /* jmpTrueOrFalse - */
5478 /*-----------------------------------------------------------------*/
5480 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5482 // ugly but optimized by peephole
5485 symbol *nlbl = newiTempLabel (NULL);
5486 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5487 emitcode ("", "%05d$:", tlbl->key + 100);
5488 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5489 emitcode ("", "%05d$:", nlbl->key + 100);
5493 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5494 emitcode ("", "%05d$:", tlbl->key + 100);
5499 // Generate code to perform a bit-wise logic operation
5500 // on two operands in far space (assumed to already have been
5501 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5502 // in far space. This requires pushing the result on the stack
5503 // then popping it into the result.
5505 genFarFarLogicOp(iCode *ic, char *logicOp)
5507 int size, resultSize, compSize;
5511 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5512 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5513 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5515 _startLazyDPSEvaluation();
5516 for (size = compSize; (size--); offset++)
5518 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5519 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5520 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5522 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5523 emitcode ("push", "acc");
5525 _endLazyDPSEvaluation();
5527 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5528 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5529 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5531 resultSize = AOP_SIZE(IC_RESULT(ic));
5533 ADJUST_PUSHED_RESULT(compSize, resultSize);
5535 _startLazyDPSEvaluation();
5538 emitcode ("pop", "acc");
5539 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5541 _endLazyDPSEvaluation();
5542 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5546 /*-----------------------------------------------------------------*/
5547 /* genAnd - code for and */
5548 /*-----------------------------------------------------------------*/
5550 genAnd (iCode * ic, iCode * ifx)
5552 operand *left, *right, *result;
5553 int size, offset = 0;
5554 unsigned long lit = 0L;
5559 D (emitcode (";", "genAnd "););
5561 AOP_OP_3_NOFATAL (ic, pushResult);
5562 AOP_SET_LOCALS (ic);
5566 genFarFarLogicOp(ic, "anl");
5571 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5573 AOP_TYPE (left), AOP_TYPE (right));
5574 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5576 AOP_SIZE (left), AOP_SIZE (right));
5579 /* if left is a literal & right is not then exchange them */
5580 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5581 #ifdef LOGIC_OPS_BROKEN
5582 || AOP_NEEDSACC (left)
5586 operand *tmp = right;
5591 /* if result = right then exchange them */
5592 if (sameRegs (AOP (result), AOP (right)))
5594 operand *tmp = right;
5599 /* if right is bit then exchange them */
5600 if (AOP_TYPE (right) == AOP_CRY &&
5601 AOP_TYPE (left) != AOP_CRY)
5603 operand *tmp = right;
5607 if (AOP_TYPE (right) == AOP_LIT)
5608 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5610 size = AOP_SIZE (result);
5613 // result = bit & yy;
5614 if (AOP_TYPE (left) == AOP_CRY)
5616 // c = bit & literal;
5617 if (AOP_TYPE (right) == AOP_LIT)
5621 if (size && sameRegs (AOP (result), AOP (left)))
5624 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5629 if (size && (AOP_TYPE (result) == AOP_CRY))
5631 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5634 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5639 emitcode ("clr", "c");
5644 if (AOP_TYPE (right) == AOP_CRY)
5647 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5648 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5653 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5655 emitcode ("rrc", "a");
5656 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5664 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5665 genIfxJump (ifx, "c");
5669 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5670 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5671 if ((AOP_TYPE (right) == AOP_LIT) &&
5672 (AOP_TYPE (result) == AOP_CRY) &&
5673 (AOP_TYPE (left) != AOP_CRY))
5675 int posbit = isLiteralBit (lit);
5680 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5683 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5689 sprintf (buffer, "acc.%d", posbit & 0x07);
5690 genIfxJump (ifx, buffer);
5697 symbol *tlbl = newiTempLabel (NULL);
5698 int sizel = AOP_SIZE (left);
5700 emitcode ("setb", "c");
5703 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5705 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5707 if ((posbit = isLiteralBit (bytelit)) != 0)
5708 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5711 if (bytelit != 0x0FFL)
5712 emitcode ("anl", "a,%s",
5713 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5714 emitcode ("jnz", "%05d$", tlbl->key + 100);
5719 // bit = left & literal
5722 emitcode ("clr", "c");
5723 emitcode ("", "%05d$:", tlbl->key + 100);
5725 // if(left & literal)
5729 jmpTrueOrFalse (ifx, tlbl);
5737 /* if left is same as result */
5738 if (sameRegs (AOP (result), AOP (left)))
5740 for (; size--; offset++)
5742 if (AOP_TYPE (right) == AOP_LIT)
5744 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5746 else if (bytelit == 0)
5747 aopPut (AOP (result), zero, offset);
5748 else if (IS_AOP_PREG (result))
5750 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5751 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5752 aopPut (AOP (result), "a", offset);
5755 emitcode ("anl", "%s,%s",
5756 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5757 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5761 if (AOP_TYPE (left) == AOP_ACC)
5762 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5765 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5766 if (IS_AOP_PREG (result))
5768 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5769 aopPut (AOP (result), "a", offset);
5773 emitcode ("anl", "%s,a",
5774 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5781 // left & result in different registers
5782 if (AOP_TYPE (result) == AOP_CRY)
5785 // if(size), result in bit
5786 // if(!size && ifx), conditional oper: if(left & right)
5787 symbol *tlbl = newiTempLabel (NULL);
5788 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5790 emitcode ("setb", "c");
5793 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5794 emitcode ("anl", "a,%s",
5795 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5797 if (AOP_TYPE(left)==AOP_ACC) {
5798 emitcode("mov", "b,a");
5799 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5800 emitcode("anl", "a,b");
5802 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5803 emitcode ("anl", "a,%s",
5804 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5807 emitcode ("jnz", "%05d$", tlbl->key + 100);
5813 emitcode ("", "%05d$:", tlbl->key + 100);
5817 jmpTrueOrFalse (ifx, tlbl);
5821 for (; (size--); offset++)
5824 // result = left & right
5825 if (AOP_TYPE (right) == AOP_LIT)
5827 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5829 aopPut (AOP (result),
5830 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5834 else if (bytelit == 0)
5836 aopPut (AOP (result), zero, offset);
5839 D (emitcode (";", "better literal AND."););
5840 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5841 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5842 FALSE, FALSE, FALSE));
5847 // faster than result <- left, anl result,right
5848 // and better if result is SFR
5849 if (AOP_TYPE (left) == AOP_ACC)
5851 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5852 FALSE, FALSE, FALSE));
5856 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
5857 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
5859 emitcode("mov", "b,a");
5863 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5864 emitcode ("anl", "a,%s", rOp);
5867 aopPut (AOP (result), "a", offset);
5873 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5874 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5875 freeAsmop (result, NULL, ic, TRUE);
5879 /*-----------------------------------------------------------------*/
5880 /* genOr - code for or */
5881 /*-----------------------------------------------------------------*/
5883 genOr (iCode * ic, iCode * ifx)
5885 operand *left, *right, *result;
5886 int size, offset = 0;
5887 unsigned long lit = 0L;
5890 D (emitcode (";", "genOr "););
5892 AOP_OP_3_NOFATAL (ic, pushResult);
5893 AOP_SET_LOCALS (ic);
5897 genFarFarLogicOp(ic, "orl");
5903 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5905 AOP_TYPE (left), AOP_TYPE (right));
5906 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5908 AOP_SIZE (left), AOP_SIZE (right));
5911 /* if left is a literal & right is not then exchange them */
5912 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5913 #ifdef LOGIC_OPS_BROKEN
5914 || AOP_NEEDSACC (left) // I think this is a net loss now.
5918 operand *tmp = right;
5923 /* if result = right then exchange them */
5924 if (sameRegs (AOP (result), AOP (right)))
5926 operand *tmp = right;
5931 /* if right is bit then exchange them */
5932 if (AOP_TYPE (right) == AOP_CRY &&
5933 AOP_TYPE (left) != AOP_CRY)
5935 operand *tmp = right;
5939 if (AOP_TYPE (right) == AOP_LIT)
5940 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5942 size = AOP_SIZE (result);
5946 if (AOP_TYPE (left) == AOP_CRY)
5948 if (AOP_TYPE (right) == AOP_LIT)
5950 // c = bit & literal;
5953 // lit != 0 => result = 1
5954 if (AOP_TYPE (result) == AOP_CRY)
5957 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5959 continueIfTrue (ifx);
5962 emitcode ("setb", "c");
5966 // lit == 0 => result = left
5967 if (size && sameRegs (AOP (result), AOP (left)))
5969 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5974 if (AOP_TYPE (right) == AOP_CRY)
5977 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5978 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5983 symbol *tlbl = newiTempLabel (NULL);
5984 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5985 emitcode ("setb", "c");
5986 emitcode ("jb", "%s,%05d$",
5987 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5989 emitcode ("jnz", "%05d$", tlbl->key + 100);
5990 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5992 jmpTrueOrFalse (ifx, tlbl);
5998 emitcode ("", "%05d$:", tlbl->key + 100);
6007 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6008 genIfxJump (ifx, "c");
6012 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6013 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6014 if ((AOP_TYPE (right) == AOP_LIT) &&
6015 (AOP_TYPE (result) == AOP_CRY) &&
6016 (AOP_TYPE (left) != AOP_CRY))
6022 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6024 continueIfTrue (ifx);
6029 // lit = 0, result = boolean(left)
6031 emitcode ("setb", "c");
6035 symbol *tlbl = newiTempLabel (NULL);
6036 emitcode ("jnz", "%05d$", tlbl->key + 100);
6038 emitcode ("", "%05d$:", tlbl->key + 100);
6042 genIfxJump (ifx, "a");
6050 /* if left is same as result */
6051 if (sameRegs (AOP (result), AOP (left)))
6053 for (; size--; offset++)
6055 if (AOP_TYPE (right) == AOP_LIT)
6057 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6063 if (IS_AOP_PREG (left))
6065 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6066 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6067 aopPut (AOP (result), "a", offset);
6071 emitcode ("orl", "%s,%s",
6072 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6073 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6079 if (AOP_TYPE (left) == AOP_ACC)
6081 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6085 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6086 if (IS_AOP_PREG (left))
6088 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6089 aopPut (AOP (result), "a", offset);
6093 emitcode ("orl", "%s,a",
6094 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6102 // left & result in different registers
6103 if (AOP_TYPE (result) == AOP_CRY)
6106 // if(size), result in bit
6107 // if(!size && ifx), conditional oper: if(left | right)
6108 symbol *tlbl = newiTempLabel (NULL);
6109 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6111 emitcode ("setb", "c");
6114 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6115 emitcode ("orl", "a,%s",
6116 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6118 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6119 emitcode ("orl", "a,%s",
6120 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6122 emitcode ("jnz", "%05d$", tlbl->key + 100);
6128 emitcode ("", "%05d$:", tlbl->key + 100);
6132 jmpTrueOrFalse (ifx, tlbl);
6136 _startLazyDPSEvaluation();
6137 for (; (size--); offset++)
6140 // result = left & right
6141 if (AOP_TYPE (right) == AOP_LIT)
6143 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6145 aopPut (AOP (result),
6146 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6150 D (emitcode (";", "better literal OR."););
6151 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6152 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6153 FALSE, FALSE, FALSE));
6158 // faster than result <- left, anl result,right
6159 // and better if result is SFR
6160 if (AOP_TYPE (left) == AOP_ACC)
6162 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6163 FALSE, FALSE, FALSE));
6167 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6169 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6171 emitcode("mov", "b,a");
6175 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6176 emitcode ("orl", "a,%s", rOp);
6179 aopPut (AOP (result), "a", offset);
6181 _endLazyDPSEvaluation();
6186 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6187 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6188 freeAsmop (result, NULL, ic, TRUE);
6191 /*-----------------------------------------------------------------*/
6192 /* genXor - code for xclusive or */
6193 /*-----------------------------------------------------------------*/
6195 genXor (iCode * ic, iCode * ifx)
6197 operand *left, *right, *result;
6198 int size, offset = 0;
6199 unsigned long lit = 0L;
6202 D (emitcode (";", "genXor "););
6204 AOP_OP_3_NOFATAL (ic, pushResult);
6205 AOP_SET_LOCALS (ic);
6209 genFarFarLogicOp(ic, "xrl");
6214 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6216 AOP_TYPE (left), AOP_TYPE (right));
6217 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6219 AOP_SIZE (left), AOP_SIZE (right));
6222 /* if left is a literal & right is not ||
6223 if left needs acc & right does not */
6224 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6225 #ifdef LOGIC_OPS_BROKEN
6226 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6230 operand *tmp = right;
6235 /* if result = right then exchange them */
6236 if (sameRegs (AOP (result), AOP (right)))
6238 operand *tmp = right;
6243 /* if right is bit then exchange them */
6244 if (AOP_TYPE (right) == AOP_CRY &&
6245 AOP_TYPE (left) != AOP_CRY)
6247 operand *tmp = right;
6251 if (AOP_TYPE (right) == AOP_LIT)
6252 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6254 size = AOP_SIZE (result);
6258 if (AOP_TYPE (left) == AOP_CRY)
6260 if (AOP_TYPE (right) == AOP_LIT)
6262 // c = bit & literal;
6265 // lit>>1 != 0 => result = 1
6266 if (AOP_TYPE (result) == AOP_CRY)
6269 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6271 continueIfTrue (ifx);
6274 emitcode ("setb", "c");
6281 // lit == 0, result = left
6282 if (size && sameRegs (AOP (result), AOP (left)))
6284 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6288 // lit == 1, result = not(left)
6289 if (size && sameRegs (AOP (result), AOP (left)))
6291 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6296 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6297 emitcode ("cpl", "c");
6306 symbol *tlbl = newiTempLabel (NULL);
6307 if (AOP_TYPE (right) == AOP_CRY)
6310 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6314 int sizer = AOP_SIZE (right);
6316 // if val>>1 != 0, result = 1
6317 emitcode ("setb", "c");
6320 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6322 // test the msb of the lsb
6323 emitcode ("anl", "a,#0xfe");
6324 emitcode ("jnz", "%05d$", tlbl->key + 100);
6328 emitcode ("rrc", "a");
6330 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6331 emitcode ("cpl", "c");
6332 emitcode ("", "%05d$:", (tlbl->key + 100));
6339 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6340 genIfxJump (ifx, "c");
6344 if (sameRegs (AOP (result), AOP (left)))
6346 /* if left is same as result */
6347 for (; size--; offset++)
6349 if (AOP_TYPE (right) == AOP_LIT)
6351 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6353 else if (IS_AOP_PREG (left))
6355 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6356 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6357 aopPut (AOP (result), "a", offset);
6360 emitcode ("xrl", "%s,%s",
6361 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6362 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6366 if (AOP_TYPE (left) == AOP_ACC)
6367 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6370 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6371 if (IS_AOP_PREG (left))
6373 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6374 aopPut (AOP (result), "a", offset);
6377 emitcode ("xrl", "%s,a",
6378 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6385 // left & result in different registers
6386 if (AOP_TYPE (result) == AOP_CRY)
6389 // if(size), result in bit
6390 // if(!size && ifx), conditional oper: if(left ^ right)
6391 symbol *tlbl = newiTempLabel (NULL);
6392 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6394 emitcode ("setb", "c");
6397 if ((AOP_TYPE (right) == AOP_LIT) &&
6398 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6400 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6404 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6405 emitcode ("xrl", "a,%s",
6406 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6408 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6409 emitcode ("xrl", "a,%s",
6410 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6413 emitcode ("jnz", "%05d$", tlbl->key + 100);
6419 emitcode ("", "%05d$:", tlbl->key + 100);
6423 jmpTrueOrFalse (ifx, tlbl);
6426 for (; (size--); offset++)
6429 // result = left & right
6430 if (AOP_TYPE (right) == AOP_LIT)
6432 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6434 aopPut (AOP (result),
6435 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6439 D (emitcode (";", "better literal XOR.");
6441 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6442 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6443 FALSE, FALSE, FALSE));
6447 // faster than result <- left, anl result,right
6448 // and better if result is SFR
6449 if (AOP_TYPE (left) == AOP_ACC)
6451 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6452 FALSE, FALSE, FALSE));
6456 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6457 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6459 emitcode("mov", "b,a");
6463 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6464 emitcode ("xrl", "a,%s", rOp);
6467 aopPut (AOP (result), "a", offset);
6472 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6473 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6474 freeAsmop (result, NULL, ic, TRUE);
6477 /*-----------------------------------------------------------------*/
6478 /* genInline - write the inline code out */
6479 /*-----------------------------------------------------------------*/
6481 genInline (iCode * ic)
6483 char *buffer, *bp, *bp1;
6485 D (emitcode (";", "genInline ");
6488 _G.inLine += (!options.asmpeep);
6490 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6491 strcpy (buffer, IC_INLINE (ic));
6493 /* emit each line as a code */
6518 /* emitcode("",buffer); */
6519 _G.inLine -= (!options.asmpeep);
6522 /*-----------------------------------------------------------------*/
6523 /* genRRC - rotate right with carry */
6524 /*-----------------------------------------------------------------*/
6528 operand *left, *result;
6529 int size, offset = 0;
6532 D (emitcode (";", "genRRC ");
6535 /* rotate right with carry */
6536 left = IC_LEFT (ic);
6537 result = IC_RESULT (ic);
6538 aopOp (left, ic, FALSE, FALSE);
6539 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6541 /* move it to the result */
6542 size = AOP_SIZE (result);
6546 _startLazyDPSEvaluation ();
6549 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6551 emitcode ("rrc", "a");
6552 if (AOP_SIZE (result) > 1)
6553 aopPut (AOP (result), "a", offset--);
6555 _endLazyDPSEvaluation ();
6557 /* now we need to put the carry into the
6558 highest order byte of the result */
6559 if (AOP_SIZE (result) > 1)
6561 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6564 emitcode ("mov", "acc.7,c");
6565 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6566 freeAsmop (left, NULL, ic, TRUE);
6567 freeAsmop (result, NULL, ic, TRUE);
6570 /*-----------------------------------------------------------------*/
6571 /* genRLC - generate code for rotate left with carry */
6572 /*-----------------------------------------------------------------*/
6576 operand *left, *result;
6577 int size, offset = 0;
6580 D (emitcode (";", "genRLC ");
6583 /* rotate right with carry */
6584 left = IC_LEFT (ic);
6585 result = IC_RESULT (ic);
6586 aopOp (left, ic, FALSE, FALSE);
6587 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6589 /* move it to the result */
6590 size = AOP_SIZE (result);
6594 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6596 emitcode ("add", "a,acc");
6597 if (AOP_SIZE (result) > 1)
6599 aopPut (AOP (result), "a", offset++);
6602 _startLazyDPSEvaluation ();
6605 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6607 emitcode ("rlc", "a");
6608 if (AOP_SIZE (result) > 1)
6609 aopPut (AOP (result), "a", offset++);
6611 _endLazyDPSEvaluation ();
6613 /* now we need to put the carry into the
6614 highest order byte of the result */
6615 if (AOP_SIZE (result) > 1)
6617 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6620 emitcode ("mov", "acc.0,c");
6621 aopPut (AOP (result), "a", 0);
6622 freeAsmop (left, NULL, ic, TRUE);
6623 freeAsmop (result, NULL, ic, TRUE);
6626 /*-----------------------------------------------------------------*/
6627 /* genGetHbit - generates code get highest order bit */
6628 /*-----------------------------------------------------------------*/
6630 genGetHbit (iCode * ic)
6632 operand *left, *result;
6633 left = IC_LEFT (ic);
6634 result = IC_RESULT (ic);
6635 aopOp (left, ic, FALSE, FALSE);
6636 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6638 D (emitcode (";", "genGetHbit ");
6641 /* get the highest order byte into a */
6642 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6643 if (AOP_TYPE (result) == AOP_CRY)
6645 emitcode ("rlc", "a");
6650 emitcode ("rl", "a");
6651 emitcode ("anl", "a,#0x01");
6656 freeAsmop (left, NULL, ic, TRUE);
6657 freeAsmop (result, NULL, ic, TRUE);
6660 /*-----------------------------------------------------------------*/
6661 /* AccRol - rotate left accumulator by known count */
6662 /*-----------------------------------------------------------------*/
6664 AccRol (int shCount)
6666 shCount &= 0x0007; // shCount : 0..7
6673 emitcode ("rl", "a");
6676 emitcode ("rl", "a");
6677 emitcode ("rl", "a");
6680 emitcode ("swap", "a");
6681 emitcode ("rr", "a");
6684 emitcode ("swap", "a");
6687 emitcode ("swap", "a");
6688 emitcode ("rl", "a");
6691 emitcode ("rr", "a");
6692 emitcode ("rr", "a");
6695 emitcode ("rr", "a");
6700 /*-----------------------------------------------------------------*/
6701 /* AccLsh - left shift accumulator by known count */
6702 /*-----------------------------------------------------------------*/
6704 AccLsh (int shCount)
6709 emitcode ("add", "a,acc");
6710 else if (shCount == 2)
6712 emitcode ("add", "a,acc");
6713 emitcode ("add", "a,acc");
6717 /* rotate left accumulator */
6719 /* and kill the lower order bits */
6720 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6725 /*-----------------------------------------------------------------*/
6726 /* AccRsh - right shift accumulator by known count */
6727 /*-----------------------------------------------------------------*/
6729 AccRsh (int shCount)
6736 emitcode ("rrc", "a");
6740 /* rotate right accumulator */
6741 AccRol (8 - shCount);
6742 /* and kill the higher order bits */
6743 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6748 #ifdef BETTER_LITERAL_SHIFT
6749 /*-----------------------------------------------------------------*/
6750 /* AccSRsh - signed right shift accumulator by known count */
6751 /*-----------------------------------------------------------------*/
6753 AccSRsh (int shCount)
6760 emitcode ("mov", "c,acc.7");
6761 emitcode ("rrc", "a");
6763 else if (shCount == 2)
6765 emitcode ("mov", "c,acc.7");
6766 emitcode ("rrc", "a");
6767 emitcode ("mov", "c,acc.7");
6768 emitcode ("rrc", "a");
6772 tlbl = newiTempLabel (NULL);
6773 /* rotate right accumulator */
6774 AccRol (8 - shCount);
6775 /* and kill the higher order bits */
6776 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6777 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6778 emitcode ("orl", "a,#0x%02x",
6779 (unsigned char) ~SRMask[shCount]);
6780 emitcode ("", "%05d$:", tlbl->key + 100);
6786 #ifdef BETTER_LITERAL_SHIFT
6787 /*-----------------------------------------------------------------*/
6788 /* shiftR1Left2Result - shift right one byte from left to result */
6789 /*-----------------------------------------------------------------*/
6791 shiftR1Left2Result (operand * left, int offl,
6792 operand * result, int offr,
6793 int shCount, int sign)
6795 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6796 /* shift right accumulator */
6801 aopPut (AOP (result), "a", offr);
6805 #ifdef BETTER_LITERAL_SHIFT
6806 /*-----------------------------------------------------------------*/
6807 /* shiftL1Left2Result - shift left one byte from left to result */
6808 /*-----------------------------------------------------------------*/
6810 shiftL1Left2Result (operand * left, int offl,
6811 operand * result, int offr, int shCount)
6813 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6814 /* shift left accumulator */
6816 aopPut (AOP (result), "a", offr);
6820 #ifdef BETTER_LITERAL_SHIFT
6821 /*-----------------------------------------------------------------*/
6822 /* movLeft2Result - move byte from left to result */
6823 /*-----------------------------------------------------------------*/
6825 movLeft2Result (operand * left, int offl,
6826 operand * result, int offr, int sign)
6829 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6831 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6833 if (*l == '@' && (IS_AOP_PREG (result)))
6835 emitcode ("mov", "a,%s", l);
6836 aopPut (AOP (result), "a", offr);
6842 aopPut (AOP (result), l, offr);
6846 /* MSB sign in acc.7 ! */
6847 if (getDataSize (left) == offl + 1)
6849 emitcode ("mov", "a,%s", l);
6850 aopPut (AOP (result), "a", offr);
6858 #ifdef BETTER_LITERAL_SHIFT
6859 /*-----------------------------------------------------------------*/
6860 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6861 /*-----------------------------------------------------------------*/
6865 emitcode ("rrc", "a");
6866 emitcode ("xch", "a,%s", x);
6867 emitcode ("rrc", "a");
6868 emitcode ("xch", "a,%s", x);
6872 #ifdef BETTER_LITERAL_SHIFT
6874 /*-----------------------------------------------------------------*/
6875 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6876 /*-----------------------------------------------------------------*/
6880 emitcode ("xch", "a,%s", x);
6881 emitcode ("rlc", "a");
6882 emitcode ("xch", "a,%s", x);
6883 emitcode ("rlc", "a");
6887 #ifdef BETTER_LITERAL_SHIFT
6888 /*-----------------------------------------------------------------*/
6889 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6890 /*-----------------------------------------------------------------*/
6894 emitcode ("xch", "a,%s", x);
6895 emitcode ("add", "a,acc");
6896 emitcode ("xch", "a,%s", x);
6897 emitcode ("rlc", "a");
6901 #ifdef BETTER_LITERAL_SHIFT
6902 /*-----------------------------------------------------------------*/
6903 /* AccAXLsh - left shift a:x by known count (0..7) */
6904 /*-----------------------------------------------------------------*/
6906 AccAXLsh (char *x, int shCount)
6921 case 5: // AAAAABBB:CCCCCDDD
6923 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6925 emitcode ("anl", "a,#0x%02x",
6926 SLMask[shCount]); // BBB00000:CCCCCDDD
6928 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6930 AccRol (shCount); // DDDCCCCC:BBB00000
6932 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6934 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6936 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6938 emitcode ("anl", "a,#0x%02x",
6939 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6941 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6943 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6946 case 6: // AAAAAABB:CCCCCCDD
6947 emitcode ("anl", "a,#0x%02x",
6948 SRMask[shCount]); // 000000BB:CCCCCCDD
6949 emitcode ("mov", "c,acc.0"); // c = B
6950 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6952 AccAXRrl1 (x); // BCCCCCCD:D000000B
6953 AccAXRrl1 (x); // BBCCCCCC:DD000000
6955 emitcode("rrc","a");
6956 emitcode("xch","a,%s", x);
6957 emitcode("rrc","a");
6958 emitcode("mov","c,acc.0"); //<< get correct bit
6959 emitcode("xch","a,%s", x);
6961 emitcode("rrc","a");
6962 emitcode("xch","a,%s", x);
6963 emitcode("rrc","a");
6964 emitcode("xch","a,%s", x);
6967 case 7: // a:x <<= 7
6969 emitcode ("anl", "a,#0x%02x",
6970 SRMask[shCount]); // 0000000B:CCCCCCCD
6972 emitcode ("mov", "c,acc.0"); // c = B
6974 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6976 AccAXRrl1 (x); // BCCCCCCC:D0000000
6985 #ifdef BETTER_LITERAL_SHIFT
6987 /*-----------------------------------------------------------------*/
6988 /* AccAXRsh - right shift a:x known count (0..7) */
6989 /*-----------------------------------------------------------------*/
6991 AccAXRsh (char *x, int shCount)
6999 AccAXRrl1 (x); // 0->a:x
7004 AccAXRrl1 (x); // 0->a:x
7007 AccAXRrl1 (x); // 0->a:x
7012 case 5: // AAAAABBB:CCCCCDDD = a:x
7014 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7016 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7018 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7020 emitcode ("anl", "a,#0x%02x",
7021 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7023 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7025 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7027 emitcode ("anl", "a,#0x%02x",
7028 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7030 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7032 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7034 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7037 case 6: // AABBBBBB:CCDDDDDD
7039 emitcode ("mov", "c,acc.7");
7040 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7042 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7044 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7046 emitcode ("anl", "a,#0x%02x",
7047 SRMask[shCount]); // 000000AA:BBBBBBCC
7050 case 7: // ABBBBBBB:CDDDDDDD
7052 emitcode ("mov", "c,acc.7"); // c = A
7054 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7056 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7058 emitcode ("anl", "a,#0x%02x",
7059 SRMask[shCount]); // 0000000A:BBBBBBBC
7068 #ifdef BETTER_LITERAL_SHIFT
7069 /*-----------------------------------------------------------------*/
7070 /* AccAXRshS - right shift signed a:x known count (0..7) */
7071 /*-----------------------------------------------------------------*/
7073 AccAXRshS (char *x, int shCount)
7081 emitcode ("mov", "c,acc.7");
7082 AccAXRrl1 (x); // s->a:x
7086 emitcode ("mov", "c,acc.7");
7087 AccAXRrl1 (x); // s->a:x
7089 emitcode ("mov", "c,acc.7");
7090 AccAXRrl1 (x); // s->a:x
7095 case 5: // AAAAABBB:CCCCCDDD = a:x
7097 tlbl = newiTempLabel (NULL);
7098 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7100 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7102 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7104 emitcode ("anl", "a,#0x%02x",
7105 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7107 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7109 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7111 emitcode ("anl", "a,#0x%02x",
7112 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7114 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7116 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7118 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7120 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7121 emitcode ("orl", "a,#0x%02x",
7122 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7124 emitcode ("", "%05d$:", tlbl->key + 100);
7125 break; // SSSSAAAA:BBBCCCCC
7127 case 6: // AABBBBBB:CCDDDDDD
7129 tlbl = newiTempLabel (NULL);
7130 emitcode ("mov", "c,acc.7");
7131 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7133 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7135 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7137 emitcode ("anl", "a,#0x%02x",
7138 SRMask[shCount]); // 000000AA:BBBBBBCC
7140 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7141 emitcode ("orl", "a,#0x%02x",
7142 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7144 emitcode ("", "%05d$:", tlbl->key + 100);
7146 case 7: // ABBBBBBB:CDDDDDDD
7148 tlbl = newiTempLabel (NULL);
7149 emitcode ("mov", "c,acc.7"); // c = A
7151 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7153 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7155 emitcode ("anl", "a,#0x%02x",
7156 SRMask[shCount]); // 0000000A:BBBBBBBC
7158 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7159 emitcode ("orl", "a,#0x%02x",
7160 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7162 emitcode ("", "%05d$:", tlbl->key + 100);
7170 #ifdef BETTER_LITERAL_SHIFT
7172 _loadLeftIntoAx(char **lsb,
7178 // Get the initial value from left into a pair of registers.
7179 // MSB must be in A, LSB can be any register.
7181 // If the result is held in registers, it is an optimization
7182 // if the LSB can be held in the register which will hold the,
7183 // result LSB since this saves us from having to copy it into
7184 // the result following AccAXLsh.
7186 // If the result is addressed indirectly, this is not a gain.
7187 if (AOP_NEEDSACC(result))
7191 _startLazyDPSEvaluation();
7192 if (AOP_TYPE(left) == AOP_DPTR2)
7195 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7196 // get LSB in DP2_RESULT_REG.
7197 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7198 assert(!strcmp(leftByte, DP2_RESULT_REG));
7202 // get LSB into DP2_RESULT_REG
7203 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7204 if (strcmp(leftByte, DP2_RESULT_REG))
7207 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7210 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7211 assert(strcmp(leftByte, DP2_RESULT_REG));
7214 _endLazyDPSEvaluation();
7215 *lsb = DP2_RESULT_REG;
7219 if (sameRegs (AOP (result), AOP (left)) &&
7220 ((offl + MSB16) == offr))
7222 /* don't crash result[offr] */
7223 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7224 emitcode ("xch", "a,%s",
7225 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7229 movLeft2Result (left, offl, result, offr, 0);
7230 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7232 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7233 assert(strcmp(*lsb,"a"));
7238 _storeAxResults(char *lsb,
7242 _startLazyDPSEvaluation();
7243 if (AOP_NEEDSACC(result))
7245 /* We have to explicitly update the result LSB.
7247 emitcode("xch","a,%s", lsb);
7248 aopPut(AOP(result), "a", offr);
7249 emitcode("mov","a,%s", lsb);
7251 if (getDataSize (result) > 1)
7253 aopPut (AOP (result), "a", offr + MSB16);
7255 _endLazyDPSEvaluation();
7258 /*-----------------------------------------------------------------*/
7259 /* shiftL2Left2Result - shift left two bytes from left to result */
7260 /*-----------------------------------------------------------------*/
7262 shiftL2Left2Result (operand * left, int offl,
7263 operand * result, int offr, int shCount)
7267 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7269 AccAXLsh (lsb, shCount);
7271 _storeAxResults(lsb, result, offr);
7275 #ifdef BETTER_LITERAL_SHIFT
7276 /*-----------------------------------------------------------------*/
7277 /* shiftR2Left2Result - shift right two bytes from left to result */
7278 /*-----------------------------------------------------------------*/
7280 shiftR2Left2Result (operand * left, int offl,
7281 operand * result, int offr,
7282 int shCount, int sign)
7286 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7288 /* a:x >> shCount (x = lsb(result)) */
7291 AccAXRshS(lsb, shCount);
7295 AccAXRsh(lsb, shCount);
7298 _storeAxResults(lsb, result, offr);
7304 /*-----------------------------------------------------------------*/
7305 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7306 /*-----------------------------------------------------------------*/
7308 shiftLLeftOrResult (operand * left, int offl,
7309 operand * result, int offr, int shCount)
7311 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7312 /* shift left accumulator */
7314 /* or with result */
7315 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7316 /* back to result */
7317 aopPut (AOP (result), "a", offr);
7323 /*-----------------------------------------------------------------*/
7324 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7325 /*-----------------------------------------------------------------*/
7327 shiftRLeftOrResult (operand * left, int offl,
7328 operand * result, int offr, int shCount)
7330 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7331 /* shift right accumulator */
7333 /* or with result */
7334 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7335 /* back to result */
7336 aopPut (AOP (result), "a", offr);
7340 #ifdef BETTER_LITERAL_SHIFT
7341 /*-----------------------------------------------------------------*/
7342 /* genlshOne - left shift a one byte quantity by known count */
7343 /*-----------------------------------------------------------------*/
7345 genlshOne (operand * result, operand * left, int shCount)
7347 D (emitcode (";", "genlshOne "););
7348 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7352 #ifdef BETTER_LITERAL_SHIFT
7353 /*-----------------------------------------------------------------*/
7354 /* genlshTwo - left shift two bytes by known amount != 0 */
7355 /*-----------------------------------------------------------------*/
7357 genlshTwo (operand * result, operand * left, int shCount)
7361 D (emitcode (";", "genlshTwo "););
7363 size = getDataSize (result);
7365 /* if shCount >= 8 */
7370 _startLazyDPSEvaluation();
7376 _endLazyDPSEvaluation();
7377 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7378 aopPut (AOP (result), zero, LSB);
7382 movLeft2Result (left, LSB, result, MSB16, 0);
7383 aopPut (AOP (result), zero, LSB);
7384 _endLazyDPSEvaluation();
7389 aopPut (AOP (result), zero, LSB);
7390 _endLazyDPSEvaluation();
7394 /* 1 <= shCount <= 7 */
7399 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7403 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7411 /*-----------------------------------------------------------------*/
7412 /* shiftLLong - shift left one long from left to result */
7413 /* offl = LSB or MSB16 */
7414 /*-----------------------------------------------------------------*/
7416 shiftLLong (operand * left, operand * result, int offr)
7419 int size = AOP_SIZE (result);
7421 if (size >= LSB + offr)
7423 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7425 emitcode ("add", "a,acc");
7426 if (sameRegs (AOP (left), AOP (result)) &&
7427 size >= MSB16 + offr && offr != LSB)
7428 emitcode ("xch", "a,%s",
7429 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7431 aopPut (AOP (result), "a", LSB + offr);
7434 if (size >= MSB16 + offr)
7436 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7438 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7441 emitcode ("rlc", "a");
7442 if (sameRegs (AOP (left), AOP (result)) &&
7443 size >= MSB24 + offr && offr != LSB)
7444 emitcode ("xch", "a,%s",
7445 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7447 aopPut (AOP (result), "a", MSB16 + offr);
7450 if (size >= MSB24 + offr)
7452 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7454 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7457 emitcode ("rlc", "a");
7458 if (sameRegs (AOP (left), AOP (result)) &&
7459 size >= MSB32 + offr && offr != LSB)
7460 emitcode ("xch", "a,%s",
7461 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7463 aopPut (AOP (result), "a", MSB24 + offr);
7466 if (size > MSB32 + offr)
7468 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7470 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7473 emitcode ("rlc", "a");
7474 aopPut (AOP (result), "a", MSB32 + offr);
7477 aopPut (AOP (result), zero, LSB);
7483 /*-----------------------------------------------------------------*/
7484 /* genlshFour - shift four byte by a known amount != 0 */
7485 /*-----------------------------------------------------------------*/
7487 genlshFour (operand * result, operand * left, int shCount)
7491 D (emitcode (";", "genlshFour ");
7494 size = AOP_SIZE (result);
7496 /* if shifting more that 3 bytes */
7501 /* lowest order of left goes to the highest
7502 order of the destination */
7503 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7505 movLeft2Result (left, LSB, result, MSB32, 0);
7506 aopPut (AOP (result), zero, LSB);
7507 aopPut (AOP (result), zero, MSB16);
7508 aopPut (AOP (result), zero, MSB24);
7512 /* more than two bytes */
7513 else if (shCount >= 16)
7515 /* lower order two bytes goes to higher order two bytes */
7517 /* if some more remaining */
7519 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7522 movLeft2Result (left, MSB16, result, MSB32, 0);
7523 movLeft2Result (left, LSB, result, MSB24, 0);
7525 aopPut (AOP (result), zero, MSB16);
7526 aopPut (AOP (result), zero, LSB);
7530 /* if more than 1 byte */
7531 else if (shCount >= 8)
7533 /* lower order three bytes goes to higher order three bytes */
7538 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7540 movLeft2Result (left, LSB, result, MSB16, 0);
7546 movLeft2Result (left, MSB24, result, MSB32, 0);
7547 movLeft2Result (left, MSB16, result, MSB24, 0);
7548 movLeft2Result (left, LSB, result, MSB16, 0);
7549 aopPut (AOP (result), zero, LSB);
7551 else if (shCount == 1)
7552 shiftLLong (left, result, MSB16);
7555 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7556 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7557 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7558 aopPut (AOP (result), zero, LSB);
7563 /* 1 <= shCount <= 7 */
7564 else if (shCount <= 2)
7566 shiftLLong (left, result, LSB);
7568 shiftLLong (result, result, LSB);
7570 /* 3 <= shCount <= 7, optimize */
7573 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7574 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7575 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7580 #ifdef BETTER_LITERAL_SHIFT
7581 /*-----------------------------------------------------------------*/
7582 /* genLeftShiftLiteral - left shifting by known count */
7583 /*-----------------------------------------------------------------*/
7585 genLeftShiftLiteral (operand * left,
7590 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7593 size = getSize (operandType (result));
7595 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7597 /* We only handle certain easy cases so far. */
7599 && (shCount < (size * 8))
7603 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7607 freeAsmop (right, NULL, ic, TRUE);
7609 aopOp(left, ic, FALSE, FALSE);
7610 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7613 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7615 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7616 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7618 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7621 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7623 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7624 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7626 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7632 emitcode ("; shift left ", "result %d, left %d", size,
7636 /* I suppose that the left size >= result size */
7639 _startLazyDPSEvaluation();
7642 movLeft2Result (left, size, result, size, 0);
7644 _endLazyDPSEvaluation();
7646 else if (shCount >= (size * 8))
7648 _startLazyDPSEvaluation();
7651 aopPut (AOP (result), zero, size);
7653 _endLazyDPSEvaluation();
7660 genlshOne (result, left, shCount);
7664 genlshTwo (result, left, shCount);
7668 genlshFour (result, left, shCount);
7672 fprintf(stderr, "*** ack! mystery literal shift!\n");
7676 freeAsmop (left, NULL, ic, TRUE);
7677 freeAsmop (result, NULL, ic, TRUE);
7682 /*-----------------------------------------------------------------*/
7683 /* genLeftShift - generates code for left shifting */
7684 /*-----------------------------------------------------------------*/
7686 genLeftShift (iCode * ic)
7688 operand *left, *right, *result;
7691 symbol *tlbl, *tlbl1;
7693 D (emitcode (";", "genLeftShift "););
7695 right = IC_RIGHT (ic);
7696 left = IC_LEFT (ic);
7697 result = IC_RESULT (ic);
7699 aopOp (right, ic, FALSE, FALSE);
7702 #ifdef BETTER_LITERAL_SHIFT
7703 /* if the shift count is known then do it
7704 as efficiently as possible */
7705 if (AOP_TYPE (right) == AOP_LIT)
7707 if (genLeftShiftLiteral (left, right, result, ic))
7714 /* shift count is unknown then we have to form
7715 a loop get the loop count in B : Note: we take
7716 only the lower order byte since shifting
7717 more that 32 bits make no sense anyway, ( the
7718 largest size of an object can be only 32 bits ) */
7720 if (AOP_TYPE (right) == AOP_LIT)
7722 /* Really should be handled by genLeftShiftLiteral,
7723 * but since I'm too lazy to fix that today, at least we can make
7724 * some small improvement.
7726 emitcode("mov", "b,#0x%02x",
7727 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7731 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7732 emitcode ("inc", "b");
7734 freeAsmop (right, NULL, ic, TRUE);
7735 aopOp (left, ic, FALSE, FALSE);
7736 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7738 /* now move the left to the result if they are not the
7740 if (!sameRegs (AOP (left), AOP (result)) &&
7741 AOP_SIZE (result) > 1)
7744 size = AOP_SIZE (result);
7746 _startLazyDPSEvaluation ();
7749 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7750 if (*l == '@' && (IS_AOP_PREG (result)))
7753 emitcode ("mov", "a,%s", l);
7754 aopPut (AOP (result), "a", offset);
7757 aopPut (AOP (result), l, offset);
7760 _endLazyDPSEvaluation ();
7763 tlbl = newiTempLabel (NULL);
7764 size = AOP_SIZE (result);
7766 tlbl1 = newiTempLabel (NULL);
7768 /* if it is only one byte then */
7771 symbol *tlbl1 = newiTempLabel (NULL);
7773 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7775 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7776 emitcode ("", "%05d$:", tlbl->key + 100);
7777 emitcode ("add", "a,acc");
7778 emitcode ("", "%05d$:", tlbl1->key + 100);
7779 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7780 aopPut (AOP (result), "a", 0);
7784 reAdjustPreg (AOP (result));
7786 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7787 emitcode ("", "%05d$:", tlbl->key + 100);
7788 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7790 emitcode ("add", "a,acc");
7791 aopPut (AOP (result), "a", offset++);
7792 _startLazyDPSEvaluation ();
7795 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7797 emitcode ("rlc", "a");
7798 aopPut (AOP (result), "a", offset++);
7800 _endLazyDPSEvaluation ();
7801 reAdjustPreg (AOP (result));
7803 emitcode ("", "%05d$:", tlbl1->key + 100);
7804 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7806 freeAsmop (left, NULL, ic, TRUE);
7807 freeAsmop (result, NULL, ic, TRUE);
7810 #ifdef BETTER_LITERAL_SHIFT
7811 /*-----------------------------------------------------------------*/
7812 /* genrshOne - right shift a one byte quantity by known count */
7813 /*-----------------------------------------------------------------*/
7815 genrshOne (operand * result, operand * left,
7816 int shCount, int sign)
7818 D (emitcode (";", "genrshOne"););
7819 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7823 #ifdef BETTER_LITERAL_SHIFT
7824 /*-----------------------------------------------------------------*/
7825 /* genrshTwo - right shift two bytes by known amount != 0 */
7826 /*-----------------------------------------------------------------*/
7828 genrshTwo (operand * result, operand * left,
7829 int shCount, int sign)
7831 D (emitcode (";", "genrshTwo"););
7833 /* if shCount >= 8 */
7837 _startLazyDPSEvaluation();
7840 shiftR1Left2Result (left, MSB16, result, LSB,
7845 movLeft2Result (left, MSB16, result, LSB, sign);
7847 addSign (result, MSB16, sign);
7848 _endLazyDPSEvaluation();
7851 /* 1 <= shCount <= 7 */
7854 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7861 /*-----------------------------------------------------------------*/
7862 /* shiftRLong - shift right one long from left to result */
7863 /* offl = LSB or MSB16 */
7864 /*-----------------------------------------------------------------*/
7866 shiftRLong (operand * left, int offl,
7867 operand * result, int sign)
7869 int isSameRegs=sameRegs(AOP(left),AOP(result));
7871 if (isSameRegs && offl>1) {
7872 // we are in big trouble, but this shouldn't happen
7873 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7876 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7881 emitcode ("rlc", "a");
7882 emitcode ("subb", "a,acc");
7883 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7885 aopPut (AOP(result), zero, MSB32);
7890 emitcode ("clr", "c");
7892 emitcode ("mov", "c,acc.7");
7895 emitcode ("rrc", "a");
7897 if (isSameRegs && offl==MSB16) {
7898 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7900 aopPut (AOP (result), "a", MSB32);
7901 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7904 emitcode ("rrc", "a");
7905 if (isSameRegs && offl==1) {
7906 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7908 aopPut (AOP (result), "a", MSB24);
7909 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7911 emitcode ("rrc", "a");
7912 aopPut (AOP (result), "a", MSB16 - offl);
7916 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7917 emitcode ("rrc", "a");
7918 aopPut (AOP (result), "a", LSB);
7925 /*-----------------------------------------------------------------*/
7926 /* genrshFour - shift four byte by a known amount != 0 */
7927 /*-----------------------------------------------------------------*/
7929 genrshFour (operand * result, operand * left,
7930 int shCount, int sign)
7932 D (emitcode (";", "genrshFour");
7935 /* if shifting more that 3 bytes */
7940 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7942 movLeft2Result (left, MSB32, result, LSB, sign);
7943 addSign (result, MSB16, sign);
7945 else if (shCount >= 16)
7949 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7952 movLeft2Result (left, MSB24, result, LSB, 0);
7953 movLeft2Result (left, MSB32, result, MSB16, sign);
7955 addSign (result, MSB24, sign);
7957 else if (shCount >= 8)
7961 shiftRLong (left, MSB16, result, sign);
7962 else if (shCount == 0)
7964 movLeft2Result (left, MSB16, result, LSB, 0);
7965 movLeft2Result (left, MSB24, result, MSB16, 0);
7966 movLeft2Result (left, MSB32, result, MSB24, sign);
7967 addSign (result, MSB32, sign);
7971 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7972 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7973 /* the last shift is signed */
7974 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7975 addSign (result, MSB32, sign);
7979 { /* 1 <= shCount <= 7 */
7982 shiftRLong (left, LSB, result, sign);
7984 shiftRLong (result, LSB, result, sign);
7988 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7989 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7990 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7996 #ifdef BETTER_LITERAL_SHIFT
7997 /*-----------------------------------------------------------------*/
7998 /* genRightShiftLiteral - right shifting by known count */
7999 /*-----------------------------------------------------------------*/
8001 genRightShiftLiteral (operand * left,
8007 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8010 size = getSize (operandType (result));
8012 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8014 /* We only handle certain easy cases so far. */
8016 && (shCount < (size * 8))
8020 D(emitcode (";", "genRightShiftLiteral wimping out"););
8024 freeAsmop (right, NULL, ic, TRUE);
8026 aopOp (left, ic, FALSE, FALSE);
8027 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8030 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8034 /* test the LEFT size !!! */
8036 /* I suppose that the left size >= result size */
8039 size = getDataSize (result);
8040 _startLazyDPSEvaluation();
8043 movLeft2Result (left, size, result, size, 0);
8045 _endLazyDPSEvaluation();
8047 else if (shCount >= (size * 8))
8051 /* get sign in acc.7 */
8052 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8054 addSign (result, LSB, sign);
8061 genrshOne (result, left, shCount, sign);
8065 genrshTwo (result, left, shCount, sign);
8069 genrshFour (result, left, shCount, sign);
8076 freeAsmop (left, NULL, ic, TRUE);
8077 freeAsmop (result, NULL, ic, TRUE);
8083 /*-----------------------------------------------------------------*/
8084 /* genSignedRightShift - right shift of signed number */
8085 /*-----------------------------------------------------------------*/
8087 genSignedRightShift (iCode * ic)
8089 operand *right, *left, *result;
8092 symbol *tlbl, *tlbl1;
8094 D (emitcode (";", "genSignedRightShift "););
8096 /* we do it the hard way put the shift count in b
8097 and loop thru preserving the sign */
8099 right = IC_RIGHT (ic);
8100 left = IC_LEFT (ic);
8101 result = IC_RESULT (ic);
8103 aopOp (right, ic, FALSE, FALSE);
8105 #ifdef BETTER_LITERAL_SHIFT
8106 if (AOP_TYPE (right) == AOP_LIT)
8108 if (genRightShiftLiteral (left, right, result, ic, 1))
8114 /* shift count is unknown then we have to form
8115 a loop get the loop count in B : Note: we take
8116 only the lower order byte since shifting
8117 more that 32 bits make no sense anyway, ( the
8118 largest size of an object can be only 32 bits ) */
8120 if (AOP_TYPE (right) == AOP_LIT)
8122 /* Really should be handled by genRightShiftLiteral,
8123 * but since I'm too lazy to fix that today, at least we can make
8124 * some small improvement.
8126 emitcode("mov", "b,#0x%02x",
8127 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8131 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8132 emitcode ("inc", "b");
8134 freeAsmop (right, NULL, ic, TRUE);
8135 aopOp (left, ic, FALSE, FALSE);
8136 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8138 /* now move the left to the result if they are not the
8140 if (!sameRegs (AOP (left), AOP (result)) &&
8141 AOP_SIZE (result) > 1)
8144 size = AOP_SIZE (result);
8146 _startLazyDPSEvaluation ();
8149 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8150 if (*l == '@' && IS_AOP_PREG (result))
8153 emitcode ("mov", "a,%s", l);
8154 aopPut (AOP (result), "a", offset);
8157 aopPut (AOP (result), l, offset);
8160 _endLazyDPSEvaluation ();
8163 /* mov the highest order bit to OVR */
8164 tlbl = newiTempLabel (NULL);
8165 tlbl1 = newiTempLabel (NULL);
8167 size = AOP_SIZE (result);
8169 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8170 emitcode ("rlc", "a");
8171 emitcode ("mov", "ov,c");
8172 /* if it is only one byte then */
8175 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8177 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8178 emitcode ("", "%05d$:", tlbl->key + 100);
8179 emitcode ("mov", "c,ov");
8180 emitcode ("rrc", "a");
8181 emitcode ("", "%05d$:", tlbl1->key + 100);
8182 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8183 aopPut (AOP (result), "a", 0);
8187 reAdjustPreg (AOP (result));
8188 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8189 emitcode ("", "%05d$:", tlbl->key + 100);
8190 emitcode ("mov", "c,ov");
8191 _startLazyDPSEvaluation ();
8194 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8196 emitcode ("rrc", "a");
8197 aopPut (AOP (result), "a", offset--);
8199 _endLazyDPSEvaluation ();
8200 reAdjustPreg (AOP (result));
8201 emitcode ("", "%05d$:", tlbl1->key + 100);
8202 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8205 freeAsmop (left, NULL, ic, TRUE);
8206 freeAsmop (result, NULL, ic, TRUE);
8209 /*-----------------------------------------------------------------*/
8210 /* genRightShift - generate code for right shifting */
8211 /*-----------------------------------------------------------------*/
8213 genRightShift (iCode * ic)
8215 operand *right, *left, *result;
8219 symbol *tlbl, *tlbl1;
8221 D (emitcode (";", "genRightShift "););
8223 /* if signed then we do it the hard way preserve the
8224 sign bit moving it inwards */
8225 retype = getSpec (operandType (IC_RESULT (ic)));
8227 if (!SPEC_USIGN (retype))
8229 genSignedRightShift (ic);
8233 /* signed & unsigned types are treated the same : i.e. the
8234 signed is NOT propagated inwards : quoting from the
8235 ANSI - standard : "for E1 >> E2, is equivalent to division
8236 by 2**E2 if unsigned or if it has a non-negative value,
8237 otherwise the result is implementation defined ", MY definition
8238 is that the sign does not get propagated */
8240 right = IC_RIGHT (ic);
8241 left = IC_LEFT (ic);
8242 result = IC_RESULT (ic);
8244 aopOp (right, ic, FALSE, FALSE);
8246 #ifdef BETTER_LITERAL_SHIFT
8247 /* if the shift count is known then do it
8248 as efficiently as possible */
8249 if (AOP_TYPE (right) == AOP_LIT)
8251 if (genRightShiftLiteral (left, right, result, ic, 0))
8258 /* shift count is unknown then we have to form
8259 a loop get the loop count in B : Note: we take
8260 only the lower order byte since shifting
8261 more that 32 bits make no sense anyway, ( the
8262 largest size of an object can be only 32 bits ) */
8264 if (AOP_TYPE (right) == AOP_LIT)
8266 /* Really should be handled by genRightShiftLiteral,
8267 * but since I'm too lazy to fix that today, at least we can make
8268 * some small improvement.
8270 emitcode("mov", "b,#0x%02x",
8271 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8275 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8276 emitcode ("inc", "b");
8278 freeAsmop (right, NULL, ic, TRUE);
8279 aopOp (left, ic, FALSE, FALSE);
8280 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8282 /* now move the left to the result if they are not the
8284 if (!sameRegs (AOP (left), AOP (result)) &&
8285 AOP_SIZE (result) > 1)
8288 size = AOP_SIZE (result);
8290 _startLazyDPSEvaluation ();
8293 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8294 if (*l == '@' && IS_AOP_PREG (result))
8297 emitcode ("mov", "a,%s", l);
8298 aopPut (AOP (result), "a", offset);
8301 aopPut (AOP (result), l, offset);
8304 _endLazyDPSEvaluation ();
8307 tlbl = newiTempLabel (NULL);
8308 tlbl1 = newiTempLabel (NULL);
8309 size = AOP_SIZE (result);
8312 /* if it is only one byte then */
8315 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8317 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8318 emitcode ("", "%05d$:", tlbl->key + 100);
8320 emitcode ("rrc", "a");
8321 emitcode ("", "%05d$:", tlbl1->key + 100);
8322 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8323 aopPut (AOP (result), "a", 0);
8327 reAdjustPreg (AOP (result));
8328 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8329 emitcode ("", "%05d$:", tlbl->key + 100);
8331 _startLazyDPSEvaluation ();
8334 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8336 emitcode ("rrc", "a");
8337 aopPut (AOP (result), "a", offset--);
8339 _endLazyDPSEvaluation ();
8340 reAdjustPreg (AOP (result));
8342 emitcode ("", "%05d$:", tlbl1->key + 100);
8343 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8346 freeAsmop (left, NULL, ic, TRUE);
8347 freeAsmop (result, NULL, ic, TRUE);
8350 /*-----------------------------------------------------------------*/
8351 /* genUnpackBits - generates code for unpacking bits */
8352 /*-----------------------------------------------------------------*/
8354 genUnpackBits (operand * result, char *rname, int ptype)
8361 D (emitcode (";", "genUnpackBits ");
8364 etype = getSpec (operandType (result));
8366 /* read the first byte */
8372 emitcode ("mov", "a,@%s", rname);
8376 emitcode ("movx", "a,@%s", rname);
8380 emitcode ("movx", "a,@dptr");
8384 emitcode ("clr", "a");
8385 emitcode ("movc", "a,@a+dptr");
8389 emitcode ("lcall", "__gptrget");
8393 /* if we have bitdisplacement then it fits */
8394 /* into this byte completely or if length is */
8395 /* less than a byte */
8396 if ((shCnt = SPEC_BSTR (etype)) ||
8397 (SPEC_BLEN (etype) <= 8))
8400 /* shift right acc */
8403 emitcode ("anl", "a,#0x%02x",
8404 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8405 aopPut (AOP (result), "a", offset);
8409 /* bit field did not fit in a byte */
8410 rlen = SPEC_BLEN (etype) - 8;
8411 aopPut (AOP (result), "a", offset++);
8420 emitcode ("inc", "%s", rname);
8421 emitcode ("mov", "a,@%s", rname);
8425 emitcode ("inc", "%s", rname);
8426 emitcode ("movx", "a,@%s", rname);
8430 emitcode ("inc", "dptr");
8431 emitcode ("movx", "a,@dptr");
8435 emitcode ("clr", "a");
8436 emitcode ("inc", "dptr");
8437 emitcode ("movc", "a,@a+dptr");
8441 emitcode ("inc", "dptr");
8442 emitcode ("lcall", "__gptrget");
8447 /* if we are done */
8451 aopPut (AOP (result), "a", offset++);
8457 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
8458 aopPut (AOP (result), "a", offset);
8465 /*-----------------------------------------------------------------*/
8466 /* genDataPointerGet - generates code when ptr offset is known */
8467 /*-----------------------------------------------------------------*/
8469 genDataPointerGet (operand * left,
8475 int size, offset = 0;
8476 aopOp (result, ic, TRUE, FALSE);
8478 /* get the string representation of the name */
8479 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8480 size = AOP_SIZE (result);
8481 _startLazyDPSEvaluation ();
8485 sprintf (buffer, "(%s + %d)", l + 1, offset);
8487 sprintf (buffer, "%s", l + 1);
8488 aopPut (AOP (result), buffer, offset++);
8490 _endLazyDPSEvaluation ();
8492 freeAsmop (left, NULL, ic, TRUE);
8493 freeAsmop (result, NULL, ic, TRUE);
8496 /*-----------------------------------------------------------------*/
8497 /* genNearPointerGet - emitcode for near pointer fetch */
8498 /*-----------------------------------------------------------------*/
8500 genNearPointerGet (operand * left,
8507 sym_link *rtype, *retype, *letype;
8508 sym_link *ltype = operandType (left);
8511 rtype = operandType (result);
8512 retype = getSpec (rtype);
8513 letype = getSpec (ltype);
8515 aopOp (left, ic, FALSE, FALSE);
8517 /* if left is rematerialisable and
8518 result is not bit variable type and
8519 the left is pointer to data space i.e
8520 lower 128 bytes of space */
8521 if (AOP_TYPE (left) == AOP_IMMD &&
8522 !IS_BITVAR (retype) &&
8523 !IS_BITVAR (letype) &&
8524 DCL_TYPE (ltype) == POINTER)
8526 genDataPointerGet (left, result, ic);
8530 /* if the value is already in a pointer register
8531 then don't need anything more */
8532 if (!AOP_INPREG (AOP (left)))
8534 /* otherwise get a free pointer register */
8536 preg = getFreePtr (ic, &aop, FALSE);
8537 emitcode ("mov", "%s,%s",
8539 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8543 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8545 freeAsmop (left, NULL, ic, TRUE);
8546 aopOp (result, ic, FALSE, FALSE);
8548 /* if bitfield then unpack the bits */
8549 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8550 genUnpackBits (result, rname, POINTER);
8553 /* we have can just get the values */
8554 int size = AOP_SIZE (result);
8559 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8562 emitcode ("mov", "a,@%s", rname);
8563 aopPut (AOP (result), "a", offset);
8567 sprintf (buffer, "@%s", rname);
8568 aopPut (AOP (result), buffer, offset);
8572 emitcode ("inc", "%s", rname);
8576 /* now some housekeeping stuff */
8579 /* we had to allocate for this iCode */
8580 freeAsmop (NULL, aop, ic, TRUE);
8584 /* we did not allocate which means left
8585 already in a pointer register, then
8586 if size > 0 && this could be used again
8587 we have to point it back to where it
8589 if (AOP_SIZE (result) > 1 &&
8590 !OP_SYMBOL (left)->remat &&
8591 (OP_SYMBOL (left)->liveTo > ic->seq ||
8594 int size = AOP_SIZE (result) - 1;
8596 emitcode ("dec", "%s", rname);
8601 freeAsmop (result, NULL, ic, TRUE);
8605 /*-----------------------------------------------------------------*/
8606 /* genPagedPointerGet - emitcode for paged pointer fetch */
8607 /*-----------------------------------------------------------------*/
8609 genPagedPointerGet (operand * left,
8616 sym_link *rtype, *retype, *letype;
8618 rtype = operandType (result);
8619 retype = getSpec (rtype);
8620 letype = getSpec (operandType (left));
8621 aopOp (left, ic, FALSE, FALSE);
8623 /* if the value is already in a pointer register
8624 then don't need anything more */
8625 if (!AOP_INPREG (AOP (left)))
8627 /* otherwise get a free pointer register */
8629 preg = getFreePtr (ic, &aop, FALSE);
8630 emitcode ("mov", "%s,%s",
8632 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8636 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8638 freeAsmop (left, NULL, ic, TRUE);
8639 aopOp (result, ic, FALSE, FALSE);
8641 /* if bitfield then unpack the bits */
8642 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8643 genUnpackBits (result, rname, PPOINTER);
8646 /* we have can just get the values */
8647 int size = AOP_SIZE (result);
8653 emitcode ("movx", "a,@%s", rname);
8654 aopPut (AOP (result), "a", offset);
8659 emitcode ("inc", "%s", rname);
8663 /* now some housekeeping stuff */
8666 /* we had to allocate for this iCode */
8667 freeAsmop (NULL, aop, ic, TRUE);
8671 /* we did not allocate which means left
8672 already in a pointer register, then
8673 if size > 0 && this could be used again
8674 we have to point it back to where it
8676 if (AOP_SIZE (result) > 1 &&
8677 !OP_SYMBOL (left)->remat &&
8678 (OP_SYMBOL (left)->liveTo > ic->seq ||
8681 int size = AOP_SIZE (result) - 1;
8683 emitcode ("dec", "%s", rname);
8688 freeAsmop (result, NULL, ic, TRUE);
8693 /*-----------------------------------------------------------------*/
8694 /* genFarPointerGet - gget value from far space */
8695 /*-----------------------------------------------------------------*/
8697 genFarPointerGet (operand * left,
8698 operand * result, iCode * ic)
8701 sym_link *retype = getSpec (operandType (result));
8702 sym_link *letype = getSpec (operandType (left));
8703 D (emitcode (";", "genFarPointerGet");
8706 aopOp (left, ic, FALSE, FALSE);
8708 /* if the operand is already in dptr
8709 then we do nothing else we move the value to dptr */
8710 if (AOP_TYPE (left) != AOP_STR)
8712 /* if this is remateriazable */
8713 if (AOP_TYPE (left) == AOP_IMMD)
8715 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8719 /* we need to get it byte by byte */
8720 _startLazyDPSEvaluation ();
8721 if (AOP_TYPE (left) != AOP_DPTR)
8723 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8724 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8725 if (options.model == MODEL_FLAT24)
8726 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8730 /* We need to generate a load to DPTR indirect through DPTR. */
8731 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8733 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8734 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8735 if (options.model == MODEL_FLAT24)
8736 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8737 emitcode ("pop", "dph");
8738 emitcode ("pop", "dpl");
8740 _endLazyDPSEvaluation ();
8743 /* so dptr know contains the address */
8744 freeAsmop (left, NULL, ic, TRUE);
8745 aopOp (result, ic, FALSE, TRUE);
8747 /* if bit then unpack */
8748 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8749 genUnpackBits (result, "dptr", FPOINTER);
8752 size = AOP_SIZE (result);
8755 _startLazyDPSEvaluation ();
8762 emitcode ("movx", "a,@dptr");
8764 emitcode ("inc", "dptr");
8766 aopPut (AOP (result), "a", offset++);
8768 _endLazyDPSEvaluation ();
8771 freeAsmop (result, NULL, ic, TRUE);
8774 /*-----------------------------------------------------------------*/
8775 /* emitcodePointerGet - gget value from code space */
8776 /*-----------------------------------------------------------------*/
8778 emitcodePointerGet (operand * left,
8779 operand * result, iCode * ic)
8782 sym_link *retype = getSpec (operandType (result));
8784 aopOp (left, ic, FALSE, FALSE);
8786 /* if the operand is already in dptr
8787 then we do nothing else we move the value to dptr */
8788 if (AOP_TYPE (left) != AOP_STR)
8790 /* if this is remateriazable */
8791 if (AOP_TYPE (left) == AOP_IMMD)
8793 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8796 { /* we need to get it byte by byte */
8797 _startLazyDPSEvaluation ();
8798 if (AOP_TYPE (left) != AOP_DPTR)
8800 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8801 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8802 if (options.model == MODEL_FLAT24)
8803 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8807 /* We need to generate a load to DPTR indirect through DPTR. */
8808 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8810 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8811 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8812 if (options.model == MODEL_FLAT24)
8813 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8814 emitcode ("pop", "dph");
8815 emitcode ("pop", "dpl");
8817 _endLazyDPSEvaluation ();
8820 /* so dptr know contains the address */
8821 freeAsmop (left, NULL, ic, TRUE);
8822 aopOp (result, ic, FALSE, TRUE);
8824 /* if bit then unpack */
8825 if (IS_BITVAR (retype))
8826 genUnpackBits (result, "dptr", CPOINTER);
8829 size = AOP_SIZE (result);
8832 _startLazyDPSEvaluation ();
8838 emitcode ("clr", "a");
8839 emitcode ("movc", "a,@a+dptr");
8841 emitcode ("inc", "dptr");
8842 aopPut (AOP (result), "a", offset++);
8844 _endLazyDPSEvaluation ();
8847 freeAsmop (result, NULL, ic, TRUE);
8850 /*-----------------------------------------------------------------*/
8851 /* genGenPointerGet - gget value from generic pointer space */
8852 /*-----------------------------------------------------------------*/
8854 genGenPointerGet (operand * left,
8855 operand * result, iCode * ic)
8858 sym_link *retype = getSpec (operandType (result));
8859 sym_link *letype = getSpec (operandType (left));
8861 D (emitcode (";", "genGenPointerGet "); );
8863 aopOp (left, ic, FALSE, TRUE);
8865 /* if the operand is already in dptr
8866 then we do nothing else we move the value to dptr */
8867 if (AOP_TYPE (left) != AOP_STR)
8869 /* if this is remateriazable */
8870 if (AOP_TYPE (left) == AOP_IMMD)
8872 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8873 if (AOP(left)->aopu.aop_immd.from_cast_remat)
8874 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
8876 emitcode ("mov", "b,#%d", pointerCode (retype));
8879 { /* we need to get it byte by byte */
8880 _startLazyDPSEvaluation ();
8881 if (AOP(left)->type==AOP_DPTR2) {
8883 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8886 emitcode ("mov", "dpl,%s", l);
8887 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8890 emitcode ("mov", "dph,%s", l);
8891 if (options.model == MODEL_FLAT24) {
8892 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8895 emitcode ("mov", "dpx,%s", l);
8896 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8898 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8901 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8902 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8903 if (options.model == MODEL_FLAT24) {
8904 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8905 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8907 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8910 _endLazyDPSEvaluation ();
8913 /* so dptr know contains the address */
8914 freeAsmop (left, NULL, ic, TRUE);
8915 aopOp (result, ic, FALSE, TRUE);
8917 /* if bit then unpack */
8918 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8919 genUnpackBits (result, "dptr", GPOINTER);
8922 size = AOP_SIZE (result);
8927 emitcode ("lcall", "__gptrget");
8928 aopPut (AOP (result), "a", offset++);
8930 emitcode ("inc", "dptr");
8934 freeAsmop (result, NULL, ic, TRUE);
8937 /*-----------------------------------------------------------------*/
8938 /* genPointerGet - generate code for pointer get */
8939 /*-----------------------------------------------------------------*/
8941 genPointerGet (iCode * ic)
8943 operand *left, *result;
8944 sym_link *type, *etype;
8947 D (emitcode (";", "genPointerGet ");
8950 left = IC_LEFT (ic);
8951 result = IC_RESULT (ic);
8953 /* depending on the type of pointer we need to
8954 move it to the correct pointer register */
8955 type = operandType (left);
8956 etype = getSpec (type);
8957 /* if left is of type of pointer then it is simple */
8958 if (IS_PTR (type) && !IS_FUNC (type->next))
8959 p_type = DCL_TYPE (type);
8962 /* we have to go by the storage class */
8963 p_type = PTR_TYPE (SPEC_OCLS (etype));
8966 /* now that we have the pointer type we assign
8967 the pointer values */
8973 genNearPointerGet (left, result, ic);
8977 genPagedPointerGet (left, result, ic);
8981 genFarPointerGet (left, result, ic);
8985 emitcodePointerGet (left, result, ic);
8989 genGenPointerGet (left, result, ic);
8995 /*-----------------------------------------------------------------*/
8996 /* genPackBits - generates code for packed bit storage */
8997 /*-----------------------------------------------------------------*/
8999 genPackBits (sym_link * etype,
9001 char *rname, int p_type)
9009 blen = SPEC_BLEN (etype);
9010 bstr = SPEC_BSTR (etype);
9012 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9015 /* if the bit lenth is less than or */
9016 /* it exactly fits a byte then */
9017 if (SPEC_BLEN (etype) <= 8)
9019 shCount = SPEC_BSTR (etype);
9021 /* shift left acc */
9024 if (SPEC_BLEN (etype) < 8)
9025 { /* if smaller than a byte */
9031 emitcode ("mov", "b,a");
9032 emitcode ("mov", "a,@%s", rname);
9036 emitcode ("mov", "b,a");
9037 emitcode ("movx", "a,@dptr");
9041 emitcode ("push", "b");
9042 emitcode ("push", "acc");
9043 emitcode ("lcall", "__gptrget");
9044 emitcode ("pop", "b");
9048 emitcode ("anl", "a,#0x%02x", (unsigned char)
9049 ((unsigned char) (0xFF << (blen + bstr)) |
9050 (unsigned char) (0xFF >> (8 - bstr))));
9051 emitcode ("orl", "a,b");
9052 if (p_type == GPOINTER)
9053 emitcode ("pop", "b");
9060 emitcode ("mov", "@%s,a", rname);
9064 emitcode ("movx", "@dptr,a");
9068 emitcode ("lcall", "__gptrput");
9073 if (SPEC_BLEN (etype) <= 8)
9076 emitcode ("inc", "%s", rname);
9077 rLen = SPEC_BLEN (etype);
9079 /* now generate for lengths greater than one byte */
9083 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9095 emitcode ("mov", "@%s,a", rname);
9098 emitcode ("mov", "@%s,%s", rname, l);
9103 emitcode ("movx", "@dptr,a");
9108 emitcode ("lcall", "__gptrput");
9111 emitcode ("inc", "%s", rname);
9116 /* last last was not complete */
9119 /* save the byte & read byte */
9123 emitcode ("mov", "b,a");
9124 emitcode ("mov", "a,@%s", rname);
9128 emitcode ("mov", "b,a");
9129 emitcode ("movx", "a,@dptr");
9133 emitcode ("push", "b");
9134 emitcode ("push", "acc");
9135 emitcode ("lcall", "__gptrget");
9136 emitcode ("pop", "b");
9140 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
9141 emitcode ("orl", "a,b");
9144 if (p_type == GPOINTER)
9145 emitcode ("pop", "b");
9151 emitcode ("mov", "@%s,a", rname);
9155 emitcode ("movx", "@dptr,a");
9159 emitcode ("lcall", "__gptrput");
9163 /*-----------------------------------------------------------------*/
9164 /* genDataPointerSet - remat pointer to data space */
9165 /*-----------------------------------------------------------------*/
9167 genDataPointerSet (operand * right,
9171 int size, offset = 0;
9172 char *l, buffer[256];
9174 aopOp (right, ic, FALSE, FALSE);
9176 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9177 size = AOP_SIZE (right);
9181 sprintf (buffer, "(%s + %d)", l + 1, offset);
9183 sprintf (buffer, "%s", l + 1);
9184 emitcode ("mov", "%s,%s", buffer,
9185 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9188 freeAsmop (right, NULL, ic, TRUE);
9189 freeAsmop (result, NULL, ic, TRUE);
9192 /*-----------------------------------------------------------------*/
9193 /* genNearPointerSet - emitcode for near pointer put */
9194 /*-----------------------------------------------------------------*/
9196 genNearPointerSet (operand * right,
9203 sym_link *retype, *letype;
9204 sym_link *ptype = operandType (result);
9206 retype = getSpec (operandType (right));
9207 letype = getSpec (ptype);
9209 aopOp (result, ic, FALSE, FALSE);
9211 /* if the result is rematerializable &
9212 in data space & not a bit variable */
9213 if (AOP_TYPE (result) == AOP_IMMD &&
9214 DCL_TYPE (ptype) == POINTER &&
9215 !IS_BITVAR (retype) &&
9216 !IS_BITVAR (letype))
9218 genDataPointerSet (right, result, ic);
9222 /* if the value is already in a pointer register
9223 then don't need anything more */
9224 if (!AOP_INPREG (AOP (result)))
9226 /* otherwise get a free pointer register */
9228 preg = getFreePtr (ic, &aop, FALSE);
9229 emitcode ("mov", "%s,%s",
9231 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9235 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9237 freeAsmop (result, NULL, ic, TRUE);
9238 aopOp (right, ic, FALSE, FALSE);
9240 /* if bitfield then unpack the bits */
9241 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9242 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9245 /* we have can just get the values */
9246 int size = AOP_SIZE (right);
9251 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9255 emitcode ("mov", "@%s,a", rname);
9258 emitcode ("mov", "@%s,%s", rname, l);
9260 emitcode ("inc", "%s", rname);
9265 /* now some housekeeping stuff */
9268 /* we had to allocate for this iCode */
9269 freeAsmop (NULL, aop, ic, TRUE);
9273 /* we did not allocate which means left
9274 already in a pointer register, then
9275 if size > 0 && this could be used again
9276 we have to point it back to where it
9278 if (AOP_SIZE (right) > 1 &&
9279 !OP_SYMBOL (result)->remat &&
9280 (OP_SYMBOL (result)->liveTo > ic->seq ||
9283 int size = AOP_SIZE (right) - 1;
9285 emitcode ("dec", "%s", rname);
9290 freeAsmop (right, NULL, ic, TRUE);
9295 /*-----------------------------------------------------------------*/
9296 /* genPagedPointerSet - emitcode for Paged pointer put */
9297 /*-----------------------------------------------------------------*/
9299 genPagedPointerSet (operand * right,
9306 sym_link *retype, *letype;
9308 retype = getSpec (operandType (right));
9309 letype = getSpec (operandType (result));
9311 aopOp (result, ic, FALSE, FALSE);
9313 /* if the value is already in a pointer register
9314 then don't need anything more */
9315 if (!AOP_INPREG (AOP (result)))
9317 /* otherwise get a free pointer register */
9319 preg = getFreePtr (ic, &aop, FALSE);
9320 emitcode ("mov", "%s,%s",
9322 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9326 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9328 freeAsmop (result, NULL, ic, TRUE);
9329 aopOp (right, ic, FALSE, FALSE);
9331 /* if bitfield then unpack the bits */
9332 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9333 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9336 /* we have can just get the values */
9337 int size = AOP_SIZE (right);
9342 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9345 emitcode ("movx", "@%s,a", rname);
9348 emitcode ("inc", "%s", rname);
9354 /* now some housekeeping stuff */
9357 /* we had to allocate for this iCode */
9358 freeAsmop (NULL, aop, ic, TRUE);
9362 /* we did not allocate which means left
9363 already in a pointer register, then
9364 if size > 0 && this could be used again
9365 we have to point it back to where it
9367 if (AOP_SIZE (right) > 1 &&
9368 !OP_SYMBOL (result)->remat &&
9369 (OP_SYMBOL (result)->liveTo > ic->seq ||
9372 int size = AOP_SIZE (right) - 1;
9374 emitcode ("dec", "%s", rname);
9379 freeAsmop (right, NULL, ic, TRUE);
9384 /*-----------------------------------------------------------------*/
9385 /* genFarPointerSet - set value from far space */
9386 /*-----------------------------------------------------------------*/
9388 genFarPointerSet (operand * right,
9389 operand * result, iCode * ic)
9392 sym_link *retype = getSpec (operandType (right));
9393 sym_link *letype = getSpec (operandType (result));
9395 aopOp (result, ic, FALSE, FALSE);
9397 /* if the operand is already in dptr
9398 then we do nothing else we move the value to dptr */
9399 if (AOP_TYPE (result) != AOP_STR)
9401 /* if this is remateriazable */
9402 if (AOP_TYPE (result) == AOP_IMMD)
9403 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9406 /* we need to get it byte by byte */
9407 _startLazyDPSEvaluation ();
9408 if (AOP_TYPE (result) != AOP_DPTR)
9410 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9411 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9412 if (options.model == MODEL_FLAT24)
9413 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9417 /* We need to generate a load to DPTR indirect through DPTR. */
9418 D (emitcode (";", "genFarPointerSet -- indirection special case.");
9420 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9421 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9422 if (options.model == MODEL_FLAT24)
9423 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9424 emitcode ("pop", "dph");
9425 emitcode ("pop", "dpl");
9427 _endLazyDPSEvaluation ();
9430 /* so dptr know contains the address */
9431 freeAsmop (result, NULL, ic, TRUE);
9432 aopOp (right, ic, FALSE, TRUE);
9434 /* if bit then unpack */
9435 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9436 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9439 size = AOP_SIZE (right);
9442 _startLazyDPSEvaluation ();
9445 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9451 emitcode ("movx", "@dptr,a");
9453 emitcode ("inc", "dptr");
9455 _endLazyDPSEvaluation ();
9458 freeAsmop (right, NULL, ic, TRUE);
9461 /*-----------------------------------------------------------------*/
9462 /* genGenPointerSet - set value from generic pointer space */
9463 /*-----------------------------------------------------------------*/
9465 genGenPointerSet (operand * right,
9466 operand * result, iCode * ic)
9469 sym_link *retype = getSpec (operandType (right));
9470 sym_link *letype = getSpec (operandType (result));
9472 aopOp (result, ic, FALSE, TRUE);
9474 /* if the operand is already in dptr
9475 then we do nothing else we move the value to dptr */
9476 if (AOP_TYPE (result) != AOP_STR)
9478 _startLazyDPSEvaluation ();
9479 /* if this is remateriazable */
9480 if (AOP_TYPE (result) == AOP_IMMD)
9482 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9483 if (AOP(result)->aopu.aop_immd.from_cast_remat)
9484 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
9486 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9489 { /* we need to get it byte by byte */
9490 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9491 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9492 if (options.model == MODEL_FLAT24) {
9493 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9494 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9496 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9499 _endLazyDPSEvaluation ();
9501 /* so dptr know contains the address */
9502 freeAsmop (result, NULL, ic, TRUE);
9503 aopOp (right, ic, FALSE, TRUE);
9505 /* if bit then unpack */
9506 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9507 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9510 size = AOP_SIZE (right);
9513 _startLazyDPSEvaluation ();
9516 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9522 emitcode ("lcall", "__gptrput");
9524 emitcode ("inc", "dptr");
9526 _endLazyDPSEvaluation ();
9529 freeAsmop (right, NULL, ic, TRUE);
9532 /*-----------------------------------------------------------------*/
9533 /* genPointerSet - stores the value into a pointer location */
9534 /*-----------------------------------------------------------------*/
9536 genPointerSet (iCode * ic)
9538 operand *right, *result;
9539 sym_link *type, *etype;
9542 D (emitcode (";", "genPointerSet ");
9545 right = IC_RIGHT (ic);
9546 result = IC_RESULT (ic);
9548 /* depending on the type of pointer we need to
9549 move it to the correct pointer register */
9550 type = operandType (result);
9551 etype = getSpec (type);
9552 /* if left is of type of pointer then it is simple */
9553 if (IS_PTR (type) && !IS_FUNC (type->next))
9555 p_type = DCL_TYPE (type);
9559 /* we have to go by the storage class */
9560 p_type = PTR_TYPE (SPEC_OCLS (etype));
9563 /* now that we have the pointer type we assign
9564 the pointer values */
9570 genNearPointerSet (right, result, ic);
9574 genPagedPointerSet (right, result, ic);
9578 genFarPointerSet (right, result, ic);
9582 genGenPointerSet (right, result, ic);
9588 /*-----------------------------------------------------------------*/
9589 /* genIfx - generate code for Ifx statement */
9590 /*-----------------------------------------------------------------*/
9592 genIfx (iCode * ic, iCode * popIc)
9594 operand *cond = IC_COND (ic);
9597 D (emitcode (";", "genIfx "););
9599 aopOp (cond, ic, FALSE, FALSE);
9601 /* get the value into acc */
9602 if (AOP_TYPE (cond) != AOP_CRY)
9606 /* the result is now in the accumulator */
9607 freeAsmop (cond, NULL, ic, TRUE);
9609 /* if there was something to be popped then do it */
9613 /* if the condition is a bit variable */
9614 if (isbit && IS_ITEMP (cond) &&
9616 genIfxJump (ic, SPIL_LOC (cond)->rname);
9617 else if (isbit && !IS_ITEMP (cond))
9618 genIfxJump (ic, OP_SYMBOL (cond)->rname);
9620 genIfxJump (ic, "a");
9625 /*-----------------------------------------------------------------*/
9626 /* genAddrOf - generates code for address of */
9627 /*-----------------------------------------------------------------*/
9629 genAddrOf (iCode * ic)
9631 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9634 D (emitcode (";", "genAddrOf ");
9637 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9639 /* if the operand is on the stack then we
9640 need to get the stack offset of this
9644 /* if it has an offset then we need to compute
9648 emitcode ("mov", "a,_bp");
9649 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9650 aopPut (AOP (IC_RESULT (ic)), "a", 0);
9654 /* we can just move _bp */
9655 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9657 /* fill the result with zero */
9658 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9661 if (options.stack10bit && size < (FPTRSIZE - 1))
9664 "*** warning: pointer to stack var truncated.\n");
9671 if (options.stack10bit && offset == 2)
9673 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
9677 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9684 /* object not on stack then we need the name */
9685 size = AOP_SIZE (IC_RESULT (ic));
9690 char s[SDCC_NAME_MAX];
9692 sprintf (s, "#(%s >> %d)",
9696 sprintf (s, "#%s", sym->rname);
9697 aopPut (AOP (IC_RESULT (ic)), s, offset++);
9701 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9705 /*-----------------------------------------------------------------*/
9706 /* genArrayInit - generates code for address of */
9707 /*-----------------------------------------------------------------*/
9709 genArrayInit (iCode * ic)
9713 int elementSize = 0, eIndex;
9714 unsigned val, lastVal;
9716 operand *left=IC_LEFT(ic);
9718 D (emitcode (";", "genArrayInit "););
9720 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
9722 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
9724 // Load immediate value into DPTR.
9725 emitcode("mov", "dptr, %s",
9726 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
9728 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
9731 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9732 "Unexpected operand to genArrayInit.\n");
9735 // a regression because of SDCCcse.c:1.52
9736 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9737 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9738 if (options.model == MODEL_FLAT24)
9739 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9743 type = operandType(IC_LEFT(ic));
9745 if (type && type->next)
9747 elementSize = getSize(type->next);
9751 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9752 "can't determine element size in genArrayInit.\n");
9756 iLoop = IC_ARRAYILIST(ic);
9761 bool firstpass = TRUE;
9763 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
9764 iLoop->count, (int)iLoop->literalValue, elementSize);
9770 symbol *tlbl = NULL;
9772 count = ix > 256 ? 256 : ix;
9776 tlbl = newiTempLabel (NULL);
9777 if (firstpass || (count & 0xff))
9779 emitcode("mov", "b, #0x%x", count & 0xff);
9782 emitcode ("", "%05d$:", tlbl->key + 100);
9787 for (eIndex = 0; eIndex < elementSize; eIndex++)
9789 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
9792 emitcode("mov", "a, #0x%x", val);
9796 emitcode("movx", "@dptr, a");
9797 emitcode("inc", "dptr");
9802 emitcode("djnz", "b, %05d$", tlbl->key + 100);
9808 iLoop = iLoop->next;
9811 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
9814 /*-----------------------------------------------------------------*/
9815 /* genFarFarAssign - assignment when both are in far space */
9816 /*-----------------------------------------------------------------*/
9818 genFarFarAssign (operand * result, operand * right, iCode * ic)
9820 int size = AOP_SIZE (right);
9822 symbol *rSym = NULL;
9826 /* quick & easy case. */
9827 D(emitcode(";","genFarFarAssign (1 byte case)"););
9828 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9829 freeAsmop (right, NULL, ic, FALSE);
9830 /* now assign DPTR to result */
9832 aopOp(result, ic, FALSE, FALSE);
9834 aopPut(AOP(result), "a", 0);
9835 freeAsmop(result, NULL, ic, FALSE);
9839 /* See if we've got an underlying symbol to abuse. */
9840 if (IS_SYMOP(result) && OP_SYMBOL(result))
9842 if (IS_TRUE_SYMOP(result))
9844 rSym = OP_SYMBOL(result);
9846 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9848 rSym = OP_SYMBOL(result)->usl.spillLoc;
9852 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9854 /* We can use the '390 auto-toggle feature to good effect here. */
9856 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
9857 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
9858 emitcode ("mov", "dptr,#%s", rSym->rname);
9859 /* DP2 = result, DP1 = right, DP1 is current. */
9862 emitcode("movx", "a,@dptr");
9863 emitcode("movx", "@dptr,a");
9866 emitcode("inc", "dptr");
9867 emitcode("inc", "dptr");
9870 emitcode("mov", "dps, #0");
9871 freeAsmop (right, NULL, ic, FALSE);
9873 some alternative code for processors without auto-toggle
9874 no time to test now, so later well put in...kpb
9875 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
9876 emitcode("mov", "dps, #0x01"); /* Select DPTR2. */
9877 emitcode ("mov", "dptr,#%s", rSym->rname);
9878 /* DP2 = result, DP1 = right, DP1 is current. */
9882 emitcode("movx", "a,@dptr");
9884 emitcode("inc", "dptr");
9885 emitcode("inc", "dps");
9886 emitcode("movx", "@dptr,a");
9888 emitcode("inc", "dptr");
9889 emitcode("inc", "dps");
9891 emitcode("mov", "dps, #0");
9892 freeAsmop (right, NULL, ic, FALSE);
9897 D (emitcode (";", "genFarFarAssign"););
9898 aopOp (result, ic, TRUE, TRUE);
9900 _startLazyDPSEvaluation ();
9904 aopPut (AOP (result),
9905 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9908 _endLazyDPSEvaluation ();
9909 freeAsmop (result, NULL, ic, FALSE);
9910 freeAsmop (right, NULL, ic, FALSE);
9914 /*-----------------------------------------------------------------*/
9915 /* genAssign - generate code for assignment */
9916 /*-----------------------------------------------------------------*/
9918 genAssign (iCode * ic)
9920 operand *result, *right;
9922 unsigned long lit = 0L;
9924 D (emitcode (";", "genAssign ");
9927 result = IC_RESULT (ic);
9928 right = IC_RIGHT (ic);
9930 /* if they are the same */
9931 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9934 aopOp (right, ic, FALSE, FALSE);
9936 emitcode (";", "genAssign: resultIsFar = %s",
9937 isOperandInFarSpace (result) ?
9940 /* special case both in far space */
9941 if ((AOP_TYPE (right) == AOP_DPTR ||
9942 AOP_TYPE (right) == AOP_DPTR2) &&
9943 /* IS_TRUE_SYMOP(result) && */
9944 isOperandInFarSpace (result))
9946 genFarFarAssign (result, right, ic);
9950 aopOp (result, ic, TRUE, FALSE);
9952 /* if they are the same registers */
9953 if (sameRegs (AOP (right), AOP (result)))
9956 /* if the result is a bit */
9957 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
9959 /* if the right size is a literal then
9960 we know what the value is */
9961 if (AOP_TYPE (right) == AOP_LIT)
9963 if (((int) operandLitValue (right)))
9964 aopPut (AOP (result), one, 0);
9966 aopPut (AOP (result), zero, 0);
9970 /* the right is also a bit variable */
9971 if (AOP_TYPE (right) == AOP_CRY)
9973 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9974 aopPut (AOP (result), "c", 0);
9980 aopPut (AOP (result), "a", 0);
9984 /* bit variables done */
9986 size = AOP_SIZE (result);
9988 if (AOP_TYPE (right) == AOP_LIT)
9989 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9992 (AOP_TYPE (result) != AOP_REG) &&
9993 (AOP_TYPE (right) == AOP_LIT) &&
9994 !IS_FLOAT (operandType (right)))
9996 _startLazyDPSEvaluation ();
9997 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9999 aopPut (AOP (result),
10000 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10005 /* And now fill the rest with zeros. */
10008 emitcode ("clr", "a");
10012 aopPut (AOP (result), "a", offset++);
10014 _endLazyDPSEvaluation ();
10018 _startLazyDPSEvaluation ();
10021 aopPut (AOP (result),
10022 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10026 _endLazyDPSEvaluation ();
10030 freeAsmop (right, NULL, ic, FALSE);
10031 freeAsmop (result, NULL, ic, TRUE);
10034 /*-----------------------------------------------------------------*/
10035 /* genJumpTab - generates code for jump table */
10036 /*-----------------------------------------------------------------*/
10038 genJumpTab (iCode * ic)
10043 D (emitcode (";", "genJumpTab ");
10046 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10047 /* get the condition into accumulator */
10048 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10050 /* multiply by four! */
10051 emitcode ("add", "a,acc");
10052 emitcode ("add", "a,acc");
10053 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10055 jtab = newiTempLabel (NULL);
10056 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10057 emitcode ("jmp", "@a+dptr");
10058 emitcode ("", "%05d$:", jtab->key + 100);
10059 /* now generate the jump labels */
10060 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10061 jtab = setNextItem (IC_JTLABELS (ic)))
10062 emitcode ("ljmp", "%05d$", jtab->key + 100);
10066 /*-----------------------------------------------------------------*/
10067 /* genCast - gen code for casting */
10068 /*-----------------------------------------------------------------*/
10070 genCast (iCode * ic)
10072 operand *result = IC_RESULT (ic);
10073 sym_link *ctype = operandType (IC_LEFT (ic));
10074 sym_link *rtype = operandType (IC_RIGHT (ic));
10075 operand *right = IC_RIGHT (ic);
10078 D (emitcode (";", "genCast ");
10081 /* if they are equivalent then do nothing */
10082 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10085 aopOp (right, ic, FALSE, FALSE);
10086 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10088 /* if the result is a bit */
10089 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10090 if (IS_BITVAR(OP_SYMBOL(result)->type))
10092 /* if the right size is a literal then
10093 we know what the value is */
10094 if (AOP_TYPE (right) == AOP_LIT)
10096 if (((int) operandLitValue (right)))
10097 aopPut (AOP (result), one, 0);
10099 aopPut (AOP (result), zero, 0);
10104 /* the right is also a bit variable */
10105 if (AOP_TYPE (right) == AOP_CRY)
10107 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10108 aopPut (AOP (result), "c", 0);
10112 /* we need to or */
10114 aopPut (AOP (result), "a", 0);
10118 /* if they are the same size : or less */
10119 if (AOP_SIZE (result) <= AOP_SIZE (right))
10122 /* if they are in the same place */
10123 if (sameRegs (AOP (right), AOP (result)))
10126 /* if they in different places then copy */
10127 size = AOP_SIZE (result);
10129 _startLazyDPSEvaluation ();
10132 aopPut (AOP (result),
10133 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10137 _endLazyDPSEvaluation ();
10142 /* if the result is of type pointer */
10143 if (IS_PTR (ctype))
10147 sym_link *type = operandType (right);
10149 /* pointer to generic pointer */
10150 if (IS_GENPTR (ctype))
10156 p_type = DCL_TYPE (type);
10160 #if OLD_CAST_BEHAVIOR
10161 /* KV: we are converting a non-pointer type to
10162 * a generic pointer. This (ifdef'd out) code
10163 * says that the resulting generic pointer
10164 * should have the same class as the storage
10165 * location of the non-pointer variable.
10167 * For example, converting an int (which happens
10168 * to be stored in DATA space) to a pointer results
10169 * in a DATA generic pointer; if the original int
10170 * in XDATA space, so will be the resulting pointer.
10172 * I don't like that behavior, and thus this change:
10173 * all such conversions will be forced to XDATA and
10174 * throw a warning. If you want some non-XDATA
10175 * type, or you want to suppress the warning, you
10176 * must go through an intermediate cast, like so:
10178 * char _generic *gp = (char _xdata *)(intVar);
10180 sym_link *etype = getSpec (type);
10182 /* we have to go by the storage class */
10183 if (SPEC_OCLS (etype) != generic)
10185 p_type = PTR_TYPE (SPEC_OCLS (etype));
10190 /* Converting unknown class (i.e. register variable)
10191 * to generic pointer. This is not good, but
10192 * we'll make a guess (and throw a warning).
10195 werror (W_INT_TO_GEN_PTR_CAST);
10199 /* the first two bytes are known */
10200 size = GPTRSIZE - 1;
10202 _startLazyDPSEvaluation ();
10205 aopPut (AOP (result),
10206 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10210 _endLazyDPSEvaluation ();
10212 /* the last byte depending on type */
10230 /* this should never happen */
10231 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10232 "got unknown pointer type");
10235 aopPut (AOP (result), l, GPTRSIZE - 1);
10239 /* just copy the pointers */
10240 size = AOP_SIZE (result);
10242 _startLazyDPSEvaluation ();
10245 aopPut (AOP (result),
10246 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10250 _endLazyDPSEvaluation ();
10254 /* so we now know that the size of destination is greater
10255 than the size of the source */
10256 /* we move to result for the size of source */
10257 size = AOP_SIZE (right);
10259 _startLazyDPSEvaluation ();
10262 aopPut (AOP (result),
10263 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10267 _endLazyDPSEvaluation ();
10269 /* now depending on the sign of the source && destination */
10270 size = AOP_SIZE (result) - AOP_SIZE (right);
10271 /* if unsigned or not an integral type */
10272 /* also, if the source is a bit, we don't need to sign extend, because
10273 * it can't possibly have set the sign bit.
10275 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10279 aopPut (AOP (result), zero, offset++);
10284 /* we need to extend the sign :{ */
10285 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10286 FALSE, FALSE, TRUE);
10288 emitcode ("rlc", "a");
10289 emitcode ("subb", "a,acc");
10291 aopPut (AOP (result), "a", offset++);
10294 /* we are done hurray !!!! */
10297 freeAsmop (right, NULL, ic, TRUE);
10298 freeAsmop (result, NULL, ic, TRUE);
10302 /*-----------------------------------------------------------------*/
10303 /* genDjnz - generate decrement & jump if not zero instrucion */
10304 /*-----------------------------------------------------------------*/
10306 genDjnz (iCode * ic, iCode * ifx)
10308 symbol *lbl, *lbl1;
10312 /* if the if condition has a false label
10313 then we cannot save */
10314 if (IC_FALSE (ifx))
10317 /* if the minus is not of the form
10319 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10320 !IS_OP_LITERAL (IC_RIGHT (ic)))
10323 if (operandLitValue (IC_RIGHT (ic)) != 1)
10326 /* if the size of this greater than one then no
10328 if (getSize (operandType (IC_RESULT (ic))) > 1)
10331 /* otherwise we can save BIG */
10332 D(emitcode(";", "genDjnz"););
10334 lbl = newiTempLabel (NULL);
10335 lbl1 = newiTempLabel (NULL);
10337 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10339 if (AOP_NEEDSACC(IC_RESULT(ic)))
10341 /* If the result is accessed indirectly via
10342 * the accumulator, we must explicitly write
10343 * it back after the decrement.
10345 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10347 if (strcmp(rByte, "a"))
10349 /* Something is hopelessly wrong */
10350 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10351 __FILE__, __LINE__);
10352 /* We can just give up; the generated code will be inefficient,
10353 * but what the hey.
10355 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10358 emitcode ("dec", "%s", rByte);
10359 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10360 emitcode ("jnz", "%05d$", lbl->key + 100);
10362 else if (IS_AOP_PREG (IC_RESULT (ic)))
10364 emitcode ("dec", "%s",
10365 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10366 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10367 emitcode ("jnz", "%05d$", lbl->key + 100);
10371 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10374 emitcode ("sjmp", "%05d$", lbl1->key + 100);
10375 emitcode ("", "%05d$:", lbl->key + 100);
10376 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10377 emitcode ("", "%05d$:", lbl1->key + 100);
10379 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10380 ifx->generated = 1;
10384 /*-----------------------------------------------------------------*/
10385 /* genReceive - generate code for a receive iCode */
10386 /*-----------------------------------------------------------------*/
10388 genReceive (iCode * ic)
10391 D (emitcode (";", "genReceive ");
10394 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10395 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10396 IS_TRUE_SYMOP (IC_RESULT (ic))))
10398 int size = getSize (operandType (IC_RESULT (ic)));
10399 int offset = fReturnSizeDS390 - size;
10402 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10403 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10406 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10407 size = AOP_SIZE (IC_RESULT (ic));
10411 emitcode ("pop", "acc");
10412 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10419 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10421 assignResultValue (IC_RESULT (ic));
10424 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10427 /*-----------------------------------------------------------------*/
10428 /* gen390Code - generate code for Dallas 390 based controllers */
10429 /*-----------------------------------------------------------------*/
10431 gen390Code (iCode * lic)
10436 lineHead = lineCurr = NULL;
10438 if (options.model == MODEL_FLAT24) {
10439 fReturnSizeDS390 = 5;
10440 fReturn = fReturn24;
10442 fReturnSizeDS390 = 4;
10443 fReturn = fReturn16;
10444 options.stack10bit=0;
10448 /* print the allocation information */
10450 printAllocInfo (currFunc, codeOutFile);
10452 /* if debug information required */
10453 if (options.debug && currFunc)
10455 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
10457 if (IS_STATIC (currFunc->etype))
10458 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
10460 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
10463 /* stack pointer name */
10464 if (options.useXstack)
10470 for (ic = lic; ic; ic = ic->next)
10473 if (cln != ic->lineno)
10478 emitcode ("", "C$%s$%d$%d$%d ==.",
10479 FileBaseName (ic->filename), ic->lineno,
10480 ic->level, ic->block);
10483 emitcode (";", "%s %d", ic->filename, ic->lineno);
10486 /* if the result is marked as
10487 spilt and rematerializable or code for
10488 this has already been generated then
10490 if (resultRemat (ic) || ic->generated)
10493 /* depending on the operation */
10513 /* IPOP happens only when trying to restore a
10514 spilt live range, if there is an ifx statement
10515 following this pop then the if statement might
10516 be using some of the registers being popped which
10517 would destory the contents of the register so
10518 we need to check for this condition and handle it */
10520 ic->next->op == IFX &&
10521 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10522 genIfx (ic->next, ic);
10540 genEndFunction (ic);
10560 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10577 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10581 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10588 /* note these two are xlated by algebraic equivalence
10589 during parsing SDCC.y */
10590 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10591 "got '>=' or '<=' shouldn't have come here");
10595 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10607 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10611 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10615 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10639 genRightShift (ic);
10642 case GET_VALUE_AT_ADDRESS:
10643 genPointerGet (ic);
10647 if (POINTER_SET (ic))
10648 genPointerSet (ic);
10674 addSet (&_G.sendSet, ic);
10687 /* now we are ready to call the
10688 peep hole optimizer */
10689 if (!options.nopeep)
10690 peepHole (&lineHead);
10692 /* now do the actual printing */
10693 printLine (lineHead, codeOutFile);