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);
565 if (ptr_type == IPOINTER) {
572 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
576 sprintf (buffer, "(%s %c 0x%04x)",
577 OP_SYMBOL (IC_LEFT (ic))->rname,
578 val >= 0 ? '+' : '-',
581 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
583 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
584 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
585 /* set immd2 field if required */
586 if (aop->aopu.aop_immd.from_cast_remat) {
587 sprintf(buffer,"#0x%02x",ptr_type);
588 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
589 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
595 /*-----------------------------------------------------------------*/
596 /* regsInCommon - two operands have some registers in common */
597 /*-----------------------------------------------------------------*/
599 regsInCommon (operand * op1, operand * op2)
604 /* if they have registers in common */
605 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
608 sym1 = OP_SYMBOL (op1);
609 sym2 = OP_SYMBOL (op2);
611 if (sym1->nRegs == 0 || sym2->nRegs == 0)
614 for (i = 0; i < sym1->nRegs; i++)
620 for (j = 0; j < sym2->nRegs; j++)
625 if (sym2->regs[j] == sym1->regs[i])
633 /*-----------------------------------------------------------------*/
634 /* operandsEqu - equivalent */
635 /*-----------------------------------------------------------------*/
637 operandsEqu (operand * op1, operand * op2)
641 /* if they not symbols */
642 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
645 sym1 = OP_SYMBOL (op1);
646 sym2 = OP_SYMBOL (op2);
648 /* if both are itemps & one is spilt
649 and the other is not then false */
650 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
651 sym1->isspilt != sym2->isspilt)
654 /* if they are the same */
658 if (strcmp (sym1->rname, sym2->rname) == 0)
662 /* if left is a tmp & right is not */
663 if (IS_ITEMP (op1) &&
666 (sym1->usl.spillLoc == sym2))
669 if (IS_ITEMP (op2) &&
673 (sym2->usl.spillLoc == sym1))
679 /*-----------------------------------------------------------------*/
680 /* sameRegs - two asmops have the same registers */
681 /*-----------------------------------------------------------------*/
683 sameRegs (asmop * aop1, asmop * aop2)
689 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
696 if (aop1->type != AOP_REG ||
697 aop2->type != AOP_REG)
700 if (aop1->size != aop2->size)
703 for (i = 0; i < aop1->size; i++)
704 if (aop1->aopu.aop_reg[i] !=
705 aop2->aopu.aop_reg[i])
711 /*-----------------------------------------------------------------*/
712 /* aopOp - allocates an asmop for an operand : */
713 /*-----------------------------------------------------------------*/
715 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
724 /* if this a literal */
725 if (IS_OP_LITERAL (op))
727 op->aop = aop = newAsmop (AOP_LIT);
728 aop->aopu.aop_lit = op->operand.valOperand;
729 aop->size = getSize (operandType (op));
733 /* if already has a asmop then continue */
737 /* if the underlying symbol has a aop */
738 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
740 op->aop = OP_SYMBOL (op)->aop;
744 /* if this is a true symbol */
745 if (IS_TRUE_SYMOP (op))
747 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
751 /* this is a temporary : this has
757 e) can be a return use only */
759 sym = OP_SYMBOL (op);
762 /* if the type is a conditional */
763 if (sym->regType == REG_CND)
765 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
770 /* if it is spilt then two situations
772 b) has a spill location */
773 if (sym->isspilt || sym->nRegs == 0)
776 /* rematerialize it NOW */
779 sym->aop = op->aop = aop =
781 aop->size = getSize (sym->type);
788 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
789 aop->size = getSize (sym->type);
790 for (i = 0; i < 2; i++)
791 aop->aopu.aop_str[i] = accUse[i];
801 /* a AOP_STR uses DPTR, but DPTR is already in use;
804 fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use! for operand %s\n",sym->name);
807 aop = op->aop = sym->aop = newAsmop (AOP_STR);
808 aop->size = getSize (sym->type);
809 for (i = 0; i < (int) fReturnSizeDS390; i++)
810 aop->aopu.aop_str[i] = fReturn[i];
814 /* else spill location */
815 sym->aop = op->aop = aop =
816 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
817 aop->size = getSize (sym->type);
821 /* must be in a register */
822 sym->aop = op->aop = aop = newAsmop (AOP_REG);
823 aop->size = sym->nRegs;
824 for (i = 0; i < sym->nRegs; i++)
825 aop->aopu.aop_reg[i] = sym->regs[i];
828 /*-----------------------------------------------------------------*/
829 /* freeAsmop - free up the asmop given to an operand */
830 /*----------------------------------------------------------------*/
832 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
849 /* depending on the asmop type only three cases need work AOP_RO
850 , AOP_R1 && AOP_STK */
858 emitcode ("pop", "ar0");
862 bitVectUnSetBit (ic->rUsed, R0_IDX);
870 emitcode ("pop", "ar1");
874 bitVectUnSetBit (ic->rUsed, R1_IDX);
880 int stk = aop->aopu.aop_stk + aop->size;
881 bitVectUnSetBit (ic->rUsed, R0_IDX);
882 bitVectUnSetBit (ic->rUsed, R1_IDX);
884 getFreePtr (ic, &aop, FALSE);
886 if (options.stack10bit)
888 /* I'm not sure what to do here yet... */
891 "*** Warning: probably generating bad code for "
892 "10 bit stack mode.\n");
897 emitcode ("mov", "a,_bp");
898 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
899 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
903 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
908 emitcode ("pop", "acc");
909 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
912 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
915 freeAsmop (op, NULL, ic, TRUE);
918 emitcode ("pop", "ar0");
924 emitcode ("pop", "ar1");
931 /* all other cases just dealloc */
937 OP_SYMBOL (op)->aop = NULL;
938 /* if the symbol has a spill */
940 SPIL_LOC (op)->aop = NULL;
945 /*------------------------------------------------------------------*/
946 /* aopGet - for fetching value of the aop */
948 /* Set canClobberACC if you are sure it is OK to clobber the value */
949 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
950 /* just less efficient. */
951 /*------------------------------------------------------------------*/
963 /* offset is greater than
965 if (offset > (aop->size - 1) &&
966 aop->type != AOP_LIT)
969 /* depending on type */
975 /* if we need to increment it */
976 while (offset > aop->coff)
978 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
982 while (offset < aop->coff)
984 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
991 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
992 return (dname ? "acc" : "a");
994 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
995 rs = Safe_calloc (1, strlen (s) + 1);
1002 if (aop->type == AOP_DPTR2)
1008 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1014 while (offset > aop->coff)
1016 emitcode ("inc", "dptr");
1020 while (offset < aop->coff)
1022 emitcode ("lcall", "__decdptr");
1029 emitcode ("clr", "a");
1030 emitcode ("movc", "a,@a+dptr");
1034 emitcode ("movx", "a,@dptr");
1037 if (aop->type == AOP_DPTR2)
1043 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1044 return DP2_RESULT_REG;
1047 return (dname ? "acc" : "a");
1050 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1051 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1053 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1055 sprintf (s, "#(%s >> %d)",
1056 aop->aopu.aop_immd.aop_immd1,
1060 aop->aopu.aop_immd.aop_immd1);
1061 rs = Safe_calloc (1, strlen (s) + 1);
1067 sprintf (s, "(%s + %d)",
1071 sprintf (s, "%s", aop->aopu.aop_dir);
1072 rs = Safe_calloc (1, strlen (s) + 1);
1078 return aop->aopu.aop_reg[offset]->dname;
1080 return aop->aopu.aop_reg[offset]->name;
1083 emitcode ("clr", "a");
1084 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1085 emitcode ("rlc", "a");
1086 return (dname ? "acc" : "a");
1089 if (!offset && dname)
1091 return aop->aopu.aop_str[offset];
1094 return aopLiteral (aop->aopu.aop_lit, offset);
1098 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1102 return aop->aopu.aop_str[offset];
1106 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1107 "aopget got unsupported aop->type");
1110 /*-----------------------------------------------------------------*/
1111 /* aopPut - puts a string for a aop */
1112 /*-----------------------------------------------------------------*/
1114 aopPut (asmop * aop, char *s, int offset)
1118 if (aop->size && offset > (aop->size - 1))
1120 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1121 "aopPut got offset > aop->size");
1125 /* will assign value to value */
1126 /* depending on where it is ofcourse */
1131 sprintf (d, "(%s + %d)",
1132 aop->aopu.aop_dir, offset);
1134 sprintf (d, "%s", aop->aopu.aop_dir);
1137 emitcode ("mov", "%s,%s", d, s);
1142 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1143 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1146 strcmp (s, "r0") == 0 ||
1147 strcmp (s, "r1") == 0 ||
1148 strcmp (s, "r2") == 0 ||
1149 strcmp (s, "r3") == 0 ||
1150 strcmp (s, "r4") == 0 ||
1151 strcmp (s, "r5") == 0 ||
1152 strcmp (s, "r6") == 0 ||
1153 strcmp (s, "r7") == 0)
1154 emitcode ("mov", "%s,%s",
1155 aop->aopu.aop_reg[offset]->dname, s);
1157 emitcode ("mov", "%s,%s",
1158 aop->aopu.aop_reg[offset]->name, s);
1165 if (aop->type == AOP_DPTR2)
1173 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1174 "aopPut writting to code space");
1178 while (offset > aop->coff)
1181 emitcode ("inc", "dptr");
1184 while (offset < aop->coff)
1187 emitcode ("lcall", "__decdptr");
1192 /* if not in accumulater */
1195 emitcode ("movx", "@dptr,a");
1197 if (aop->type == AOP_DPTR2)
1205 while (offset > aop->coff)
1208 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1210 while (offset < aop->coff)
1213 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1220 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1226 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1228 else if (strcmp (s, "r0") == 0 ||
1229 strcmp (s, "r1") == 0 ||
1230 strcmp (s, "r2") == 0 ||
1231 strcmp (s, "r3") == 0 ||
1232 strcmp (s, "r4") == 0 ||
1233 strcmp (s, "r5") == 0 ||
1234 strcmp (s, "r6") == 0 ||
1235 strcmp (s, "r7") == 0)
1238 sprintf (buffer, "a%s", s);
1239 emitcode ("mov", "@%s,%s",
1240 aop->aopu.aop_ptr->name, buffer);
1243 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1248 if (strcmp (s, "a") == 0)
1249 emitcode ("push", "acc");
1253 emitcode ("push", "acc");
1255 emitcode ("push", s);
1261 /* if bit variable */
1262 if (!aop->aopu.aop_dir)
1264 emitcode ("clr", "a");
1265 emitcode ("rlc", "a");
1270 emitcode ("clr", "%s", aop->aopu.aop_dir);
1272 emitcode ("setb", "%s", aop->aopu.aop_dir);
1273 else if (!strcmp (s, "c"))
1274 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1277 if (strcmp (s, "a"))
1282 symbol *lbl = newiTempLabel (NULL);
1283 emitcode ("clr", "c");
1284 emitcode ("jz", "%05d$", lbl->key + 100);
1285 emitcode ("cpl", "c");
1286 emitcode ("", "%05d$:", lbl->key + 100);
1287 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1295 if (strcmp (aop->aopu.aop_str[offset], s))
1296 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1301 if (!offset && (strcmp (s, "acc") == 0))
1304 if (strcmp (aop->aopu.aop_str[offset], s))
1305 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1309 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1310 "aopPut got unsupported aop->type");
1317 /*--------------------------------------------------------------------*/
1318 /* reAdjustPreg - points a register back to where it should (coff==0) */
1319 /*--------------------------------------------------------------------*/
1321 reAdjustPreg (asmop * aop)
1323 if ((aop->coff==0) || (aop->size <= 1)) {
1332 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1336 if (aop->type == AOP_DPTR2)
1343 emitcode ("lcall", "__decdptr");
1346 if (aop->type == AOP_DPTR2)
1356 #define AOP(op) op->aop
1357 #define AOP_TYPE(op) AOP(op)->type
1358 #define AOP_SIZE(op) AOP(op)->size
1359 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1360 AOP_TYPE(x) == AOP_R0))
1362 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1363 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1366 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1367 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1368 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1370 /* Workaround for DS80C390 bug: div ab may return bogus results
1371 * if A is accessed in instruction immediately before the div.
1373 * Will be fixed in B4 rev of processor, Dallas claims.
1376 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1377 if (!AOP_NEEDSACC(RIGHT)) \
1379 /* We can load A first, then B, since \
1380 * B (the RIGHT operand) won't clobber A, \
1381 * thus avoiding touching A right before the div. \
1383 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1384 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1386 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1390 /* Just stuff in a nop after loading A. */ \
1391 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1392 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1394 emitcode("nop", "; workaround for DS80C390 div bug."); \
1397 /*-----------------------------------------------------------------*/
1398 /* genNotFloat - generates not for float operations */
1399 /*-----------------------------------------------------------------*/
1401 genNotFloat (operand * op, operand * res)
1407 D (emitcode (";", "genNotFloat ");
1410 /* we will put 127 in the first byte of
1412 aopPut (AOP (res), "#127", 0);
1413 size = AOP_SIZE (op) - 1;
1416 _startLazyDPSEvaluation ();
1417 l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1422 emitcode ("orl", "a,%s",
1424 offset++, FALSE, FALSE, FALSE));
1426 _endLazyDPSEvaluation ();
1428 tlbl = newiTempLabel (NULL);
1429 aopPut (res->aop, one, 1);
1430 emitcode ("jz", "%05d$", (tlbl->key + 100));
1431 aopPut (res->aop, zero, 1);
1432 emitcode ("", "%05d$:", (tlbl->key + 100));
1434 size = res->aop->size - 2;
1436 /* put zeros in the rest */
1438 aopPut (res->aop, zero, offset++);
1441 /*-----------------------------------------------------------------*/
1442 /* opIsGptr: returns non-zero if the passed operand is */
1443 /* a generic pointer type. */
1444 /*-----------------------------------------------------------------*/
1446 opIsGptr (operand * op)
1448 sym_link *type = operandType (op);
1450 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1457 /*-----------------------------------------------------------------*/
1458 /* getDataSize - get the operand data size */
1459 /*-----------------------------------------------------------------*/
1461 getDataSize (operand * op)
1464 size = AOP_SIZE (op);
1465 if (size == GPTRSIZE)
1467 sym_link *type = operandType (op);
1468 if (IS_GENPTR (type))
1470 /* generic pointer; arithmetic operations
1471 * should ignore the high byte (pointer type).
1479 /*-----------------------------------------------------------------*/
1480 /* outAcc - output Acc */
1481 /*-----------------------------------------------------------------*/
1483 outAcc (operand * result)
1486 size = getDataSize (result);
1489 aopPut (AOP (result), "a", 0);
1492 /* unsigned or positive */
1495 aopPut (AOP (result), zero, offset++);
1500 /*-----------------------------------------------------------------*/
1501 /* outBitC - output a bit C */
1502 /*-----------------------------------------------------------------*/
1504 outBitC (operand * result)
1506 /* if the result is bit */
1507 if (AOP_TYPE (result) == AOP_CRY)
1509 aopPut (AOP (result), "c", 0);
1513 emitcode ("clr", "a");
1514 emitcode ("rlc", "a");
1519 /*-----------------------------------------------------------------*/
1520 /* toBoolean - emit code for orl a,operator(sizeop) */
1521 /*-----------------------------------------------------------------*/
1523 toBoolean (operand * oper)
1525 int size = AOP_SIZE (oper) - 1;
1529 /* The generic part of a generic pointer should
1530 * not participate in it's truth value.
1532 * i.e. 0x10000000 is zero.
1534 if (opIsGptr (oper))
1536 D (emitcode (";", "toBoolean: generic ptr special case.");
1541 _startLazyDPSEvaluation ();
1542 if (AOP_NEEDSACC (oper) && size)
1545 emitcode ("push", "b");
1546 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1550 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1556 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1560 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1563 _endLazyDPSEvaluation ();
1567 emitcode ("mov", "a,b");
1568 emitcode ("pop", "b");
1573 /*-----------------------------------------------------------------*/
1574 /* genNot - generate code for ! operation */
1575 /*-----------------------------------------------------------------*/
1580 sym_link *optype = operandType (IC_LEFT (ic));
1582 D (emitcode (";", "genNot ");
1585 /* assign asmOps to operand & result */
1586 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1587 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1589 /* if in bit space then a special case */
1590 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1592 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1593 emitcode ("cpl", "c");
1594 outBitC (IC_RESULT (ic));
1598 /* if type float then do float */
1599 if (IS_FLOAT (optype))
1601 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1605 toBoolean (IC_LEFT (ic));
1607 tlbl = newiTempLabel (NULL);
1608 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1609 emitcode ("", "%05d$:", tlbl->key + 100);
1610 outBitC (IC_RESULT (ic));
1613 /* release the aops */
1614 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1615 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1619 /*-----------------------------------------------------------------*/
1620 /* genCpl - generate code for complement */
1621 /*-----------------------------------------------------------------*/
1628 D (emitcode (";", "genCpl ");
1632 /* assign asmOps to operand & result */
1633 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1634 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1636 /* if both are in bit space then
1638 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1639 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1642 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1643 emitcode ("cpl", "c");
1644 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1648 size = AOP_SIZE (IC_RESULT (ic));
1649 _startLazyDPSEvaluation ();
1652 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1654 emitcode ("cpl", "a");
1655 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1657 _endLazyDPSEvaluation ();
1661 /* release the aops */
1662 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1663 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1666 /*-----------------------------------------------------------------*/
1667 /* genUminusFloat - unary minus for floating points */
1668 /*-----------------------------------------------------------------*/
1670 genUminusFloat (operand * op, operand * result)
1672 int size, offset = 0;
1674 /* for this we just need to flip the
1675 first it then copy the rest in place */
1676 D (emitcode (";", "genUminusFloat");
1679 _startLazyDPSEvaluation ();
1680 size = AOP_SIZE (op) - 1;
1681 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1684 emitcode ("cpl", "acc.7");
1685 aopPut (AOP (result), "a", 3);
1689 aopPut (AOP (result),
1690 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1694 _endLazyDPSEvaluation ();
1697 /*-----------------------------------------------------------------*/
1698 /* genUminus - unary minus code generation */
1699 /*-----------------------------------------------------------------*/
1701 genUminus (iCode * ic)
1704 sym_link *optype, *rtype;
1706 D (emitcode (";", "genUminus ");
1711 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1712 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1714 /* if both in bit space then special
1716 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1717 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1720 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1721 emitcode ("cpl", "c");
1722 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1726 optype = operandType (IC_LEFT (ic));
1727 rtype = operandType (IC_RESULT (ic));
1729 /* if float then do float stuff */
1730 if (IS_FLOAT (optype))
1732 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1736 /* otherwise subtract from zero */
1737 size = AOP_SIZE (IC_LEFT (ic));
1739 _startLazyDPSEvaluation ();
1742 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1743 if (!strcmp (l, "a"))
1747 emitcode ("cpl", "a");
1748 emitcode ("addc", "a,#0");
1754 emitcode ("clr", "a");
1755 emitcode ("subb", "a,%s", l);
1757 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1759 _endLazyDPSEvaluation ();
1761 /* if any remaining bytes in the result */
1762 /* we just need to propagate the sign */
1763 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1765 emitcode ("rlc", "a");
1766 emitcode ("subb", "a,acc");
1768 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1772 /* release the aops */
1773 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1774 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1777 /*-----------------------------------------------------------------*/
1778 /* saveRegisters - will look for a call and save the registers */
1779 /*-----------------------------------------------------------------*/
1781 saveRegisters (iCode * lic)
1789 for (ic = lic; ic; ic = ic->next)
1790 if (ic->op == CALL || ic->op == PCALL)
1795 fprintf (stderr, "found parameter push with no function call\n");
1799 /* if the registers have been saved already then
1801 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type) ||
1802 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))))
1805 /* find the registers in use at this time
1806 and push them away to safety */
1807 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1811 if (options.useXstack)
1813 if (bitVectBitValue (rsave, R0_IDX))
1814 emitcode ("mov", "b,r0");
1815 emitcode ("mov", "r0,%s", spname);
1816 for (i = 0; i < ds390_nRegs; i++)
1818 if (bitVectBitValue (rsave, i))
1821 emitcode ("mov", "a,b");
1823 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1824 emitcode ("movx", "@r0,a");
1825 emitcode ("inc", "r0");
1828 emitcode ("mov", "%s,r0", spname);
1829 if (bitVectBitValue (rsave, R0_IDX))
1830 emitcode ("mov", "r0,b");
1833 for (i = 0; i < ds390_nRegs; i++)
1835 if (bitVectBitValue (rsave, i))
1836 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1839 detype = getSpec (operandType (IC_LEFT (ic)));
1842 /*-----------------------------------------------------------------*/
1843 /* unsaveRegisters - pop the pushed registers */
1844 /*-----------------------------------------------------------------*/
1846 unsaveRegisters (iCode * ic)
1850 /* find the registers in use at this time
1851 and push them away to safety */
1852 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1855 if (options.useXstack)
1857 emitcode ("mov", "r0,%s", spname);
1858 for (i = ds390_nRegs; i >= 0; i--)
1860 if (bitVectBitValue (rsave, i))
1862 emitcode ("dec", "r0");
1863 emitcode ("movx", "a,@r0");
1865 emitcode ("mov", "b,a");
1867 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1871 emitcode ("mov", "%s,r0", spname);
1872 if (bitVectBitValue (rsave, R0_IDX))
1873 emitcode ("mov", "r0,b");
1876 for (i = ds390_nRegs; i >= 0; i--)
1878 if (bitVectBitValue (rsave, i))
1879 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1885 /*-----------------------------------------------------------------*/
1887 /*-----------------------------------------------------------------*/
1889 pushSide (operand * oper, int size)
1892 _startLazyDPSEvaluation ();
1895 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1896 if (AOP_TYPE (oper) != AOP_REG &&
1897 AOP_TYPE (oper) != AOP_DIR &&
1900 emitcode ("mov", "a,%s", l);
1901 emitcode ("push", "acc");
1904 emitcode ("push", "%s", l);
1906 _endLazyDPSEvaluation ();
1909 /*-----------------------------------------------------------------*/
1910 /* assignResultValue - */
1911 /*-----------------------------------------------------------------*/
1913 assignResultValue (operand * oper)
1916 int size = AOP_SIZE (oper);
1918 _startLazyDPSEvaluation ();
1921 aopPut (AOP (oper), fReturn[offset], offset);
1924 _endLazyDPSEvaluation ();
1928 /*-----------------------------------------------------------------*/
1929 /* genXpush - pushes onto the external stack */
1930 /*-----------------------------------------------------------------*/
1932 genXpush (iCode * ic)
1934 asmop *aop = newAsmop (0);
1936 int size, offset = 0;
1938 D (emitcode (";", "genXpush ");
1941 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1942 r = getFreePtr (ic, &aop, FALSE);
1945 emitcode ("mov", "%s,_spx", r->name);
1947 size = AOP_SIZE (IC_LEFT (ic));
1948 _startLazyDPSEvaluation ();
1952 char *l = aopGet (AOP (IC_LEFT (ic)),
1953 offset++, FALSE, FALSE, TRUE);
1955 emitcode ("movx", "@%s,a", r->name);
1956 emitcode ("inc", "%s", r->name);
1959 _endLazyDPSEvaluation ();
1962 emitcode ("mov", "_spx,%s", r->name);
1964 freeAsmop (NULL, aop, ic, TRUE);
1965 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1968 /*-----------------------------------------------------------------*/
1969 /* genIpush - genrate code for pushing this gets a little complex */
1970 /*-----------------------------------------------------------------*/
1972 genIpush (iCode * ic)
1974 int size, offset = 0;
1977 D (emitcode (";", "genIpush ");
1980 /* if this is not a parm push : ie. it is spill push
1981 and spill push is always done on the local stack */
1985 /* and the item is spilt then do nothing */
1986 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1989 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1990 size = AOP_SIZE (IC_LEFT (ic));
1991 /* push it on the stack */
1992 _startLazyDPSEvaluation ();
1995 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
2001 emitcode ("push", "%s", l);
2003 _endLazyDPSEvaluation ();
2007 /* this is a paramter push: in this case we call
2008 the routine to find the call and save those
2009 registers that need to be saved */
2012 /* if use external stack then call the external
2013 stack pushing routine */
2014 if (options.useXstack)
2020 /* then do the push */
2021 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2023 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2024 size = AOP_SIZE (IC_LEFT (ic));
2026 _startLazyDPSEvaluation ();
2029 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2030 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2031 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2034 emitcode ("mov", "a,%s", l);
2035 emitcode ("push", "acc");
2038 emitcode ("push", "%s", l);
2040 _endLazyDPSEvaluation ();
2042 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2045 /*-----------------------------------------------------------------*/
2046 /* genIpop - recover the registers: can happen only for spilling */
2047 /*-----------------------------------------------------------------*/
2049 genIpop (iCode * ic)
2053 D (emitcode (";", "genIpop ");
2057 /* if the temp was not pushed then */
2058 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2061 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2062 size = AOP_SIZE (IC_LEFT (ic));
2063 offset = (size - 1);
2064 _startLazyDPSEvaluation ();
2067 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2068 FALSE, TRUE, TRUE));
2070 _endLazyDPSEvaluation ();
2072 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2075 /*-----------------------------------------------------------------*/
2076 /* unsaveRBank - restores the resgister bank from stack */
2077 /*-----------------------------------------------------------------*/
2079 unsaveRBank (int bank, iCode * ic, bool popPsw)
2085 if (options.useXstack)
2089 /* Assume r0 is available for use. */
2090 r = ds390_regWithIdx (R0_IDX);;
2095 r = getFreePtr (ic, &aop, FALSE);
2097 emitcode ("mov", "%s,_spx", r->name);
2102 if (options.useXstack)
2104 emitcode ("movx", "a,@%s", r->name);
2105 emitcode ("mov", "psw,a");
2106 emitcode ("dec", "%s", r->name);
2110 emitcode ("pop", "psw");
2114 for (i = (ds390_nRegs - 1); i >= 0; i--)
2116 if (options.useXstack)
2118 emitcode ("movx", "a,@%s", r->name);
2119 emitcode ("mov", "(%s+%d),a",
2120 regs390[i].base, 8 * bank + regs390[i].offset);
2121 emitcode ("dec", "%s", r->name);
2125 emitcode ("pop", "(%s+%d)",
2126 regs390[i].base, 8 * bank + regs390[i].offset);
2129 if (options.useXstack)
2131 emitcode ("mov", "_spx,%s", r->name);
2136 freeAsmop (NULL, aop, ic, TRUE);
2140 /*-----------------------------------------------------------------*/
2141 /* saveRBank - saves an entire register bank on the stack */
2142 /*-----------------------------------------------------------------*/
2144 saveRBank (int bank, iCode * ic, bool pushPsw)
2150 if (options.useXstack)
2154 /* Assume r0 is available for use. */
2155 r = ds390_regWithIdx (R0_IDX);;
2160 r = getFreePtr (ic, &aop, FALSE);
2162 emitcode ("mov", "%s,_spx", r->name);
2165 for (i = 0; i < ds390_nRegs; i++)
2167 if (options.useXstack)
2169 emitcode ("inc", "%s", r->name);
2170 emitcode ("mov", "a,(%s+%d)",
2171 regs390[i].base, 8 * bank + regs390[i].offset);
2172 emitcode ("movx", "@%s,a", r->name);
2175 emitcode ("push", "(%s+%d)",
2176 regs390[i].base, 8 * bank + regs390[i].offset);
2181 if (options.useXstack)
2183 emitcode ("mov", "a,psw");
2184 emitcode ("movx", "@%s,a", r->name);
2185 emitcode ("inc", "%s", r->name);
2186 emitcode ("mov", "_spx,%s", r->name);
2190 emitcode ("push", "psw");
2193 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2198 freeAsmop (NULL, aop, ic, TRUE);
2207 /*-----------------------------------------------------------------*/
2208 /* genCall - generates a call statement */
2209 /*-----------------------------------------------------------------*/
2211 genCall (iCode * ic)
2214 bool restoreBank = FALSE;
2215 bool swapBanks = FALSE;
2217 D (emitcode (";", "genCall "););
2219 /* if we are calling a not _naked function that is not using
2220 the same register bank then we need to save the
2221 destination registers on the stack */
2222 dtype = operandType (IC_LEFT (ic));
2223 if (dtype && !IFFUNC_ISNAKED(dtype) &&
2224 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2225 IFFUNC_ISISR (currFunc->type))
2229 /* This is unexpected; the bank should have been saved in
2232 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2238 /* if caller saves & we have not saved then */
2242 /* if send set is not empty the assign */
2243 /* We've saved all the registers we care about;
2244 * therefore, we may clobber any register not used
2245 * in the calling convention (i.e. anything not in
2252 for (sic = setFirstItem (_G.sendSet); sic;
2253 sic = setNextItem (_G.sendSet))
2255 int size, offset = 0;
2257 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2258 size = AOP_SIZE (IC_LEFT (sic));
2260 _startLazyDPSEvaluation ();
2263 char *l = aopGet (AOP(IC_LEFT(sic)), offset,
2264 FALSE, FALSE, TRUE);
2265 if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size)
2267 emitcode("mov", "%s,%s", regs390[offset].name, l);
2269 else if (strcmp (l, fReturn[offset]))
2271 emitcode ("mov", "%s,%s",
2277 _endLazyDPSEvaluation ();
2278 if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR)
2280 size = AOP_SIZE (IC_LEFT (sic));
2288 emitcode("mov", "%s,%s",
2289 fReturn[size], regs390[size].name);
2292 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2299 emitcode ("mov", "psw,#0x%02x",
2300 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2304 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2305 OP_SYMBOL (IC_LEFT (ic))->rname :
2306 OP_SYMBOL (IC_LEFT (ic))->name));
2310 emitcode ("mov", "psw,#0x%02x",
2311 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2314 /* if we need assign a result value */
2315 if ((IS_ITEMP (IC_RESULT (ic)) &&
2316 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2317 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2318 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2319 IS_TRUE_SYMOP (IC_RESULT (ic)))
2321 if (isOperandInFarSpace (IC_RESULT (ic))
2322 && getSize (operandType (IC_RESULT (ic))) <= 2)
2324 int size = getSize (operandType (IC_RESULT (ic)));
2326 /* Special case for 1 or 2 byte return in far space. */
2330 emitcode ("mov", "b,%s", fReturn[1]);
2333 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2334 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2338 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2340 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2345 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2348 assignResultValue (IC_RESULT (ic));
2350 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2354 /* adjust the stack for parameters if
2359 if (ic->parmBytes > 3)
2361 emitcode ("mov", "a,%s", spname);
2362 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2363 emitcode ("mov", "%s,a", spname);
2366 for (i = 0; i < ic->parmBytes; i++)
2367 emitcode ("dec", "%s", spname);
2370 /* if we hade saved some registers then unsave them */
2371 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2372 unsaveRegisters (ic);
2374 /* if register bank was saved then pop them */
2376 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2379 /*-----------------------------------------------------------------*/
2380 /* genPcall - generates a call by pointer statement */
2381 /*-----------------------------------------------------------------*/
2383 genPcall (iCode * ic)
2386 symbol *rlbl = newiTempLabel (NULL);
2387 bool restoreBank=FALSE;
2389 D (emitcode (";", "genPcall ");
2393 /* if caller saves & we have not saved then */
2397 /* if we are calling a function that is not using
2398 the same register bank then we need to save the
2399 destination registers on the stack */
2400 dtype = operandType (IC_LEFT (ic));
2401 if (dtype && !IFFUNC_ISNAKED(dtype) &&
2402 IFFUNC_ISISR (currFunc->type) &&
2403 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2404 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2408 /* push the return address on to the stack */
2409 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2410 emitcode ("push", "acc");
2411 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2412 emitcode ("push", "acc");
2414 if (options.model == MODEL_FLAT24)
2416 emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2417 emitcode ("push", "acc");
2420 /* now push the calling address */
2421 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2423 pushSide (IC_LEFT (ic), FPTRSIZE);
2425 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2427 /* if send set is not empty the assign */
2432 for (sic = setFirstItem (_G.sendSet); sic;
2433 sic = setNextItem (_G.sendSet))
2435 int size, offset = 0;
2437 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2438 size = AOP_SIZE (IC_LEFT (sic));
2439 _startLazyDPSEvaluation ();
2442 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2443 FALSE, FALSE, TRUE);
2444 if (strcmp (l, fReturn[offset]))
2446 emitcode ("mov", "%s,%s",
2452 _endLazyDPSEvaluation ();
2453 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2458 emitcode ("ret", "");
2459 emitcode ("", "%05d$:", (rlbl->key + 100));
2462 /* if we need assign a result value */
2463 if ((IS_ITEMP (IC_RESULT (ic)) &&
2464 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2465 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2466 IS_TRUE_SYMOP (IC_RESULT (ic)))
2470 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2473 assignResultValue (IC_RESULT (ic));
2475 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2478 /* adjust the stack for parameters if
2483 if (ic->parmBytes > 3)
2485 emitcode ("mov", "a,%s", spname);
2486 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2487 emitcode ("mov", "%s,a", spname);
2490 for (i = 0; i < ic->parmBytes; i++)
2491 emitcode ("dec", "%s", spname);
2495 /* if register bank was saved then unsave them */
2497 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2499 /* if we hade saved some registers then
2501 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2502 unsaveRegisters (ic);
2506 /*-----------------------------------------------------------------*/
2507 /* resultRemat - result is rematerializable */
2508 /*-----------------------------------------------------------------*/
2510 resultRemat (iCode * ic)
2512 if (SKIP_IC (ic) || ic->op == IFX)
2515 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2517 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2518 if (sym->remat && !POINTER_SET (ic))
2525 #if defined(__BORLANDC__) || defined(_MSC_VER)
2526 #define STRCASECMP stricmp
2528 #define STRCASECMP strcasecmp
2531 /*-----------------------------------------------------------------*/
2532 /* inExcludeList - return 1 if the string is in exclude Reg list */
2533 /*-----------------------------------------------------------------*/
2535 inExcludeList (char *s)
2539 if (options.excludeRegs[i] &&
2540 STRCASECMP (options.excludeRegs[i], "none") == 0)
2543 for (i = 0; options.excludeRegs[i]; i++)
2545 if (options.excludeRegs[i] &&
2546 STRCASECMP (s, options.excludeRegs[i]) == 0)
2552 /*-----------------------------------------------------------------*/
2553 /* genFunction - generated code for function entry */
2554 /*-----------------------------------------------------------------*/
2556 genFunction (iCode * ic)
2560 bool switchedPSW = FALSE;
2562 D (emitcode (";", "genFunction "););
2565 /* create the function header */
2566 emitcode (";", "-----------------------------------------");
2567 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2568 emitcode (";", "-----------------------------------------");
2570 emitcode ("", "%s:", sym->rname);
2571 ftype = operandType (IC_LEFT (ic));
2573 if (IFFUNC_ISNAKED(ftype))
2575 emitcode(";", "naked function: no prologue.");
2579 /* if critical function then turn interrupts off */
2580 if (IFFUNC_ISCRITICAL (ftype))
2581 emitcode ("clr", "ea");
2583 /* here we need to generate the equates for the
2584 register bank if required */
2585 if (FUNC_REGBANK (ftype) != rbank)
2589 rbank = FUNC_REGBANK (ftype);
2590 for (i = 0; i < ds390_nRegs; i++)
2592 if (regs390[i].print) {
2593 if (strcmp (regs390[i].base, "0") == 0)
2594 emitcode ("", "%s = 0x%02x",
2596 8 * rbank + regs390[i].offset);
2598 emitcode ("", "%s = %s + 0x%02x",
2601 8 * rbank + regs390[i].offset);
2606 /* if this is an interrupt service routine then
2607 save acc, b, dpl, dph */
2608 if (IFFUNC_ISISR (sym->type))
2611 if (!inExcludeList ("acc"))
2612 emitcode ("push", "acc");
2613 if (!inExcludeList ("b"))
2614 emitcode ("push", "b");
2615 if (!inExcludeList ("dpl"))
2616 emitcode ("push", "dpl");
2617 if (!inExcludeList ("dph"))
2618 emitcode ("push", "dph");
2619 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2621 emitcode ("push", "dpx");
2622 /* Make sure we're using standard DPTR */
2623 emitcode ("push", "dps");
2624 emitcode ("mov", "dps, #0x00");
2625 if (options.stack10bit)
2627 /* This ISR could conceivably use DPTR2. Better save it. */
2628 emitcode ("push", "dpl1");
2629 emitcode ("push", "dph1");
2630 emitcode ("push", "dpx1");
2631 emitcode ("push", DP2_RESULT_REG);
2634 /* if this isr has no bank i.e. is going to
2635 run with bank 0 , then we need to save more
2637 if (!FUNC_REGBANK (sym->type))
2640 /* if this function does not call any other
2641 function then we can be economical and
2642 save only those registers that are used */
2643 if (!IFFUNC_HASFCALL(sym->type))
2647 /* if any registers used */
2650 /* save the registers used */
2651 for (i = 0; i < sym->regsUsed->size; i++)
2653 if (bitVectBitValue (sym->regsUsed, i) ||
2654 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2655 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2662 /* this function has a function call cannot
2663 determines register usage so we will have to push the
2665 saveRBank (0, ic, FALSE);
2670 /* This ISR uses a non-zero bank.
2672 * We assume that the bank is available for our
2675 * However, if this ISR calls a function which uses some
2676 * other bank, we must save that bank entirely.
2678 unsigned long banksToSave = 0;
2680 if (IFFUNC_HASFCALL(sym->type))
2683 #define MAX_REGISTER_BANKS 4
2688 for (i = ic; i; i = i->next)
2690 if (i->op == ENDFUNCTION)
2692 /* we got to the end OK. */
2700 dtype = operandType (IC_LEFT(i));
2702 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2704 /* Mark this bank for saving. */
2705 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2707 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2711 banksToSave |= (1 << FUNC_REGBANK(dtype));
2714 /* And note that we don't need to do it in
2722 /* This is a mess; we have no idea what
2723 * register bank the called function might
2726 * The only thing I can think of to do is
2727 * throw a warning and hope.
2729 werror(W_FUNCPTR_IN_USING_ISR);
2733 if (banksToSave && options.useXstack)
2735 /* Since we aren't passing it an ic,
2736 * saveRBank will assume r0 is available to abuse.
2738 * So switch to our (trashable) bank now, so
2739 * the caller's R0 isn't trashed.
2741 emitcode ("push", "psw");
2742 emitcode ("mov", "psw,#0x%02x",
2743 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2747 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2749 if (banksToSave & (1 << ix))
2751 saveRBank(ix, NULL, FALSE);
2755 // jwk: this needs a closer look
2756 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2761 /* if callee-save to be used for this function
2762 then save the registers being used in this function */
2763 if (IFFUNC_CALLEESAVES(sym->type))
2767 /* if any registers used */
2770 /* save the registers used */
2771 for (i = 0; i < sym->regsUsed->size; i++)
2773 if (bitVectBitValue (sym->regsUsed, i) ||
2774 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2776 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2784 /* set the register bank to the desired value */
2785 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2788 emitcode ("push", "psw");
2789 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2792 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2795 if (options.useXstack)
2797 emitcode ("mov", "r0,%s", spname);
2798 emitcode ("mov", "a,_bp");
2799 emitcode ("movx", "@r0,a");
2800 emitcode ("inc", "%s", spname);
2804 /* set up the stack */
2805 emitcode ("push", "_bp"); /* save the callers stack */
2807 emitcode ("mov", "_bp,%s", spname);
2810 /* adjust the stack for the function */
2816 werror (W_STACK_OVERFLOW, sym->name);
2818 if (i > 3 && sym->recvSize < 4)
2821 emitcode ("mov", "a,sp");
2822 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2823 emitcode ("mov", "sp,a");
2828 emitcode ("inc", "sp");
2834 emitcode ("mov", "a,_spx");
2835 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2836 emitcode ("mov", "_spx,a");
2841 /*-----------------------------------------------------------------*/
2842 /* genEndFunction - generates epilogue for functions */
2843 /*-----------------------------------------------------------------*/
2845 genEndFunction (iCode * ic)
2847 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2849 D (emitcode (";", "genEndFunction "););
2851 if (IFFUNC_ISNAKED(sym->type))
2853 emitcode(";", "naked function: no epilogue.");
2857 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2859 emitcode ("mov", "%s,_bp", spname);
2862 /* if use external stack but some variables were
2863 added to the local stack then decrement the
2865 if (options.useXstack && sym->stack)
2867 emitcode ("mov", "a,sp");
2868 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2869 emitcode ("mov", "sp,a");
2873 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2875 if (options.useXstack)
2877 emitcode ("mov", "r0,%s", spname);
2878 emitcode ("movx", "a,@r0");
2879 emitcode ("mov", "_bp,a");
2880 emitcode ("dec", "%s", spname);
2884 emitcode ("pop", "_bp");
2888 /* restore the register bank */
2889 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2891 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
2892 || !options.useXstack)
2894 /* Special case of ISR using non-zero bank with useXstack
2897 emitcode ("pop", "psw");
2901 if (IFFUNC_ISISR (sym->type))
2904 /* now we need to restore the registers */
2905 /* if this isr has no bank i.e. is going to
2906 run with bank 0 , then we need to save more
2908 if (!FUNC_REGBANK (sym->type))
2910 /* if this function does not call any other
2911 function then we can be economical and
2912 save only those registers that are used */
2913 if (!IFFUNC_HASFCALL(sym->type))
2917 /* if any registers used */
2920 /* save the registers used */
2921 for (i = sym->regsUsed->size; i >= 0; i--)
2923 if (bitVectBitValue (sym->regsUsed, i) ||
2924 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2925 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2932 /* this function has a function call cannot
2933 determines register usage so we will have to pop the
2935 unsaveRBank (0, ic, FALSE);
2940 /* This ISR uses a non-zero bank.
2942 * Restore any register banks saved by genFunction
2945 // jwk: this needs a closer look
2946 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2949 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2951 if (savedBanks & (1 << ix))
2953 unsaveRBank(ix, NULL, FALSE);
2957 if (options.useXstack)
2959 /* Restore bank AFTER calling unsaveRBank,
2960 * since it can trash r0.
2962 emitcode ("pop", "psw");
2966 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2968 if (options.stack10bit)
2970 emitcode ("pop", DP2_RESULT_REG);
2971 emitcode ("pop", "dpx1");
2972 emitcode ("pop", "dph1");
2973 emitcode ("pop", "dpl1");
2975 emitcode ("pop", "dps");
2976 emitcode ("pop", "dpx");
2978 if (!inExcludeList ("dph"))
2979 emitcode ("pop", "dph");
2980 if (!inExcludeList ("dpl"))
2981 emitcode ("pop", "dpl");
2982 if (!inExcludeList ("b"))
2983 emitcode ("pop", "b");
2984 if (!inExcludeList ("acc"))
2985 emitcode ("pop", "acc");
2987 if (IFFUNC_ISCRITICAL (sym->type))
2988 emitcode ("setb", "ea");
2990 /* if debug then send end of function */
2991 if (options.debug && currFunc) {
2993 emitcode ("", "C$%s$%d$%d$%d ==.",
2994 FileBaseName (ic->filename), currFunc->lastLine,
2995 ic->level, ic->block);
2996 if (IS_STATIC (currFunc->etype))
2997 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2999 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3003 emitcode ("reti", "");
3007 if (IFFUNC_ISCRITICAL (sym->type))
3008 emitcode ("setb", "ea");
3010 if (IFFUNC_CALLEESAVES(sym->type))
3014 /* if any registers used */
3017 /* save the registers used */
3018 for (i = sym->regsUsed->size; i >= 0; i--)
3020 if (bitVectBitValue (sym->regsUsed, i) ||
3021 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3022 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3028 /* if debug then send end of function */
3029 if (options.debug && currFunc)
3032 emitcode ("", "C$%s$%d$%d$%d ==.",
3033 FileBaseName (ic->filename), currFunc->lastLine,
3034 ic->level, ic->block);
3035 if (IS_STATIC (currFunc->etype))
3036 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3038 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3042 emitcode ("ret", "");
3047 /*-----------------------------------------------------------------*/
3048 /* genRet - generate code for return statement */
3049 /*-----------------------------------------------------------------*/
3053 int size, offset = 0, pushed = 0;
3055 D (emitcode (";", "genRet ");
3058 /* if we have no return value then
3059 just generate the "ret" */
3063 /* we have something to return then
3064 move the return value into place */
3065 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
3066 size = AOP_SIZE (IC_LEFT (ic));
3068 _startLazyDPSEvaluation ();
3072 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3074 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3075 FALSE, TRUE, FALSE);
3076 emitcode ("push", "%s", l);
3081 /* Since A is the last element of fReturn,
3082 * is is OK to clobber it in the aopGet.
3084 l = aopGet (AOP (IC_LEFT (ic)), offset,
3085 FALSE, FALSE, TRUE);
3086 if (strcmp (fReturn[offset], l))
3087 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3090 _endLazyDPSEvaluation ();
3097 if (strcmp (fReturn[pushed], "a"))
3098 emitcode ("pop", fReturn[pushed]);
3100 emitcode ("pop", "acc");
3103 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3106 /* generate a jump to the return label
3107 if the next is not the return statement */
3108 if (!(ic->next && ic->next->op == LABEL &&
3109 IC_LABEL (ic->next) == returnLabel))
3111 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3115 /*-----------------------------------------------------------------*/
3116 /* genLabel - generates a label */
3117 /*-----------------------------------------------------------------*/
3119 genLabel (iCode * ic)
3121 /* special case never generate */
3122 if (IC_LABEL (ic) == entryLabel)
3125 D (emitcode (";", "genLabel ");
3128 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3131 /*-----------------------------------------------------------------*/
3132 /* genGoto - generates a ljmp */
3133 /*-----------------------------------------------------------------*/
3135 genGoto (iCode * ic)
3137 D (emitcode (";", "genGoto ");
3139 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3142 /*-----------------------------------------------------------------*/
3143 /* findLabelBackwards: walks back through the iCode chain looking */
3144 /* for the given label. Returns number of iCode instructions */
3145 /* between that label and given ic. */
3146 /* Returns zero if label not found. */
3147 /*-----------------------------------------------------------------*/
3149 findLabelBackwards (iCode * ic, int key)
3158 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3160 /* printf("findLabelBackwards = %d\n", count); */
3168 /*-----------------------------------------------------------------*/
3169 /* genPlusIncr :- does addition with increment if possible */
3170 /*-----------------------------------------------------------------*/
3172 genPlusIncr (iCode * ic)
3174 unsigned int icount;
3175 unsigned int size = getDataSize (IC_RESULT (ic));
3177 /* will try to generate an increment */
3178 /* if the right side is not a literal
3180 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3183 /* if the literal value of the right hand side
3184 is greater than 4 then it is not worth it */
3185 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3188 /* if increment 16 bits in register */
3190 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3191 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3192 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3200 /* If the next instruction is a goto and the goto target
3201 * is <= 5 instructions previous to this, we can generate
3202 * jumps straight to that target.
3204 if (ic->next && ic->next->op == GOTO
3205 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3208 emitcode (";", "tail increment optimized (range %d)", labelRange);
3209 tlbl = IC_LABEL (ic->next);
3214 tlbl = newiTempLabel (NULL);
3217 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3218 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3219 IS_AOP_PREG (IC_RESULT (ic)))
3220 emitcode ("cjne", "%s,#0x00,%05d$"
3221 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3225 emitcode ("clr", "a");
3226 emitcode ("cjne", "a,%s,%05d$"
3227 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3231 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3234 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3235 IS_AOP_PREG (IC_RESULT (ic)))
3236 emitcode ("cjne", "%s,#0x00,%05d$"
3237 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3240 emitcode ("cjne", "a,%s,%05d$"
3241 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3244 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3248 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3249 IS_AOP_PREG (IC_RESULT (ic)))
3250 emitcode ("cjne", "%s,#0x00,%05d$"
3251 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3255 emitcode ("cjne", "a,%s,%05d$"
3256 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3259 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3264 emitcode ("", "%05d$:", tlbl->key + 100);
3269 /* if the sizes are greater than 1 then we cannot */
3270 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3271 AOP_SIZE (IC_LEFT (ic)) > 1)
3274 /* we can if the aops of the left & result match or
3275 if they are in registers and the registers are the
3278 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3279 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3280 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3285 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3286 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3287 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3292 _startLazyDPSEvaluation ();
3295 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3297 _endLazyDPSEvaluation ();
3306 /*-----------------------------------------------------------------*/
3307 /* outBitAcc - output a bit in acc */
3308 /*-----------------------------------------------------------------*/
3310 outBitAcc (operand * result)
3312 symbol *tlbl = newiTempLabel (NULL);
3313 /* if the result is a bit */
3314 if (AOP_TYPE (result) == AOP_CRY)
3316 aopPut (AOP (result), "a", 0);
3320 emitcode ("jz", "%05d$", tlbl->key + 100);
3321 emitcode ("mov", "a,%s", one);
3322 emitcode ("", "%05d$:", tlbl->key + 100);
3327 /*-----------------------------------------------------------------*/
3328 /* genPlusBits - generates code for addition of two bits */
3329 /*-----------------------------------------------------------------*/
3331 genPlusBits (iCode * ic)
3333 D (emitcode (";", "genPlusBits ");
3335 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3337 symbol *lbl = newiTempLabel (NULL);
3338 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3339 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3340 emitcode ("cpl", "c");
3341 emitcode ("", "%05d$:", (lbl->key + 100));
3342 outBitC (IC_RESULT (ic));
3346 emitcode ("clr", "a");
3347 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3348 emitcode ("rlc", "a");
3349 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3350 emitcode ("addc", "a,#0x00");
3351 outAcc (IC_RESULT (ic));
3356 adjustArithmeticResult (iCode * ic)
3358 if (opIsGptr (IC_RESULT (ic)) &&
3359 opIsGptr (IC_LEFT (ic)) &&
3360 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3362 aopPut (AOP (IC_RESULT (ic)),
3363 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3367 if (opIsGptr (IC_RESULT (ic)) &&
3368 opIsGptr (IC_RIGHT (ic)) &&
3369 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3371 aopPut (AOP (IC_RESULT (ic)),
3372 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3376 if (opIsGptr (IC_RESULT (ic)) &&
3377 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3378 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3379 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3380 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3383 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3384 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3388 #if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
3389 // Please don't bring it back without a really good reason.
3390 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3391 // (because all three operands are in far space).
3392 #define AOP_OP_3(ic) \
3393 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3394 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3395 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3396 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3397 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3398 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3400 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3402 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3406 // Macro to aopOp all three operands of an ic. If this cannot be done,
3407 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3408 // will be set TRUE. The caller must then handle the case specially, noting
3409 // that the IC_RESULT operand is not aopOp'd.
3410 #define AOP_OP_3_NOFATAL(ic, rc) \
3411 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3412 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3413 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3414 isOperandInFarSpace(IC_RESULT(ic))) \
3416 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3421 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3422 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3424 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3425 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3427 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3429 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3433 // aopOp the left & right operands of an ic.
3434 #define AOP_OP_2(ic) \
3435 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3436 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3438 // convienience macro.
3439 #define AOP_SET_LOCALS(ic) \
3440 left = IC_LEFT(ic); \
3441 right = IC_RIGHT(ic); \
3442 result = IC_RESULT(ic);
3445 // Given an integer value of pushedSize bytes on the stack,
3446 // adjust it to be resultSize bytes, either by discarding
3447 // the most significant bytes or by zero-padding.
3449 // On exit from this macro, pushedSize will have been adjusted to
3450 // equal resultSize, and ACC may be trashed.
3451 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3452 /* If the pushed data is bigger than the result, \
3453 * simply discard unused bytes. Icky, but works. \
3455 while (pushedSize > resultSize) \
3457 D (emitcode (";", "discarding unused result byte."););\
3458 emitcode ("pop", "acc"); \
3461 if (pushedSize < resultSize) \
3463 emitcode ("clr", "a"); \
3464 /* Conversly, we haven't pushed enough here. \
3465 * just zero-pad, and all is well. \
3467 while (pushedSize < resultSize) \
3469 emitcode("push", "acc"); \
3473 assert(pushedSize == resultSize);
3475 /*-----------------------------------------------------------------*/
3476 /* genPlus - generates code for addition */
3477 /*-----------------------------------------------------------------*/
3479 genPlus (iCode * ic)
3481 int size, offset = 0;
3482 bool pushResult = FALSE;
3485 D (emitcode (";", "genPlus "););
3487 /* special cases :- */
3489 AOP_OP_3_NOFATAL (ic, pushResult);
3492 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3497 /* if literal, literal on the right or
3498 if left requires ACC or right is already
3500 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3501 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3502 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3504 operand *t = IC_RIGHT (ic);
3505 IC_RIGHT (ic) = IC_LEFT (ic);
3507 emitcode (";", "Swapped plus args.");
3510 /* if both left & right are in bit
3512 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3513 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3519 /* if left in bit space & right literal */
3520 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3521 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3523 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3524 /* if result in bit space */
3525 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3527 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3528 emitcode ("cpl", "c");
3529 outBitC (IC_RESULT (ic));
3533 size = getDataSize (IC_RESULT (ic));
3534 _startLazyDPSEvaluation ();
3537 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3538 emitcode ("addc", "a,#00");
3539 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3541 _endLazyDPSEvaluation ();
3546 /* if I can do an increment instead
3547 of add then GOOD for ME */
3548 if (genPlusIncr (ic) == TRUE)
3550 emitcode (";", "did genPlusIncr");
3555 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3557 _startLazyDPSEvaluation ();
3560 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3562 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3564 emitcode ("add", "a,%s",
3565 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3567 emitcode ("addc", "a,%s",
3568 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3572 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3574 /* right is going to use ACC or we would have taken the
3577 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3579 D(emitcode(";", "+ AOP_ACC special case."););
3580 emitcode("xch", "a, %s", DP2_RESULT_REG);
3582 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3585 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3588 emitcode("add", "a, %s", DP2_RESULT_REG);
3592 emitcode ("add", "a,%s",
3593 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3598 emitcode ("addc", "a,%s",
3599 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3604 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3608 emitcode ("push", "acc");
3612 _endLazyDPSEvaluation ();
3616 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3618 size = getDataSize (IC_LEFT (ic));
3619 rSize = getDataSize (IC_RESULT (ic));
3621 ADJUST_PUSHED_RESULT(size, rSize);
3623 _startLazyDPSEvaluation ();
3626 emitcode ("pop", "acc");
3627 aopPut (AOP (IC_RESULT (ic)), "a", size);
3629 _endLazyDPSEvaluation ();
3632 adjustArithmeticResult (ic);
3635 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3636 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3637 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3640 /*-----------------------------------------------------------------*/
3641 /* genMinusDec :- does subtraction with deccrement if possible */
3642 /*-----------------------------------------------------------------*/
3644 genMinusDec (iCode * ic)
3646 unsigned int icount;
3647 unsigned int size = getDataSize (IC_RESULT (ic));
3649 /* will try to generate an increment */
3650 /* if the right side is not a literal
3652 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3655 /* if the literal value of the right hand side
3656 is greater than 4 then it is not worth it */
3657 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3660 /* if decrement 16 bits in register */
3661 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3662 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3663 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3671 /* If the next instruction is a goto and the goto target
3672 * is <= 5 instructions previous to this, we can generate
3673 * jumps straight to that target.
3675 if (ic->next && ic->next->op == GOTO
3676 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3679 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3680 tlbl = IC_LABEL (ic->next);
3685 tlbl = newiTempLabel (NULL);
3689 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3690 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3691 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3692 IS_AOP_PREG (IC_RESULT (ic)))
3693 emitcode ("cjne", "%s,#0xff,%05d$"
3694 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3698 emitcode ("mov", "a,#0xff");
3699 emitcode ("cjne", "a,%s,%05d$"
3700 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3703 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3706 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3707 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3708 IS_AOP_PREG (IC_RESULT (ic)))
3709 emitcode ("cjne", "%s,#0xff,%05d$"
3710 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3714 emitcode ("cjne", "a,%s,%05d$"
3715 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3718 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3722 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3723 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3724 IS_AOP_PREG (IC_RESULT (ic)))
3725 emitcode ("cjne", "%s,#0xff,%05d$"
3726 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3730 emitcode ("cjne", "a,%s,%05d$"
3731 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3734 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3738 emitcode ("", "%05d$:", tlbl->key + 100);
3743 /* if the sizes are greater than 1 then we cannot */
3744 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3745 AOP_SIZE (IC_LEFT (ic)) > 1)
3748 /* we can if the aops of the left & result match or
3749 if they are in registers and the registers are the
3752 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3753 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3754 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3757 _startLazyDPSEvaluation ();
3760 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3762 _endLazyDPSEvaluation ();
3770 /*-----------------------------------------------------------------*/
3771 /* addSign - complete with sign */
3772 /*-----------------------------------------------------------------*/
3774 addSign (operand * result, int offset, int sign)
3776 int size = (getDataSize (result) - offset);
3779 _startLazyDPSEvaluation();
3782 emitcode ("rlc", "a");
3783 emitcode ("subb", "a,acc");
3786 aopPut (AOP (result), "a", offset++);
3793 aopPut (AOP (result), zero, offset++);
3796 _endLazyDPSEvaluation();
3800 /*-----------------------------------------------------------------*/
3801 /* genMinusBits - generates code for subtraction of two bits */
3802 /*-----------------------------------------------------------------*/
3804 genMinusBits (iCode * ic)
3806 symbol *lbl = newiTempLabel (NULL);
3808 D (emitcode (";", "genMinusBits "););
3810 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3812 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3813 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3814 emitcode ("cpl", "c");
3815 emitcode ("", "%05d$:", (lbl->key + 100));
3816 outBitC (IC_RESULT (ic));
3820 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3821 emitcode ("subb", "a,acc");
3822 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3823 emitcode ("inc", "a");
3824 emitcode ("", "%05d$:", (lbl->key + 100));
3825 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3826 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3830 /*-----------------------------------------------------------------*/
3831 /* genMinus - generates code for subtraction */
3832 /*-----------------------------------------------------------------*/
3834 genMinus (iCode * ic)
3836 int size, offset = 0;
3838 unsigned long lit = 0L;
3839 bool pushResult = FALSE;
3841 D (emitcode (";", "genMinus "););
3843 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3844 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3845 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3846 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3852 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3854 /* special cases :- */
3855 /* if both left & right are in bit space */
3856 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3857 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3863 /* if I can do an decrement instead
3864 of subtract then GOOD for ME */
3865 if (genMinusDec (ic) == TRUE)
3870 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3872 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3878 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3883 /* if literal, add a,#-lit, else normal subb */
3884 _startLazyDPSEvaluation ();
3887 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3888 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3889 emitcode ("subb", "a,%s",
3890 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3893 /* first add without previous c */
3895 if (!size && lit==-1) {
3896 emitcode ("dec", "a");
3898 emitcode ("add", "a,#0x%02x",
3899 (unsigned int) (lit & 0x0FFL));
3902 emitcode ("addc", "a,#0x%02x",
3903 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3909 emitcode ("push", "acc");
3913 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3917 _endLazyDPSEvaluation ();
3921 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3923 size = getDataSize (IC_LEFT (ic));
3924 rSize = getDataSize (IC_RESULT (ic));
3926 ADJUST_PUSHED_RESULT(size, rSize);
3928 _startLazyDPSEvaluation ();
3931 emitcode ("pop", "acc");
3932 aopPut (AOP (IC_RESULT (ic)), "a", size);
3934 _endLazyDPSEvaluation ();
3937 adjustArithmeticResult (ic);
3940 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3941 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3942 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3946 /*-----------------------------------------------------------------*/
3947 /* genMultbits :- multiplication of bits */
3948 /*-----------------------------------------------------------------*/
3950 genMultbits (operand * left,
3955 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3956 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3957 aopOp(result, ic, TRUE, FALSE);
3962 /*-----------------------------------------------------------------*/
3963 /* genMultOneByte : 8*8=8/16 bit multiplication */
3964 /*-----------------------------------------------------------------*/
3966 genMultOneByte (operand * left,
3971 sym_link *opetype = operandType (result);
3975 /* (if two literals: the value is computed before) */
3976 /* if one literal, literal on the right */
3977 if (AOP_TYPE (left) == AOP_LIT)
3982 emitcode (";", "swapped left and right");
3985 if (SPEC_USIGN(opetype)
3986 // ignore the sign of left and right, what else can we do?
3987 || (SPEC_USIGN(operandType(left)) &&
3988 SPEC_USIGN(operandType(right)))) {
3989 // just an unsigned 8*8=8/16 multiply
3990 //emitcode (";","unsigned");
3991 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3992 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3993 emitcode ("mul", "ab");
3996 aopOp(result, ic, TRUE, FALSE);
3998 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4000 // this should never happen
4001 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4002 AOP_SIZE(result), __FILE__, lineno);
4006 aopPut (AOP (result), "a", 0);
4008 if (AOP_SIZE(result)==2)
4010 aopPut (AOP (result), "b", 1);
4015 // we have to do a signed multiply
4017 emitcode (";", "signed");
4018 emitcode ("clr", "F0"); // reset sign flag
4019 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4021 lbl=newiTempLabel(NULL);
4022 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
4023 // left side is negative, 8-bit two's complement, this fails for -128
4024 emitcode ("setb", "F0"); // set sign flag
4025 emitcode ("cpl", "a");
4026 emitcode ("inc", "a");
4028 emitcode ("", "%05d$:", lbl->key+100);
4031 if (AOP_TYPE(right)==AOP_LIT) {
4032 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4033 /* AND literal negative */
4034 if ((int) val < 0) {
4035 emitcode ("cpl", "F0"); // complement sign flag
4036 emitcode ("mov", "b,#0x%02x", -val);
4038 emitcode ("mov", "b,#0x%02x", val);
4041 lbl=newiTempLabel(NULL);
4042 emitcode ("mov", "b,a");
4043 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4044 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
4045 // right side is negative, 8-bit two's complement
4046 emitcode ("cpl", "F0"); // complement sign flag
4047 emitcode ("cpl", "a");
4048 emitcode ("inc", "a");
4049 emitcode ("", "%05d$:", lbl->key+100);
4051 emitcode ("mul", "ab");
4054 aopOp(result, ic, TRUE, FALSE);
4056 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4058 // this should never happen
4059 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4060 AOP_SIZE(result), __FILE__, lineno);
4064 lbl=newiTempLabel(NULL);
4065 emitcode ("jnb", "F0,%05d$", lbl->key+100);
4066 // only ONE op was negative, we have to do a 8/16-bit two's complement
4067 emitcode ("cpl", "a"); // lsb
4068 if (AOP_SIZE(result)==1) {
4069 emitcode ("inc", "a");
4071 emitcode ("add", "a,#1");
4072 emitcode ("xch", "a,b");
4073 emitcode ("cpl", "a"); // msb
4074 emitcode ("addc", "a,#0");
4075 emitcode ("xch", "a,b");
4078 emitcode ("", "%05d$:", lbl->key+100);
4079 aopPut (AOP (result), "a", 0);
4081 if (AOP_SIZE(result)==2) {
4082 aopPut (AOP (result), "b", 1);
4086 /*-----------------------------------------------------------------*/
4087 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4088 /*-----------------------------------------------------------------*/
4089 static void genMultTwoByte (operand *left, operand *right,
4090 operand *result, iCode *ic)
4092 sym_link *retype = getSpec(operandType(right));
4093 sym_link *letype = getSpec(operandType(left));
4094 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4097 if (AOP_TYPE (left) == AOP_LIT) {
4102 /* save EA bit in F1 */
4103 lbl = newiTempLabel(NULL);
4104 emitcode ("setb","F1");
4105 emitcode ("jbc","EA,%05d$",lbl->key+100);
4106 emitcode ("clr","F1");
4107 emitcode("","%05d$:",lbl->key+100);
4109 /* load up MB with right */
4111 emitcode("clr","F0");
4112 if (AOP_TYPE(right) == AOP_LIT) {
4113 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4115 emitcode("setb","F0");
4118 emitcode ("mov","mb,#0x%02x",val & 0xff);
4119 emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4121 lbl = newiTempLabel(NULL);
4122 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4123 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4124 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4125 emitcode ("xch", "a,b");
4126 emitcode ("cpl","a");
4127 emitcode ("add", "a,#1");
4128 emitcode ("xch", "a,b");
4129 emitcode ("cpl", "a"); // msb
4130 emitcode ("addc", "a,#0");
4131 emitcode ("setb","F0");
4132 emitcode ("","%05d$:",lbl->key+100);
4133 emitcode ("mov","mb,b");
4134 emitcode ("mov","mb,a");
4137 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4138 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4140 /* load up MA with left */
4142 lbl = newiTempLabel(NULL);
4143 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4144 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4145 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4146 emitcode ("xch", "a,b");
4147 emitcode ("cpl","a");
4148 emitcode ("add", "a,#1");
4149 emitcode ("xch", "a,b");
4150 emitcode ("cpl", "a"); // msb
4151 emitcode ("addc","a,#0");
4152 emitcode ("jbc","F0,%05d$",lbl->key+100);
4153 emitcode ("setb","F0");
4154 emitcode ("","%05d$:",lbl->key+100);
4155 emitcode ("mov","ma,b");
4156 emitcode ("mov","ma,a");
4158 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4159 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4161 /* wait for multiplication to finish */
4162 lbl = newiTempLabel(NULL);
4163 emitcode("","%05d$:", lbl->key+100);
4164 emitcode("mov","a,mcnt1");
4165 emitcode("anl","a,#0x80");
4166 emitcode("jnz","%05d$",lbl->key+100);
4168 freeAsmop (left, NULL, ic, TRUE);
4169 freeAsmop (right, NULL, ic,TRUE);
4170 aopOp(result, ic, TRUE, FALSE);
4172 /* if unsigned then simple */
4174 emitcode ("mov","a,ma");
4175 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4176 emitcode ("mov","a,ma");
4177 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4178 aopPut(AOP(result),"ma",1);
4179 aopPut(AOP(result),"ma",0);
4181 emitcode("push","ma");
4182 emitcode("push","ma");
4183 emitcode("push","ma");
4185 /* negate result if needed */
4186 lbl = newiTempLabel(NULL);
4187 emitcode("jnb","F0,%05d$",lbl->key+100);
4188 emitcode("cpl","a");
4189 emitcode("add","a,#1");
4190 emitcode("","%05d$:", lbl->key+100);
4191 if (AOP_TYPE(result) == AOP_ACC)
4193 D(emitcode(";", "ACC special case."););
4194 /* We know result is the only live aop, and
4195 * it's obviously not a DPTR2, so AP is available.
4197 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4201 aopPut(AOP(result),"a",0);
4204 emitcode("pop","acc");
4205 lbl = newiTempLabel(NULL);
4206 emitcode("jnb","F0,%05d$",lbl->key+100);
4207 emitcode("cpl","a");
4208 emitcode("addc","a,#0");
4209 emitcode("","%05d$:", lbl->key+100);
4210 aopPut(AOP(result),"a",1);
4211 emitcode("pop","acc");
4212 if (AOP_SIZE(result) >= 3) {
4213 lbl = newiTempLabel(NULL);
4214 emitcode("jnb","F0,%05d$",lbl->key+100);
4215 emitcode("cpl","a");
4216 emitcode("addc","a,#0");
4217 emitcode("","%05d$:", lbl->key+100);
4218 aopPut(AOP(result),"a",2);
4220 emitcode("pop","acc");
4221 if (AOP_SIZE(result) >= 4) {
4222 lbl = newiTempLabel(NULL);
4223 emitcode("jnb","F0,%05d$",lbl->key+100);
4224 emitcode("cpl","a");
4225 emitcode("addc","a,#0");
4226 emitcode("","%05d$:", lbl->key+100);
4227 aopPut(AOP(result),"a",3);
4229 if (AOP_TYPE(result) == AOP_ACC)
4231 /* We stashed the result away above. */
4232 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4236 freeAsmop (result, NULL, ic, TRUE);
4238 /* restore EA bit in F1 */
4239 lbl = newiTempLabel(NULL);
4240 emitcode ("jnb","F1,%05d$",lbl->key+100);
4241 emitcode ("setb","EA");
4242 emitcode("","%05d$:",lbl->key+100);
4246 /*-----------------------------------------------------------------*/
4247 /* genMult - generates code for multiplication */
4248 /*-----------------------------------------------------------------*/
4250 genMult (iCode * ic)
4252 operand *left = IC_LEFT (ic);
4253 operand *right = IC_RIGHT (ic);
4254 operand *result = IC_RESULT (ic);
4256 D (emitcode (";", "genMult "););
4258 /* assign the amsops */
4261 /* special cases first */
4263 if (AOP_TYPE (left) == AOP_CRY &&
4264 AOP_TYPE (right) == AOP_CRY)
4266 genMultbits (left, right, result, ic);
4270 /* if both are of size == 1 */
4271 if (AOP_SIZE (left) == 1 &&
4272 AOP_SIZE (right) == 1)
4274 genMultOneByte (left, right, result, ic);
4278 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4279 /* use the ds390 ARITHMETIC accel UNIT */
4280 genMultTwoByte (left, right, result, ic);
4283 /* should have been converted to function call */
4287 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4288 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4289 freeAsmop (result, NULL, ic, TRUE);
4292 /*-----------------------------------------------------------------*/
4293 /* genDivbits :- division of bits */
4294 /*-----------------------------------------------------------------*/
4296 genDivbits (operand * left,
4304 /* the result must be bit */
4305 LOAD_AB_FOR_DIV (left, right, l);
4306 emitcode ("div", "ab");
4307 emitcode ("rrc", "a");
4308 aopOp(result, ic, TRUE, FALSE);
4310 aopPut (AOP (result), "c", 0);
4313 /*-----------------------------------------------------------------*/
4314 /* genDivOneByte : 8 bit division */
4315 /*-----------------------------------------------------------------*/
4317 genDivOneByte (operand * left,
4322 sym_link *opetype = operandType (result);
4328 /* signed or unsigned */
4329 if (SPEC_USIGN (opetype))
4331 /* unsigned is easy */
4332 LOAD_AB_FOR_DIV (left, right, l);
4333 emitcode ("div", "ab");
4336 aopOp(result, ic, TRUE, FALSE);
4337 aopPut (AOP (result), "a", 0);
4340 size = AOP_SIZE (result) - 1;
4344 aopPut (AOP (result), zero, offset++);
4349 /* signed is a little bit more difficult */
4351 /* save the signs of the operands */
4352 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4354 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4355 emitcode ("push", "acc"); /* save it on the stack */
4357 /* now sign adjust for both left & right */
4358 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4360 lbl = newiTempLabel (NULL);
4361 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4362 emitcode ("cpl", "a");
4363 emitcode ("inc", "a");
4364 emitcode ("", "%05d$:", (lbl->key + 100));
4365 emitcode ("mov", "b,a");
4367 /* sign adjust left side */
4368 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4371 lbl = newiTempLabel (NULL);
4372 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4373 emitcode ("cpl", "a");
4374 emitcode ("inc", "a");
4375 emitcode ("", "%05d$:", (lbl->key + 100));
4377 /* now the division */
4378 emitcode ("nop", "; workaround for DS80C390 div bug.");
4379 emitcode ("div", "ab");
4380 /* we are interested in the lower order
4382 emitcode ("mov", "b,a");
4383 lbl = newiTempLabel (NULL);
4384 emitcode ("pop", "acc");
4385 /* if there was an over flow we don't
4386 adjust the sign of the result */
4387 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4388 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4390 emitcode ("clr", "a");
4391 emitcode ("subb", "a,b");
4392 emitcode ("mov", "b,a");
4393 emitcode ("", "%05d$:", (lbl->key + 100));
4395 /* now we are done */
4397 aopOp(result, ic, TRUE, FALSE);
4399 aopPut (AOP (result), "b", 0);
4401 size = AOP_SIZE (result) - 1;
4405 emitcode ("mov", "c,b.7");
4406 emitcode ("subb", "a,acc");
4410 aopPut (AOP (result), "a", offset++);
4416 /*-----------------------------------------------------------------*/
4417 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4418 /*-----------------------------------------------------------------*/
4419 static void genDivTwoByte (operand *left, operand *right,
4420 operand *result, iCode *ic)
4422 sym_link *retype = getSpec(operandType(right));
4423 sym_link *letype = getSpec(operandType(left));
4424 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4427 /* save EA bit in F1 */
4428 lbl = newiTempLabel(NULL);
4429 emitcode ("setb","F1");
4430 emitcode ("jbc","EA,%05d$",lbl->key+100);
4431 emitcode ("clr","F1");
4432 emitcode("","%05d$:",lbl->key+100);
4434 /* load up MA with left */
4436 emitcode("clr","F0");
4437 lbl = newiTempLabel(NULL);
4438 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4439 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4440 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4441 emitcode ("xch", "a,b");
4442 emitcode ("cpl","a");
4443 emitcode ("add", "a,#1");
4444 emitcode ("xch", "a,b");
4445 emitcode ("cpl", "a"); // msb
4446 emitcode ("addc","a,#0");
4447 emitcode ("setb","F0");
4448 emitcode ("","%05d$:",lbl->key+100);
4449 emitcode ("mov","ma,b");
4450 emitcode ("mov","ma,a");
4452 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4453 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4456 /* load up MB with right */
4458 if (AOP_TYPE(right) == AOP_LIT) {
4459 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4461 lbl = newiTempLabel(NULL);
4462 emitcode ("jbc","F0,%05d$",lbl->key+100);
4463 emitcode("setb","F0");
4464 emitcode ("","%05d$:",lbl->key+100);
4467 emitcode ("mov","mb,#0x%02x",val & 0xff);
4468 emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4470 lbl = newiTempLabel(NULL);
4471 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4472 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4473 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4474 emitcode ("xch", "a,b");
4475 emitcode ("cpl","a");
4476 emitcode ("add", "a,#1");
4477 emitcode ("xch", "a,b");
4478 emitcode ("cpl", "a"); // msb
4479 emitcode ("addc", "a,#0");
4480 emitcode ("jbc","F0,%05d$",lbl->key+100);
4481 emitcode ("setb","F0");
4482 emitcode ("","%05d$:",lbl->key+100);
4483 emitcode ("mov","mb,b");
4484 emitcode ("mov","mb,a");
4487 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4488 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4491 /* wait for multiplication to finish */
4492 lbl = newiTempLabel(NULL);
4493 emitcode("","%05d$:", lbl->key+100);
4494 emitcode("mov","a,mcnt1");
4495 emitcode("anl","a,#0x80");
4496 emitcode("jnz","%05d$",lbl->key+100);
4498 freeAsmop (left, NULL, ic, TRUE);
4499 freeAsmop (right, NULL, ic,TRUE);
4500 aopOp(result, ic, TRUE, FALSE);
4502 /* if unsigned then simple */
4504 aopPut(AOP(result),"ma",1);
4505 aopPut(AOP(result),"ma",0);
4507 emitcode("push","ma");
4509 /* negate result if needed */
4510 lbl = newiTempLabel(NULL);
4511 emitcode("jnb","F0,%05d$",lbl->key+100);
4512 emitcode("cpl","a");
4513 emitcode("add","a,#1");
4514 emitcode("","%05d$:", lbl->key+100);
4515 aopPut(AOP(result),"a",0);
4516 emitcode("pop","acc");
4517 lbl = newiTempLabel(NULL);
4518 emitcode("jnb","F0,%05d$",lbl->key+100);
4519 emitcode("cpl","a");
4520 emitcode("addc","a,#0");
4521 emitcode("","%05d$:", lbl->key+100);
4522 aopPut(AOP(result),"a",1);
4524 freeAsmop (result, NULL, ic, TRUE);
4525 /* restore EA bit in F1 */
4526 lbl = newiTempLabel(NULL);
4527 emitcode ("jnb","F1,%05d$",lbl->key+100);
4528 emitcode ("setb","EA");
4529 emitcode("","%05d$:",lbl->key+100);
4533 /*-----------------------------------------------------------------*/
4534 /* genDiv - generates code for division */
4535 /*-----------------------------------------------------------------*/
4539 operand *left = IC_LEFT (ic);
4540 operand *right = IC_RIGHT (ic);
4541 operand *result = IC_RESULT (ic);
4543 D (emitcode (";", "genDiv "););
4545 /* assign the amsops */
4548 /* special cases first */
4550 if (AOP_TYPE (left) == AOP_CRY &&
4551 AOP_TYPE (right) == AOP_CRY)
4553 genDivbits (left, right, result, ic);
4557 /* if both are of size == 1 */
4558 if (AOP_SIZE (left) == 1 &&
4559 AOP_SIZE (right) == 1)
4561 genDivOneByte (left, right, result, ic);
4565 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4566 /* use the ds390 ARITHMETIC accel UNIT */
4567 genDivTwoByte (left, right, result, ic);
4570 /* should have been converted to function call */
4573 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4574 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4575 freeAsmop (result, NULL, ic, TRUE);
4578 /*-----------------------------------------------------------------*/
4579 /* genModbits :- modulus of bits */
4580 /*-----------------------------------------------------------------*/
4582 genModbits (operand * left,
4590 /* the result must be bit */
4591 LOAD_AB_FOR_DIV (left, right, l);
4592 emitcode ("div", "ab");
4593 emitcode ("mov", "a,b");
4594 emitcode ("rrc", "a");
4595 aopOp(result, ic, TRUE, FALSE);
4596 aopPut (AOP (result), "c", 0);
4599 /*-----------------------------------------------------------------*/
4600 /* genModOneByte : 8 bit modulus */
4601 /*-----------------------------------------------------------------*/
4603 genModOneByte (operand * left,
4608 sym_link *opetype = operandType (result);
4612 /* signed or unsigned */
4613 if (SPEC_USIGN (opetype))
4615 /* unsigned is easy */
4616 LOAD_AB_FOR_DIV (left, right, l);
4617 emitcode ("div", "ab");
4618 aopOp(result, ic, TRUE, FALSE);
4619 aopPut (AOP (result), "b", 0);
4623 /* signed is a little bit more difficult */
4625 /* save the signs of the operands */
4626 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4629 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4630 emitcode ("push", "acc"); /* save it on the stack */
4632 /* now sign adjust for both left & right */
4633 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4636 lbl = newiTempLabel (NULL);
4637 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4638 emitcode ("cpl", "a");
4639 emitcode ("inc", "a");
4640 emitcode ("", "%05d$:", (lbl->key + 100));
4641 emitcode ("mov", "b,a");
4643 /* sign adjust left side */
4644 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4647 lbl = newiTempLabel (NULL);
4648 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4649 emitcode ("cpl", "a");
4650 emitcode ("inc", "a");
4651 emitcode ("", "%05d$:", (lbl->key + 100));
4653 /* now the multiplication */
4654 emitcode ("nop", "; workaround for DS80C390 div bug.");
4655 emitcode ("div", "ab");
4656 /* we are interested in the lower order
4658 lbl = newiTempLabel (NULL);
4659 emitcode ("pop", "acc");
4660 /* if there was an over flow we don't
4661 adjust the sign of the result */
4662 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4663 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4665 emitcode ("clr", "a");
4666 emitcode ("subb", "a,b");
4667 emitcode ("mov", "b,a");
4668 emitcode ("", "%05d$:", (lbl->key + 100));
4670 /* now we are done */
4671 aopOp(result, ic, TRUE, FALSE);
4672 aopPut (AOP (result), "b", 0);
4676 /*-----------------------------------------------------------------*/
4677 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
4678 /*-----------------------------------------------------------------*/
4679 static void genModTwoByte (operand *left, operand *right,
4680 operand *result, iCode *ic)
4682 sym_link *retype = getSpec(operandType(right));
4683 sym_link *letype = getSpec(operandType(left));
4684 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4687 /* load up MA with left */
4688 /* save EA bit in F1 */
4689 lbl = newiTempLabel(NULL);
4690 emitcode ("setb","F1");
4691 emitcode ("jbc","EA,%05d$",lbl->key+100);
4692 emitcode ("clr","F1");
4693 emitcode("","%05d$:",lbl->key+100);
4696 lbl = newiTempLabel(NULL);
4697 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4698 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4699 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4700 emitcode ("xch", "a,b");
4701 emitcode ("cpl","a");
4702 emitcode ("add", "a,#1");
4703 emitcode ("xch", "a,b");
4704 emitcode ("cpl", "a"); // msb
4705 emitcode ("addc","a,#0");
4706 emitcode ("","%05d$:",lbl->key+100);
4707 emitcode ("mov","ma,b");
4708 emitcode ("mov","ma,a");
4710 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4711 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4714 /* load up MB with right */
4716 if (AOP_TYPE(right) == AOP_LIT) {
4717 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4721 emitcode ("mov","mb,#0x%02x",val & 0xff);
4722 emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4724 lbl = newiTempLabel(NULL);
4725 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4726 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4727 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4728 emitcode ("xch", "a,b");
4729 emitcode ("cpl","a");
4730 emitcode ("add", "a,#1");
4731 emitcode ("xch", "a,b");
4732 emitcode ("cpl", "a"); // msb
4733 emitcode ("addc", "a,#0");
4734 emitcode ("","%05d$:",lbl->key+100);
4735 emitcode ("mov","mb,b");
4736 emitcode ("mov","mb,a");
4739 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4740 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4743 /* wait for multiplication to finish */
4744 lbl = newiTempLabel(NULL);
4745 emitcode("","%05d$:", lbl->key+100);
4746 emitcode("mov","a,mcnt1");
4747 emitcode("anl","a,#0x80");
4748 emitcode("jnz","%05d$",lbl->key+100);
4750 freeAsmop (left, NULL, ic, TRUE);
4751 freeAsmop (right, NULL, ic,TRUE);
4752 aopOp(result, ic, TRUE, FALSE);
4754 aopPut(AOP(result),"mb",1);
4755 aopPut(AOP(result),"mb",0);
4756 freeAsmop (result, NULL, ic, TRUE);
4758 /* restore EA bit in F1 */
4759 lbl = newiTempLabel(NULL);
4760 emitcode ("jnb","F1,%05d$",lbl->key+100);
4761 emitcode ("setb","EA");
4762 emitcode("","%05d$:",lbl->key+100);
4766 /*-----------------------------------------------------------------*/
4767 /* genMod - generates code for division */
4768 /*-----------------------------------------------------------------*/
4772 operand *left = IC_LEFT (ic);
4773 operand *right = IC_RIGHT (ic);
4774 operand *result = IC_RESULT (ic);
4776 D (emitcode (";", "genMod "); );
4778 /* assign the amsops */
4781 /* special cases first */
4783 if (AOP_TYPE (left) == AOP_CRY &&
4784 AOP_TYPE (right) == AOP_CRY)
4786 genModbits (left, right, result, ic);
4790 /* if both are of size == 1 */
4791 if (AOP_SIZE (left) == 1 &&
4792 AOP_SIZE (right) == 1)
4794 genModOneByte (left, right, result, ic);
4798 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4799 /* use the ds390 ARITHMETIC accel UNIT */
4800 genModTwoByte (left, right, result, ic);
4804 /* should have been converted to function call */
4808 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4809 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4810 freeAsmop (result, NULL, ic, TRUE);
4813 /*-----------------------------------------------------------------*/
4814 /* genIfxJump :- will create a jump depending on the ifx */
4815 /*-----------------------------------------------------------------*/
4817 genIfxJump (iCode * ic, char *jval)
4820 symbol *tlbl = newiTempLabel (NULL);
4823 D (emitcode (";", "genIfxJump ");
4826 /* if true label then we jump if condition
4830 jlbl = IC_TRUE (ic);
4831 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4832 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4836 /* false label is present */
4837 jlbl = IC_FALSE (ic);
4838 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4839 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4841 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4842 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4844 emitcode (inst, "%05d$", tlbl->key + 100);
4845 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4846 emitcode ("", "%05d$:", tlbl->key + 100);
4848 /* mark the icode as generated */
4852 /*-----------------------------------------------------------------*/
4853 /* genCmp :- greater or less than comparison */
4854 /*-----------------------------------------------------------------*/
4856 genCmp (operand * left, operand * right,
4857 iCode * ic, iCode * ifx, int sign)
4859 int size, offset = 0;
4860 unsigned long lit = 0L;
4863 D (emitcode (";", "genCmp");
4866 result = IC_RESULT (ic);
4868 /* if left & right are bit variables */
4869 if (AOP_TYPE (left) == AOP_CRY &&
4870 AOP_TYPE (right) == AOP_CRY)
4872 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4873 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4877 /* subtract right from left if at the
4878 end the carry flag is set then we know that
4879 left is greater than right */
4880 size = max (AOP_SIZE (left), AOP_SIZE (right));
4882 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4883 if ((size == 1) && !sign &&
4884 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4886 symbol *lbl = newiTempLabel (NULL);
4887 emitcode ("cjne", "%s,%s,%05d$",
4888 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4889 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4891 emitcode ("", "%05d$:", lbl->key + 100);
4895 if (AOP_TYPE (right) == AOP_LIT)
4897 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4898 /* optimize if(x < 0) or if(x >= 0) */
4907 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4909 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4910 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4912 aopOp (result, ic, FALSE, FALSE);
4914 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4916 freeAsmop (result, NULL, ic, TRUE);
4917 genIfxJump (ifx, "acc.7");
4922 emitcode ("rlc", "a");
4924 goto release_freedLR;
4932 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4933 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4934 emitcode (";", "genCmp #2");
4935 if (sign && (size == 0))
4937 emitcode (";", "genCmp #3");
4938 emitcode ("xrl", "a,#0x80");
4939 if (AOP_TYPE (right) == AOP_LIT)
4941 unsigned long lit = (unsigned long)
4942 floatFromVal (AOP (right)->aopu.aop_lit);
4943 emitcode (";", "genCmp #3.1");
4944 emitcode ("subb", "a,#0x%02x",
4945 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4949 emitcode (";", "genCmp #3.2");
4950 if (AOP_NEEDSACC (right))
4952 emitcode ("push", "acc");
4954 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4955 FALSE, FALSE, FALSE));
4956 emitcode ("xrl", "b,#0x80");
4957 if (AOP_NEEDSACC (right))
4959 emitcode ("pop", "acc");
4961 emitcode ("subb", "a,b");
4968 emitcode (";", "genCmp #4");
4969 if (AOP_NEEDSACC (right))
4972 emitcode (";", "genCmp #4.1");
4973 emitcode ("xch", "a, b");
4974 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4975 emitcode ("xch", "a, b");
4980 emitcode (";", "genCmp #4.2");
4981 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4984 emitcode ("subb", "a,%s", s);
4991 /* Don't need the left & right operands any more; do need the result. */
4992 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4993 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4995 aopOp (result, ic, FALSE, FALSE);
4999 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5005 /* if the result is used in the next
5006 ifx conditional branch then generate
5007 code a little differently */
5010 genIfxJump (ifx, "c");
5016 /* leave the result in acc */
5018 freeAsmop (result, NULL, ic, TRUE);
5021 /*-----------------------------------------------------------------*/
5022 /* genCmpGt :- greater than comparison */
5023 /*-----------------------------------------------------------------*/
5025 genCmpGt (iCode * ic, iCode * ifx)
5027 operand *left, *right;
5028 sym_link *letype, *retype;
5031 D (emitcode (";", "genCmpGt ");
5034 left = IC_LEFT (ic);
5035 right = IC_RIGHT (ic);
5037 letype = getSpec (operandType (left));
5038 retype = getSpec (operandType (right));
5039 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5041 /* assign the left & right amsops */
5044 genCmp (right, left, ic, ifx, sign);
5047 /*-----------------------------------------------------------------*/
5048 /* genCmpLt - less than comparisons */
5049 /*-----------------------------------------------------------------*/
5051 genCmpLt (iCode * ic, iCode * ifx)
5053 operand *left, *right;
5054 sym_link *letype, *retype;
5057 D (emitcode (";", "genCmpLt "););
5059 left = IC_LEFT (ic);
5060 right = IC_RIGHT (ic);
5062 letype = getSpec (operandType (left));
5063 retype = getSpec (operandType (right));
5064 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5066 /* assign the left & right amsops */
5069 genCmp (left, right, ic, ifx, sign);
5072 /*-----------------------------------------------------------------*/
5073 /* gencjneshort - compare and jump if not equal */
5074 /*-----------------------------------------------------------------*/
5076 gencjneshort (operand * left, operand * right, symbol * lbl)
5078 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5080 unsigned long lit = 0L;
5082 D (emitcode (";", "gencjneshort");
5085 /* if the left side is a literal or
5086 if the right is in a pointer register and left
5088 if ((AOP_TYPE (left) == AOP_LIT) ||
5089 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5096 if (AOP_TYPE (right) == AOP_LIT)
5097 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5099 if (opIsGptr (left) || opIsGptr (right))
5101 /* We are comparing a generic pointer to something.
5102 * Exclude the generic type byte from the comparison.
5105 D (emitcode (";", "cjneshort: generic ptr special case.");
5110 /* if the right side is a literal then anything goes */
5111 if (AOP_TYPE (right) == AOP_LIT &&
5112 AOP_TYPE (left) != AOP_DIR)
5116 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5118 emitcode ("cjne", "a,%s,%05d$",
5119 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5125 /* if the right side is in a register or in direct space or
5126 if the left is a pointer register & right is not */
5127 else if (AOP_TYPE (right) == AOP_REG ||
5128 AOP_TYPE (right) == AOP_DIR ||
5129 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5130 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5134 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5135 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5136 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5137 emitcode ("jnz", "%05d$", lbl->key + 100);
5139 emitcode ("cjne", "a,%s,%05d$",
5140 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5147 /* right is a pointer reg need both a & b */
5150 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5151 if (strcmp (l, "b"))
5152 emitcode ("mov", "b,%s", l);
5153 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5154 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5160 /*-----------------------------------------------------------------*/
5161 /* gencjne - compare and jump if not equal */
5162 /*-----------------------------------------------------------------*/
5164 gencjne (operand * left, operand * right, symbol * lbl)
5166 symbol *tlbl = newiTempLabel (NULL);
5168 D (emitcode (";", "gencjne");
5171 gencjneshort (left, right, lbl);
5173 emitcode ("mov", "a,%s", one);
5174 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5175 emitcode ("", "%05d$:", lbl->key + 100);
5176 emitcode ("clr", "a");
5177 emitcode ("", "%05d$:", tlbl->key + 100);
5180 /*-----------------------------------------------------------------*/
5181 /* genCmpEq - generates code for equal to */
5182 /*-----------------------------------------------------------------*/
5184 genCmpEq (iCode * ic, iCode * ifx)
5186 operand *left, *right, *result;
5188 D (emitcode (";", "genCmpEq ");
5192 AOP_SET_LOCALS (ic);
5194 /* if literal, literal on the right or
5195 if the right is in a pointer register and left
5197 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5198 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5200 operand *t = IC_RIGHT (ic);
5201 IC_RIGHT (ic) = IC_LEFT (ic);
5205 if (ifx && /* !AOP_SIZE(result) */
5206 OP_SYMBOL (result) &&
5207 OP_SYMBOL (result)->regType == REG_CND)
5210 /* if they are both bit variables */
5211 if (AOP_TYPE (left) == AOP_CRY &&
5212 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5214 if (AOP_TYPE (right) == AOP_LIT)
5216 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5219 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5220 emitcode ("cpl", "c");
5224 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5228 emitcode ("clr", "c");
5230 /* AOP_TYPE(right) == AOP_CRY */
5234 symbol *lbl = newiTempLabel (NULL);
5235 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5236 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5237 emitcode ("cpl", "c");
5238 emitcode ("", "%05d$:", (lbl->key + 100));
5240 /* if true label then we jump if condition
5242 tlbl = newiTempLabel (NULL);
5245 emitcode ("jnc", "%05d$", tlbl->key + 100);
5246 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5250 emitcode ("jc", "%05d$", tlbl->key + 100);
5251 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5253 emitcode ("", "%05d$:", tlbl->key + 100);
5257 tlbl = newiTempLabel (NULL);
5258 gencjneshort (left, right, tlbl);
5261 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5262 emitcode ("", "%05d$:", tlbl->key + 100);
5266 symbol *lbl = newiTempLabel (NULL);
5267 emitcode ("sjmp", "%05d$", lbl->key + 100);
5268 emitcode ("", "%05d$:", tlbl->key + 100);
5269 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5270 emitcode ("", "%05d$:", lbl->key + 100);
5273 /* mark the icode as generated */
5276 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5277 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5281 /* if they are both bit variables */
5282 if (AOP_TYPE (left) == AOP_CRY &&
5283 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5285 if (AOP_TYPE (right) == AOP_LIT)
5287 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5290 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5291 emitcode ("cpl", "c");
5295 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5299 emitcode ("clr", "c");
5301 /* AOP_TYPE(right) == AOP_CRY */
5305 symbol *lbl = newiTempLabel (NULL);
5306 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5307 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5308 emitcode ("cpl", "c");
5309 emitcode ("", "%05d$:", (lbl->key + 100));
5312 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5313 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5315 aopOp (result, ic, TRUE, FALSE);
5318 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5325 genIfxJump (ifx, "c");
5328 /* if the result is used in an arithmetic operation
5329 then put the result in place */
5334 gencjne (left, right, newiTempLabel (NULL));
5336 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5337 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5339 aopOp (result, ic, TRUE, FALSE);
5341 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5343 aopPut (AOP (result), "a", 0);
5348 genIfxJump (ifx, "a");
5351 /* if the result is used in an arithmetic operation
5352 then put the result in place */
5353 if (AOP_TYPE (result) != AOP_CRY)
5355 /* leave the result in acc */
5359 freeAsmop (result, NULL, ic, TRUE);
5362 /*-----------------------------------------------------------------*/
5363 /* ifxForOp - returns the icode containing the ifx for operand */
5364 /*-----------------------------------------------------------------*/
5366 ifxForOp (operand * op, iCode * ic)
5368 /* if true symbol then needs to be assigned */
5369 if (IS_TRUE_SYMOP (op))
5372 /* if this has register type condition and
5373 the next instruction is ifx with the same operand
5374 and live to of the operand is upto the ifx only then */
5376 ic->next->op == IFX &&
5377 IC_COND (ic->next)->key == op->key &&
5378 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5383 /*-----------------------------------------------------------------*/
5384 /* hasInc - operand is incremented before any other use */
5385 /*-----------------------------------------------------------------*/
5387 hasInc (operand *op, iCode *ic)
5389 sym_link *type = operandType(op);
5390 sym_link *retype = getSpec (type);
5391 iCode *lic = ic->next;
5394 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5395 if (!IS_SYMOP(op)) return NULL;
5397 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5398 isize = getSize(type->next);
5400 /* if operand of the form op = op + <sizeof *op> */
5401 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5402 isOperandEqual(IC_RESULT(lic),op) &&
5403 isOperandLiteral(IC_RIGHT(lic)) &&
5404 operandLitValue(IC_RIGHT(lic)) == isize) {
5407 /* if the operand used or deffed */
5408 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5416 /*-----------------------------------------------------------------*/
5417 /* genAndOp - for && operation */
5418 /*-----------------------------------------------------------------*/
5420 genAndOp (iCode * ic)
5422 operand *left, *right, *result;
5425 D (emitcode (";", "genAndOp "););
5427 /* note here that && operations that are in an
5428 if statement are taken away by backPatchLabels
5429 only those used in arthmetic operations remain */
5431 AOP_SET_LOCALS (ic);
5433 /* if both are bit variables */
5434 if (AOP_TYPE (left) == AOP_CRY &&
5435 AOP_TYPE (right) == AOP_CRY)
5437 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5438 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5439 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5440 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5442 aopOp (result,ic,FALSE, FALSE);
5447 tlbl = newiTempLabel (NULL);
5449 emitcode ("jz", "%05d$", tlbl->key + 100);
5451 emitcode ("", "%05d$:", tlbl->key + 100);
5452 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5453 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5455 aopOp (result,ic,FALSE, FALSE);
5458 freeAsmop (result, NULL, ic, TRUE);
5462 /*-----------------------------------------------------------------*/
5463 /* genOrOp - for || operation */
5464 /*-----------------------------------------------------------------*/
5466 genOrOp (iCode * ic)
5468 operand *left, *right, *result;
5471 D (emitcode (";", "genOrOp "););
5473 /* note here that || operations that are in an
5474 if statement are taken away by backPatchLabels
5475 only those used in arthmetic operations remain */
5477 AOP_SET_LOCALS (ic);
5479 /* if both are bit variables */
5480 if (AOP_TYPE (left) == AOP_CRY &&
5481 AOP_TYPE (right) == AOP_CRY)
5483 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5484 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5485 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5486 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5488 aopOp (result,ic,FALSE, FALSE);
5494 tlbl = newiTempLabel (NULL);
5496 emitcode ("jnz", "%05d$", tlbl->key + 100);
5498 emitcode ("", "%05d$:", tlbl->key + 100);
5499 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5500 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5502 aopOp (result,ic,FALSE, FALSE);
5507 freeAsmop (result, NULL, ic, TRUE);
5510 /*-----------------------------------------------------------------*/
5511 /* isLiteralBit - test if lit == 2^n */
5512 /*-----------------------------------------------------------------*/
5514 isLiteralBit (unsigned long lit)
5516 unsigned long pw[32] =
5517 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5518 0x100L, 0x200L, 0x400L, 0x800L,
5519 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5520 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5521 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5522 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5523 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5526 for (idx = 0; idx < 32; idx++)
5532 /*-----------------------------------------------------------------*/
5533 /* continueIfTrue - */
5534 /*-----------------------------------------------------------------*/
5536 continueIfTrue (iCode * ic)
5539 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5543 /*-----------------------------------------------------------------*/
5545 /*-----------------------------------------------------------------*/
5547 jumpIfTrue (iCode * ic)
5550 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5554 /*-----------------------------------------------------------------*/
5555 /* jmpTrueOrFalse - */
5556 /*-----------------------------------------------------------------*/
5558 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5560 // ugly but optimized by peephole
5563 symbol *nlbl = newiTempLabel (NULL);
5564 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5565 emitcode ("", "%05d$:", tlbl->key + 100);
5566 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5567 emitcode ("", "%05d$:", nlbl->key + 100);
5571 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5572 emitcode ("", "%05d$:", tlbl->key + 100);
5577 // Generate code to perform a bit-wise logic operation
5578 // on two operands in far space (assumed to already have been
5579 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5580 // in far space. This requires pushing the result on the stack
5581 // then popping it into the result.
5583 genFarFarLogicOp(iCode *ic, char *logicOp)
5585 int size, resultSize, compSize;
5589 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5590 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5591 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5593 _startLazyDPSEvaluation();
5594 for (size = compSize; (size--); offset++)
5596 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5597 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5598 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5600 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5601 emitcode ("push", "acc");
5603 _endLazyDPSEvaluation();
5605 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5606 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5607 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5609 resultSize = AOP_SIZE(IC_RESULT(ic));
5611 ADJUST_PUSHED_RESULT(compSize, resultSize);
5613 _startLazyDPSEvaluation();
5616 emitcode ("pop", "acc");
5617 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5619 _endLazyDPSEvaluation();
5620 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5624 /*-----------------------------------------------------------------*/
5625 /* genAnd - code for and */
5626 /*-----------------------------------------------------------------*/
5628 genAnd (iCode * ic, iCode * ifx)
5630 operand *left, *right, *result;
5631 int size, offset = 0;
5632 unsigned long lit = 0L;
5637 D (emitcode (";", "genAnd "););
5639 AOP_OP_3_NOFATAL (ic, pushResult);
5640 AOP_SET_LOCALS (ic);
5644 genFarFarLogicOp(ic, "anl");
5649 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5651 AOP_TYPE (left), AOP_TYPE (right));
5652 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5654 AOP_SIZE (left), AOP_SIZE (right));
5657 /* if left is a literal & right is not then exchange them */
5658 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5659 #ifdef LOGIC_OPS_BROKEN
5660 || AOP_NEEDSACC (left)
5664 operand *tmp = right;
5669 /* if result = right then exchange them */
5670 if (sameRegs (AOP (result), AOP (right)))
5672 operand *tmp = right;
5677 /* if right is bit then exchange them */
5678 if (AOP_TYPE (right) == AOP_CRY &&
5679 AOP_TYPE (left) != AOP_CRY)
5681 operand *tmp = right;
5685 if (AOP_TYPE (right) == AOP_LIT)
5686 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5688 size = AOP_SIZE (result);
5691 // result = bit & yy;
5692 if (AOP_TYPE (left) == AOP_CRY)
5694 // c = bit & literal;
5695 if (AOP_TYPE (right) == AOP_LIT)
5699 if (size && sameRegs (AOP (result), AOP (left)))
5702 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5707 if (size && (AOP_TYPE (result) == AOP_CRY))
5709 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5712 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5717 emitcode ("clr", "c");
5722 if (AOP_TYPE (right) == AOP_CRY)
5725 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5726 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5731 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5733 emitcode ("rrc", "a");
5734 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5742 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5743 genIfxJump (ifx, "c");
5747 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5748 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5749 if ((AOP_TYPE (right) == AOP_LIT) &&
5750 (AOP_TYPE (result) == AOP_CRY) &&
5751 (AOP_TYPE (left) != AOP_CRY))
5753 int posbit = isLiteralBit (lit);
5758 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5761 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5767 sprintf (buffer, "acc.%d", posbit & 0x07);
5768 genIfxJump (ifx, buffer);
5775 symbol *tlbl = newiTempLabel (NULL);
5776 int sizel = AOP_SIZE (left);
5778 emitcode ("setb", "c");
5781 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5783 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5785 if ((posbit = isLiteralBit (bytelit)) != 0)
5786 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5789 if (bytelit != 0x0FFL)
5790 emitcode ("anl", "a,%s",
5791 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5792 emitcode ("jnz", "%05d$", tlbl->key + 100);
5797 // bit = left & literal
5800 emitcode ("clr", "c");
5801 emitcode ("", "%05d$:", tlbl->key + 100);
5803 // if(left & literal)
5807 jmpTrueOrFalse (ifx, tlbl);
5815 /* if left is same as result */
5816 if (sameRegs (AOP (result), AOP (left)))
5818 for (; size--; offset++)
5820 if (AOP_TYPE (right) == AOP_LIT)
5822 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5824 else if (bytelit == 0)
5825 aopPut (AOP (result), zero, offset);
5826 else if (IS_AOP_PREG (result))
5828 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5829 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5830 aopPut (AOP (result), "a", offset);
5833 emitcode ("anl", "%s,%s",
5834 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5835 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5839 if (AOP_TYPE (left) == AOP_ACC)
5840 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5843 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5844 if (IS_AOP_PREG (result))
5846 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5847 aopPut (AOP (result), "a", offset);
5851 emitcode ("anl", "%s,a",
5852 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5859 // left & result in different registers
5860 if (AOP_TYPE (result) == AOP_CRY)
5863 // if(size), result in bit
5864 // if(!size && ifx), conditional oper: if(left & right)
5865 symbol *tlbl = newiTempLabel (NULL);
5866 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5868 emitcode ("setb", "c");
5871 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5872 emitcode ("anl", "a,%s",
5873 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5875 if (AOP_TYPE(left)==AOP_ACC) {
5876 emitcode("mov", "b,a");
5877 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5878 emitcode("anl", "a,b");
5880 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5881 emitcode ("anl", "a,%s",
5882 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5885 emitcode ("jnz", "%05d$", tlbl->key + 100);
5891 emitcode ("", "%05d$:", tlbl->key + 100);
5895 jmpTrueOrFalse (ifx, tlbl);
5899 for (; (size--); offset++)
5902 // result = left & right
5903 if (AOP_TYPE (right) == AOP_LIT)
5905 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5907 aopPut (AOP (result),
5908 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5912 else if (bytelit == 0)
5914 aopPut (AOP (result), zero, offset);
5917 D (emitcode (";", "better literal AND."););
5918 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5919 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5920 FALSE, FALSE, FALSE));
5925 // faster than result <- left, anl result,right
5926 // and better if result is SFR
5927 if (AOP_TYPE (left) == AOP_ACC)
5929 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5930 FALSE, FALSE, FALSE));
5934 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
5935 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
5937 emitcode("mov", "b,a");
5941 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5942 emitcode ("anl", "a,%s", rOp);
5945 aopPut (AOP (result), "a", offset);
5951 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5952 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5953 freeAsmop (result, NULL, ic, TRUE);
5957 /*-----------------------------------------------------------------*/
5958 /* genOr - code for or */
5959 /*-----------------------------------------------------------------*/
5961 genOr (iCode * ic, iCode * ifx)
5963 operand *left, *right, *result;
5964 int size, offset = 0;
5965 unsigned long lit = 0L;
5968 D (emitcode (";", "genOr "););
5970 AOP_OP_3_NOFATAL (ic, pushResult);
5971 AOP_SET_LOCALS (ic);
5975 genFarFarLogicOp(ic, "orl");
5981 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5983 AOP_TYPE (left), AOP_TYPE (right));
5984 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5986 AOP_SIZE (left), AOP_SIZE (right));
5989 /* if left is a literal & right is not then exchange them */
5990 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5991 #ifdef LOGIC_OPS_BROKEN
5992 || AOP_NEEDSACC (left) // I think this is a net loss now.
5996 operand *tmp = right;
6001 /* if result = right then exchange them */
6002 if (sameRegs (AOP (result), AOP (right)))
6004 operand *tmp = right;
6009 /* if right is bit then exchange them */
6010 if (AOP_TYPE (right) == AOP_CRY &&
6011 AOP_TYPE (left) != AOP_CRY)
6013 operand *tmp = right;
6017 if (AOP_TYPE (right) == AOP_LIT)
6018 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6020 size = AOP_SIZE (result);
6024 if (AOP_TYPE (left) == AOP_CRY)
6026 if (AOP_TYPE (right) == AOP_LIT)
6028 // c = bit & literal;
6031 // lit != 0 => result = 1
6032 if (AOP_TYPE (result) == AOP_CRY)
6035 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6037 continueIfTrue (ifx);
6040 emitcode ("setb", "c");
6044 // lit == 0 => result = left
6045 if (size && sameRegs (AOP (result), AOP (left)))
6047 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6052 if (AOP_TYPE (right) == AOP_CRY)
6055 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6056 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6061 symbol *tlbl = newiTempLabel (NULL);
6062 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6063 emitcode ("setb", "c");
6064 emitcode ("jb", "%s,%05d$",
6065 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6067 emitcode ("jnz", "%05d$", tlbl->key + 100);
6068 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6070 jmpTrueOrFalse (ifx, tlbl);
6076 emitcode ("", "%05d$:", tlbl->key + 100);
6085 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6086 genIfxJump (ifx, "c");
6090 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6091 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6092 if ((AOP_TYPE (right) == AOP_LIT) &&
6093 (AOP_TYPE (result) == AOP_CRY) &&
6094 (AOP_TYPE (left) != AOP_CRY))
6100 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6102 continueIfTrue (ifx);
6107 // lit = 0, result = boolean(left)
6109 emitcode ("setb", "c");
6113 symbol *tlbl = newiTempLabel (NULL);
6114 emitcode ("jnz", "%05d$", tlbl->key + 100);
6116 emitcode ("", "%05d$:", tlbl->key + 100);
6120 genIfxJump (ifx, "a");
6128 /* if left is same as result */
6129 if (sameRegs (AOP (result), AOP (left)))
6131 for (; size--; offset++)
6133 if (AOP_TYPE (right) == AOP_LIT)
6135 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6141 if (IS_AOP_PREG (left))
6143 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6144 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6145 aopPut (AOP (result), "a", offset);
6149 emitcode ("orl", "%s,%s",
6150 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6151 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6157 if (AOP_TYPE (left) == AOP_ACC)
6159 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6163 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6164 if (IS_AOP_PREG (left))
6166 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6167 aopPut (AOP (result), "a", offset);
6171 emitcode ("orl", "%s,a",
6172 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6180 // left & result in different registers
6181 if (AOP_TYPE (result) == AOP_CRY)
6184 // if(size), result in bit
6185 // if(!size && ifx), conditional oper: if(left | right)
6186 symbol *tlbl = newiTempLabel (NULL);
6187 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6189 emitcode ("setb", "c");
6192 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6193 emitcode ("orl", "a,%s",
6194 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6196 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6197 emitcode ("orl", "a,%s",
6198 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6200 emitcode ("jnz", "%05d$", tlbl->key + 100);
6206 emitcode ("", "%05d$:", tlbl->key + 100);
6210 jmpTrueOrFalse (ifx, tlbl);
6214 _startLazyDPSEvaluation();
6215 for (; (size--); offset++)
6218 // result = left & right
6219 if (AOP_TYPE (right) == AOP_LIT)
6221 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6223 aopPut (AOP (result),
6224 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6228 D (emitcode (";", "better literal OR."););
6229 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6230 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6231 FALSE, FALSE, FALSE));
6236 // faster than result <- left, anl result,right
6237 // and better if result is SFR
6238 if (AOP_TYPE (left) == AOP_ACC)
6240 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6241 FALSE, FALSE, FALSE));
6245 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6247 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6249 emitcode("mov", "b,a");
6253 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6254 emitcode ("orl", "a,%s", rOp);
6257 aopPut (AOP (result), "a", offset);
6259 _endLazyDPSEvaluation();
6264 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6265 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6266 freeAsmop (result, NULL, ic, TRUE);
6269 /*-----------------------------------------------------------------*/
6270 /* genXor - code for xclusive or */
6271 /*-----------------------------------------------------------------*/
6273 genXor (iCode * ic, iCode * ifx)
6275 operand *left, *right, *result;
6276 int size, offset = 0;
6277 unsigned long lit = 0L;
6280 D (emitcode (";", "genXor "););
6282 AOP_OP_3_NOFATAL (ic, pushResult);
6283 AOP_SET_LOCALS (ic);
6287 genFarFarLogicOp(ic, "xrl");
6292 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6294 AOP_TYPE (left), AOP_TYPE (right));
6295 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6297 AOP_SIZE (left), AOP_SIZE (right));
6300 /* if left is a literal & right is not ||
6301 if left needs acc & right does not */
6302 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6303 #ifdef LOGIC_OPS_BROKEN
6304 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6308 operand *tmp = right;
6313 /* if result = right then exchange them */
6314 if (sameRegs (AOP (result), AOP (right)))
6316 operand *tmp = right;
6321 /* if right is bit then exchange them */
6322 if (AOP_TYPE (right) == AOP_CRY &&
6323 AOP_TYPE (left) != AOP_CRY)
6325 operand *tmp = right;
6329 if (AOP_TYPE (right) == AOP_LIT)
6330 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6332 size = AOP_SIZE (result);
6336 if (AOP_TYPE (left) == AOP_CRY)
6338 if (AOP_TYPE (right) == AOP_LIT)
6340 // c = bit & literal;
6343 // lit>>1 != 0 => result = 1
6344 if (AOP_TYPE (result) == AOP_CRY)
6347 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6349 continueIfTrue (ifx);
6352 emitcode ("setb", "c");
6359 // lit == 0, result = left
6360 if (size && sameRegs (AOP (result), AOP (left)))
6362 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6366 // lit == 1, result = not(left)
6367 if (size && sameRegs (AOP (result), AOP (left)))
6369 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6374 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6375 emitcode ("cpl", "c");
6384 symbol *tlbl = newiTempLabel (NULL);
6385 if (AOP_TYPE (right) == AOP_CRY)
6388 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6392 int sizer = AOP_SIZE (right);
6394 // if val>>1 != 0, result = 1
6395 emitcode ("setb", "c");
6398 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6400 // test the msb of the lsb
6401 emitcode ("anl", "a,#0xfe");
6402 emitcode ("jnz", "%05d$", tlbl->key + 100);
6406 emitcode ("rrc", "a");
6408 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6409 emitcode ("cpl", "c");
6410 emitcode ("", "%05d$:", (tlbl->key + 100));
6417 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6418 genIfxJump (ifx, "c");
6422 if (sameRegs (AOP (result), AOP (left)))
6424 /* if left is same as result */
6425 for (; size--; offset++)
6427 if (AOP_TYPE (right) == AOP_LIT)
6429 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6431 else if (IS_AOP_PREG (left))
6433 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6434 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6435 aopPut (AOP (result), "a", offset);
6438 emitcode ("xrl", "%s,%s",
6439 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6440 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6444 if (AOP_TYPE (left) == AOP_ACC)
6445 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6448 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6449 if (IS_AOP_PREG (left))
6451 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6452 aopPut (AOP (result), "a", offset);
6455 emitcode ("xrl", "%s,a",
6456 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6463 // left & result in different registers
6464 if (AOP_TYPE (result) == AOP_CRY)
6467 // if(size), result in bit
6468 // if(!size && ifx), conditional oper: if(left ^ right)
6469 symbol *tlbl = newiTempLabel (NULL);
6470 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6472 emitcode ("setb", "c");
6475 if ((AOP_TYPE (right) == AOP_LIT) &&
6476 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6478 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6482 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6483 emitcode ("xrl", "a,%s",
6484 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6486 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6487 emitcode ("xrl", "a,%s",
6488 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6491 emitcode ("jnz", "%05d$", tlbl->key + 100);
6497 emitcode ("", "%05d$:", tlbl->key + 100);
6501 jmpTrueOrFalse (ifx, tlbl);
6504 for (; (size--); offset++)
6507 // result = left & right
6508 if (AOP_TYPE (right) == AOP_LIT)
6510 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6512 aopPut (AOP (result),
6513 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6517 D (emitcode (";", "better literal XOR.");
6519 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6520 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6521 FALSE, FALSE, FALSE));
6525 // faster than result <- left, anl result,right
6526 // and better if result is SFR
6527 if (AOP_TYPE (left) == AOP_ACC)
6529 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6530 FALSE, FALSE, FALSE));
6534 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6535 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6537 emitcode("mov", "b,a");
6541 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6542 emitcode ("xrl", "a,%s", rOp);
6545 aopPut (AOP (result), "a", offset);
6550 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6551 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6552 freeAsmop (result, NULL, ic, TRUE);
6555 /*-----------------------------------------------------------------*/
6556 /* genInline - write the inline code out */
6557 /*-----------------------------------------------------------------*/
6559 genInline (iCode * ic)
6561 char *buffer, *bp, *bp1;
6563 D (emitcode (";", "genInline ");
6566 _G.inLine += (!options.asmpeep);
6568 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6569 strcpy (buffer, IC_INLINE (ic));
6571 /* emit each line as a code */
6596 /* emitcode("",buffer); */
6597 _G.inLine -= (!options.asmpeep);
6600 /*-----------------------------------------------------------------*/
6601 /* genRRC - rotate right with carry */
6602 /*-----------------------------------------------------------------*/
6606 operand *left, *result;
6607 int size, offset = 0;
6610 D (emitcode (";", "genRRC ");
6613 /* rotate right with carry */
6614 left = IC_LEFT (ic);
6615 result = IC_RESULT (ic);
6616 aopOp (left, ic, FALSE, FALSE);
6617 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6619 /* move it to the result */
6620 size = AOP_SIZE (result);
6624 _startLazyDPSEvaluation ();
6627 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6629 emitcode ("rrc", "a");
6630 if (AOP_SIZE (result) > 1)
6631 aopPut (AOP (result), "a", offset--);
6633 _endLazyDPSEvaluation ();
6635 /* now we need to put the carry into the
6636 highest order byte of the result */
6637 if (AOP_SIZE (result) > 1)
6639 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6642 emitcode ("mov", "acc.7,c");
6643 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6644 freeAsmop (left, NULL, ic, TRUE);
6645 freeAsmop (result, NULL, ic, TRUE);
6648 /*-----------------------------------------------------------------*/
6649 /* genRLC - generate code for rotate left with carry */
6650 /*-----------------------------------------------------------------*/
6654 operand *left, *result;
6655 int size, offset = 0;
6658 D (emitcode (";", "genRLC ");
6661 /* rotate right with carry */
6662 left = IC_LEFT (ic);
6663 result = IC_RESULT (ic);
6664 aopOp (left, ic, FALSE, FALSE);
6665 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6667 /* move it to the result */
6668 size = AOP_SIZE (result);
6672 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6674 emitcode ("add", "a,acc");
6675 if (AOP_SIZE (result) > 1)
6677 aopPut (AOP (result), "a", offset++);
6680 _startLazyDPSEvaluation ();
6683 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6685 emitcode ("rlc", "a");
6686 if (AOP_SIZE (result) > 1)
6687 aopPut (AOP (result), "a", offset++);
6689 _endLazyDPSEvaluation ();
6691 /* now we need to put the carry into the
6692 highest order byte of the result */
6693 if (AOP_SIZE (result) > 1)
6695 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6698 emitcode ("mov", "acc.0,c");
6699 aopPut (AOP (result), "a", 0);
6700 freeAsmop (left, NULL, ic, TRUE);
6701 freeAsmop (result, NULL, ic, TRUE);
6704 /*-----------------------------------------------------------------*/
6705 /* genGetHbit - generates code get highest order bit */
6706 /*-----------------------------------------------------------------*/
6708 genGetHbit (iCode * ic)
6710 operand *left, *result;
6711 left = IC_LEFT (ic);
6712 result = IC_RESULT (ic);
6713 aopOp (left, ic, FALSE, FALSE);
6714 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6716 D (emitcode (";", "genGetHbit ");
6719 /* get the highest order byte into a */
6720 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6721 if (AOP_TYPE (result) == AOP_CRY)
6723 emitcode ("rlc", "a");
6728 emitcode ("rl", "a");
6729 emitcode ("anl", "a,#0x01");
6734 freeAsmop (left, NULL, ic, TRUE);
6735 freeAsmop (result, NULL, ic, TRUE);
6738 /*-----------------------------------------------------------------*/
6739 /* AccRol - rotate left accumulator by known count */
6740 /*-----------------------------------------------------------------*/
6742 AccRol (int shCount)
6744 shCount &= 0x0007; // shCount : 0..7
6751 emitcode ("rl", "a");
6754 emitcode ("rl", "a");
6755 emitcode ("rl", "a");
6758 emitcode ("swap", "a");
6759 emitcode ("rr", "a");
6762 emitcode ("swap", "a");
6765 emitcode ("swap", "a");
6766 emitcode ("rl", "a");
6769 emitcode ("rr", "a");
6770 emitcode ("rr", "a");
6773 emitcode ("rr", "a");
6778 /*-----------------------------------------------------------------*/
6779 /* AccLsh - left shift accumulator by known count */
6780 /*-----------------------------------------------------------------*/
6782 AccLsh (int shCount)
6787 emitcode ("add", "a,acc");
6788 else if (shCount == 2)
6790 emitcode ("add", "a,acc");
6791 emitcode ("add", "a,acc");
6795 /* rotate left accumulator */
6797 /* and kill the lower order bits */
6798 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6803 /*-----------------------------------------------------------------*/
6804 /* AccRsh - right shift accumulator by known count */
6805 /*-----------------------------------------------------------------*/
6807 AccRsh (int shCount)
6814 emitcode ("rrc", "a");
6818 /* rotate right accumulator */
6819 AccRol (8 - shCount);
6820 /* and kill the higher order bits */
6821 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6826 #ifdef BETTER_LITERAL_SHIFT
6827 /*-----------------------------------------------------------------*/
6828 /* AccSRsh - signed right shift accumulator by known count */
6829 /*-----------------------------------------------------------------*/
6831 AccSRsh (int shCount)
6838 emitcode ("mov", "c,acc.7");
6839 emitcode ("rrc", "a");
6841 else if (shCount == 2)
6843 emitcode ("mov", "c,acc.7");
6844 emitcode ("rrc", "a");
6845 emitcode ("mov", "c,acc.7");
6846 emitcode ("rrc", "a");
6850 tlbl = newiTempLabel (NULL);
6851 /* rotate right accumulator */
6852 AccRol (8 - shCount);
6853 /* and kill the higher order bits */
6854 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6855 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6856 emitcode ("orl", "a,#0x%02x",
6857 (unsigned char) ~SRMask[shCount]);
6858 emitcode ("", "%05d$:", tlbl->key + 100);
6864 #ifdef BETTER_LITERAL_SHIFT
6865 /*-----------------------------------------------------------------*/
6866 /* shiftR1Left2Result - shift right one byte from left to result */
6867 /*-----------------------------------------------------------------*/
6869 shiftR1Left2Result (operand * left, int offl,
6870 operand * result, int offr,
6871 int shCount, int sign)
6873 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6874 /* shift right accumulator */
6879 aopPut (AOP (result), "a", offr);
6883 #ifdef BETTER_LITERAL_SHIFT
6884 /*-----------------------------------------------------------------*/
6885 /* shiftL1Left2Result - shift left one byte from left to result */
6886 /*-----------------------------------------------------------------*/
6888 shiftL1Left2Result (operand * left, int offl,
6889 operand * result, int offr, int shCount)
6891 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6892 /* shift left accumulator */
6894 aopPut (AOP (result), "a", offr);
6898 #ifdef BETTER_LITERAL_SHIFT
6899 /*-----------------------------------------------------------------*/
6900 /* movLeft2Result - move byte from left to result */
6901 /*-----------------------------------------------------------------*/
6903 movLeft2Result (operand * left, int offl,
6904 operand * result, int offr, int sign)
6907 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6909 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6911 if (*l == '@' && (IS_AOP_PREG (result)))
6913 emitcode ("mov", "a,%s", l);
6914 aopPut (AOP (result), "a", offr);
6920 aopPut (AOP (result), l, offr);
6924 /* MSB sign in acc.7 ! */
6925 if (getDataSize (left) == offl + 1)
6927 emitcode ("mov", "a,%s", l);
6928 aopPut (AOP (result), "a", offr);
6936 #ifdef BETTER_LITERAL_SHIFT
6937 /*-----------------------------------------------------------------*/
6938 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6939 /*-----------------------------------------------------------------*/
6943 emitcode ("rrc", "a");
6944 emitcode ("xch", "a,%s", x);
6945 emitcode ("rrc", "a");
6946 emitcode ("xch", "a,%s", x);
6950 #ifdef BETTER_LITERAL_SHIFT
6952 /*-----------------------------------------------------------------*/
6953 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6954 /*-----------------------------------------------------------------*/
6958 emitcode ("xch", "a,%s", x);
6959 emitcode ("rlc", "a");
6960 emitcode ("xch", "a,%s", x);
6961 emitcode ("rlc", "a");
6965 #ifdef BETTER_LITERAL_SHIFT
6966 /*-----------------------------------------------------------------*/
6967 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6968 /*-----------------------------------------------------------------*/
6972 emitcode ("xch", "a,%s", x);
6973 emitcode ("add", "a,acc");
6974 emitcode ("xch", "a,%s", x);
6975 emitcode ("rlc", "a");
6979 #ifdef BETTER_LITERAL_SHIFT
6980 /*-----------------------------------------------------------------*/
6981 /* AccAXLsh - left shift a:x by known count (0..7) */
6982 /*-----------------------------------------------------------------*/
6984 AccAXLsh (char *x, int shCount)
6999 case 5: // AAAAABBB:CCCCCDDD
7001 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7003 emitcode ("anl", "a,#0x%02x",
7004 SLMask[shCount]); // BBB00000:CCCCCDDD
7006 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7008 AccRol (shCount); // DDDCCCCC:BBB00000
7010 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7012 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7014 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7016 emitcode ("anl", "a,#0x%02x",
7017 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7019 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7021 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7024 case 6: // AAAAAABB:CCCCCCDD
7025 emitcode ("anl", "a,#0x%02x",
7026 SRMask[shCount]); // 000000BB:CCCCCCDD
7027 emitcode ("mov", "c,acc.0"); // c = B
7028 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7030 AccAXRrl1 (x); // BCCCCCCD:D000000B
7031 AccAXRrl1 (x); // BBCCCCCC:DD000000
7033 emitcode("rrc","a");
7034 emitcode("xch","a,%s", x);
7035 emitcode("rrc","a");
7036 emitcode("mov","c,acc.0"); //<< get correct bit
7037 emitcode("xch","a,%s", x);
7039 emitcode("rrc","a");
7040 emitcode("xch","a,%s", x);
7041 emitcode("rrc","a");
7042 emitcode("xch","a,%s", x);
7045 case 7: // a:x <<= 7
7047 emitcode ("anl", "a,#0x%02x",
7048 SRMask[shCount]); // 0000000B:CCCCCCCD
7050 emitcode ("mov", "c,acc.0"); // c = B
7052 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7054 AccAXRrl1 (x); // BCCCCCCC:D0000000
7063 #ifdef BETTER_LITERAL_SHIFT
7065 /*-----------------------------------------------------------------*/
7066 /* AccAXRsh - right shift a:x known count (0..7) */
7067 /*-----------------------------------------------------------------*/
7069 AccAXRsh (char *x, int shCount)
7077 AccAXRrl1 (x); // 0->a:x
7082 AccAXRrl1 (x); // 0->a:x
7085 AccAXRrl1 (x); // 0->a:x
7090 case 5: // AAAAABBB:CCCCCDDD = a:x
7092 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7094 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7096 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7098 emitcode ("anl", "a,#0x%02x",
7099 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7101 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7103 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7105 emitcode ("anl", "a,#0x%02x",
7106 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7108 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7110 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7112 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7115 case 6: // AABBBBBB:CCDDDDDD
7117 emitcode ("mov", "c,acc.7");
7118 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7120 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7122 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7124 emitcode ("anl", "a,#0x%02x",
7125 SRMask[shCount]); // 000000AA:BBBBBBCC
7128 case 7: // ABBBBBBB:CDDDDDDD
7130 emitcode ("mov", "c,acc.7"); // c = A
7132 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7134 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7136 emitcode ("anl", "a,#0x%02x",
7137 SRMask[shCount]); // 0000000A:BBBBBBBC
7146 #ifdef BETTER_LITERAL_SHIFT
7147 /*-----------------------------------------------------------------*/
7148 /* AccAXRshS - right shift signed a:x known count (0..7) */
7149 /*-----------------------------------------------------------------*/
7151 AccAXRshS (char *x, int shCount)
7159 emitcode ("mov", "c,acc.7");
7160 AccAXRrl1 (x); // s->a:x
7164 emitcode ("mov", "c,acc.7");
7165 AccAXRrl1 (x); // s->a:x
7167 emitcode ("mov", "c,acc.7");
7168 AccAXRrl1 (x); // s->a:x
7173 case 5: // AAAAABBB:CCCCCDDD = a:x
7175 tlbl = newiTempLabel (NULL);
7176 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7178 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7180 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7182 emitcode ("anl", "a,#0x%02x",
7183 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7185 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7187 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7189 emitcode ("anl", "a,#0x%02x",
7190 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7192 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7194 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7196 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7198 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7199 emitcode ("orl", "a,#0x%02x",
7200 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7202 emitcode ("", "%05d$:", tlbl->key + 100);
7203 break; // SSSSAAAA:BBBCCCCC
7205 case 6: // AABBBBBB:CCDDDDDD
7207 tlbl = newiTempLabel (NULL);
7208 emitcode ("mov", "c,acc.7");
7209 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7211 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7213 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7215 emitcode ("anl", "a,#0x%02x",
7216 SRMask[shCount]); // 000000AA:BBBBBBCC
7218 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7219 emitcode ("orl", "a,#0x%02x",
7220 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7222 emitcode ("", "%05d$:", tlbl->key + 100);
7224 case 7: // ABBBBBBB:CDDDDDDD
7226 tlbl = newiTempLabel (NULL);
7227 emitcode ("mov", "c,acc.7"); // c = A
7229 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7231 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7233 emitcode ("anl", "a,#0x%02x",
7234 SRMask[shCount]); // 0000000A:BBBBBBBC
7236 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7237 emitcode ("orl", "a,#0x%02x",
7238 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7240 emitcode ("", "%05d$:", tlbl->key + 100);
7248 #ifdef BETTER_LITERAL_SHIFT
7250 _loadLeftIntoAx(char **lsb,
7256 // Get the initial value from left into a pair of registers.
7257 // MSB must be in A, LSB can be any register.
7259 // If the result is held in registers, it is an optimization
7260 // if the LSB can be held in the register which will hold the,
7261 // result LSB since this saves us from having to copy it into
7262 // the result following AccAXLsh.
7264 // If the result is addressed indirectly, this is not a gain.
7265 if (AOP_NEEDSACC(result))
7269 _startLazyDPSEvaluation();
7270 if (AOP_TYPE(left) == AOP_DPTR2)
7273 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7274 // get LSB in DP2_RESULT_REG.
7275 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7276 assert(!strcmp(leftByte, DP2_RESULT_REG));
7280 // get LSB into DP2_RESULT_REG
7281 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7282 if (strcmp(leftByte, DP2_RESULT_REG))
7285 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7288 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7289 assert(strcmp(leftByte, DP2_RESULT_REG));
7292 _endLazyDPSEvaluation();
7293 *lsb = DP2_RESULT_REG;
7297 if (sameRegs (AOP (result), AOP (left)) &&
7298 ((offl + MSB16) == offr))
7300 /* don't crash result[offr] */
7301 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7302 emitcode ("xch", "a,%s",
7303 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7307 movLeft2Result (left, offl, result, offr, 0);
7308 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7310 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7311 assert(strcmp(*lsb,"a"));
7316 _storeAxResults(char *lsb,
7320 _startLazyDPSEvaluation();
7321 if (AOP_NEEDSACC(result))
7323 /* We have to explicitly update the result LSB.
7325 emitcode("xch","a,%s", lsb);
7326 aopPut(AOP(result), "a", offr);
7327 emitcode("mov","a,%s", lsb);
7329 if (getDataSize (result) > 1)
7331 aopPut (AOP (result), "a", offr + MSB16);
7333 _endLazyDPSEvaluation();
7336 /*-----------------------------------------------------------------*/
7337 /* shiftL2Left2Result - shift left two bytes from left to result */
7338 /*-----------------------------------------------------------------*/
7340 shiftL2Left2Result (operand * left, int offl,
7341 operand * result, int offr, int shCount)
7345 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7347 AccAXLsh (lsb, shCount);
7349 _storeAxResults(lsb, result, offr);
7353 #ifdef BETTER_LITERAL_SHIFT
7354 /*-----------------------------------------------------------------*/
7355 /* shiftR2Left2Result - shift right two bytes from left to result */
7356 /*-----------------------------------------------------------------*/
7358 shiftR2Left2Result (operand * left, int offl,
7359 operand * result, int offr,
7360 int shCount, int sign)
7364 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7366 /* a:x >> shCount (x = lsb(result)) */
7369 AccAXRshS(lsb, shCount);
7373 AccAXRsh(lsb, shCount);
7376 _storeAxResults(lsb, result, offr);
7382 /*-----------------------------------------------------------------*/
7383 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7384 /*-----------------------------------------------------------------*/
7386 shiftLLeftOrResult (operand * left, int offl,
7387 operand * result, int offr, int shCount)
7389 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7390 /* shift left accumulator */
7392 /* or with result */
7393 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7394 /* back to result */
7395 aopPut (AOP (result), "a", offr);
7401 /*-----------------------------------------------------------------*/
7402 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7403 /*-----------------------------------------------------------------*/
7405 shiftRLeftOrResult (operand * left, int offl,
7406 operand * result, int offr, int shCount)
7408 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7409 /* shift right accumulator */
7411 /* or with result */
7412 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7413 /* back to result */
7414 aopPut (AOP (result), "a", offr);
7418 #ifdef BETTER_LITERAL_SHIFT
7419 /*-----------------------------------------------------------------*/
7420 /* genlshOne - left shift a one byte quantity by known count */
7421 /*-----------------------------------------------------------------*/
7423 genlshOne (operand * result, operand * left, int shCount)
7425 D (emitcode (";", "genlshOne "););
7426 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7430 #ifdef BETTER_LITERAL_SHIFT
7431 /*-----------------------------------------------------------------*/
7432 /* genlshTwo - left shift two bytes by known amount != 0 */
7433 /*-----------------------------------------------------------------*/
7435 genlshTwo (operand * result, operand * left, int shCount)
7439 D (emitcode (";", "genlshTwo "););
7441 size = getDataSize (result);
7443 /* if shCount >= 8 */
7448 _startLazyDPSEvaluation();
7454 _endLazyDPSEvaluation();
7455 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7456 aopPut (AOP (result), zero, LSB);
7460 movLeft2Result (left, LSB, result, MSB16, 0);
7461 aopPut (AOP (result), zero, LSB);
7462 _endLazyDPSEvaluation();
7467 aopPut (AOP (result), zero, LSB);
7468 _endLazyDPSEvaluation();
7472 /* 1 <= shCount <= 7 */
7477 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7481 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7489 /*-----------------------------------------------------------------*/
7490 /* shiftLLong - shift left one long from left to result */
7491 /* offl = LSB or MSB16 */
7492 /*-----------------------------------------------------------------*/
7494 shiftLLong (operand * left, operand * result, int offr)
7497 int size = AOP_SIZE (result);
7499 if (size >= LSB + offr)
7501 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7503 emitcode ("add", "a,acc");
7504 if (sameRegs (AOP (left), AOP (result)) &&
7505 size >= MSB16 + offr && offr != LSB)
7506 emitcode ("xch", "a,%s",
7507 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7509 aopPut (AOP (result), "a", LSB + offr);
7512 if (size >= MSB16 + offr)
7514 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7516 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7519 emitcode ("rlc", "a");
7520 if (sameRegs (AOP (left), AOP (result)) &&
7521 size >= MSB24 + offr && offr != LSB)
7522 emitcode ("xch", "a,%s",
7523 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7525 aopPut (AOP (result), "a", MSB16 + offr);
7528 if (size >= MSB24 + offr)
7530 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7532 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7535 emitcode ("rlc", "a");
7536 if (sameRegs (AOP (left), AOP (result)) &&
7537 size >= MSB32 + offr && offr != LSB)
7538 emitcode ("xch", "a,%s",
7539 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7541 aopPut (AOP (result), "a", MSB24 + offr);
7544 if (size > MSB32 + offr)
7546 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7548 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7551 emitcode ("rlc", "a");
7552 aopPut (AOP (result), "a", MSB32 + offr);
7555 aopPut (AOP (result), zero, LSB);
7561 /*-----------------------------------------------------------------*/
7562 /* genlshFour - shift four byte by a known amount != 0 */
7563 /*-----------------------------------------------------------------*/
7565 genlshFour (operand * result, operand * left, int shCount)
7569 D (emitcode (";", "genlshFour ");
7572 size = AOP_SIZE (result);
7574 /* if shifting more that 3 bytes */
7579 /* lowest order of left goes to the highest
7580 order of the destination */
7581 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7583 movLeft2Result (left, LSB, result, MSB32, 0);
7584 aopPut (AOP (result), zero, LSB);
7585 aopPut (AOP (result), zero, MSB16);
7586 aopPut (AOP (result), zero, MSB24);
7590 /* more than two bytes */
7591 else if (shCount >= 16)
7593 /* lower order two bytes goes to higher order two bytes */
7595 /* if some more remaining */
7597 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7600 movLeft2Result (left, MSB16, result, MSB32, 0);
7601 movLeft2Result (left, LSB, result, MSB24, 0);
7603 aopPut (AOP (result), zero, MSB16);
7604 aopPut (AOP (result), zero, LSB);
7608 /* if more than 1 byte */
7609 else if (shCount >= 8)
7611 /* lower order three bytes goes to higher order three bytes */
7616 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7618 movLeft2Result (left, LSB, result, MSB16, 0);
7624 movLeft2Result (left, MSB24, result, MSB32, 0);
7625 movLeft2Result (left, MSB16, result, MSB24, 0);
7626 movLeft2Result (left, LSB, result, MSB16, 0);
7627 aopPut (AOP (result), zero, LSB);
7629 else if (shCount == 1)
7630 shiftLLong (left, result, MSB16);
7633 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7634 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7635 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7636 aopPut (AOP (result), zero, LSB);
7641 /* 1 <= shCount <= 7 */
7642 else if (shCount <= 2)
7644 shiftLLong (left, result, LSB);
7646 shiftLLong (result, result, LSB);
7648 /* 3 <= shCount <= 7, optimize */
7651 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7652 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7653 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7658 #ifdef BETTER_LITERAL_SHIFT
7659 /*-----------------------------------------------------------------*/
7660 /* genLeftShiftLiteral - left shifting by known count */
7661 /*-----------------------------------------------------------------*/
7663 genLeftShiftLiteral (operand * left,
7668 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7671 size = getSize (operandType (result));
7673 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7675 /* We only handle certain easy cases so far. */
7677 && (shCount < (size * 8))
7681 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7685 freeAsmop (right, NULL, ic, TRUE);
7687 aopOp(left, ic, FALSE, FALSE);
7688 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7691 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7693 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7694 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7696 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7699 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7701 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7702 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7704 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7710 emitcode ("; shift left ", "result %d, left %d", size,
7714 /* I suppose that the left size >= result size */
7717 _startLazyDPSEvaluation();
7720 movLeft2Result (left, size, result, size, 0);
7722 _endLazyDPSEvaluation();
7724 else if (shCount >= (size * 8))
7726 _startLazyDPSEvaluation();
7729 aopPut (AOP (result), zero, size);
7731 _endLazyDPSEvaluation();
7738 genlshOne (result, left, shCount);
7742 genlshTwo (result, left, shCount);
7746 genlshFour (result, left, shCount);
7750 fprintf(stderr, "*** ack! mystery literal shift!\n");
7754 freeAsmop (left, NULL, ic, TRUE);
7755 freeAsmop (result, NULL, ic, TRUE);
7760 /*-----------------------------------------------------------------*/
7761 /* genLeftShift - generates code for left shifting */
7762 /*-----------------------------------------------------------------*/
7764 genLeftShift (iCode * ic)
7766 operand *left, *right, *result;
7769 symbol *tlbl, *tlbl1;
7771 D (emitcode (";", "genLeftShift "););
7773 right = IC_RIGHT (ic);
7774 left = IC_LEFT (ic);
7775 result = IC_RESULT (ic);
7777 aopOp (right, ic, FALSE, FALSE);
7780 #ifdef BETTER_LITERAL_SHIFT
7781 /* if the shift count is known then do it
7782 as efficiently as possible */
7783 if (AOP_TYPE (right) == AOP_LIT)
7785 if (genLeftShiftLiteral (left, right, result, ic))
7792 /* shift count is unknown then we have to form
7793 a loop get the loop count in B : Note: we take
7794 only the lower order byte since shifting
7795 more that 32 bits make no sense anyway, ( the
7796 largest size of an object can be only 32 bits ) */
7798 if (AOP_TYPE (right) == AOP_LIT)
7800 /* Really should be handled by genLeftShiftLiteral,
7801 * but since I'm too lazy to fix that today, at least we can make
7802 * some small improvement.
7804 emitcode("mov", "b,#0x%02x",
7805 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7809 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7810 emitcode ("inc", "b");
7812 freeAsmop (right, NULL, ic, TRUE);
7813 aopOp (left, ic, FALSE, FALSE);
7814 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7816 /* now move the left to the result if they are not the
7818 if (!sameRegs (AOP (left), AOP (result)) &&
7819 AOP_SIZE (result) > 1)
7822 size = AOP_SIZE (result);
7824 _startLazyDPSEvaluation ();
7827 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7828 if (*l == '@' && (IS_AOP_PREG (result)))
7831 emitcode ("mov", "a,%s", l);
7832 aopPut (AOP (result), "a", offset);
7835 aopPut (AOP (result), l, offset);
7838 _endLazyDPSEvaluation ();
7841 tlbl = newiTempLabel (NULL);
7842 size = AOP_SIZE (result);
7844 tlbl1 = newiTempLabel (NULL);
7846 /* if it is only one byte then */
7849 symbol *tlbl1 = newiTempLabel (NULL);
7851 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7853 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7854 emitcode ("", "%05d$:", tlbl->key + 100);
7855 emitcode ("add", "a,acc");
7856 emitcode ("", "%05d$:", tlbl1->key + 100);
7857 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7858 aopPut (AOP (result), "a", 0);
7862 reAdjustPreg (AOP (result));
7864 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7865 emitcode ("", "%05d$:", tlbl->key + 100);
7866 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7868 emitcode ("add", "a,acc");
7869 aopPut (AOP (result), "a", offset++);
7870 _startLazyDPSEvaluation ();
7873 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7875 emitcode ("rlc", "a");
7876 aopPut (AOP (result), "a", offset++);
7878 _endLazyDPSEvaluation ();
7879 reAdjustPreg (AOP (result));
7881 emitcode ("", "%05d$:", tlbl1->key + 100);
7882 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7884 freeAsmop (left, NULL, ic, TRUE);
7885 freeAsmop (result, NULL, ic, TRUE);
7888 #ifdef BETTER_LITERAL_SHIFT
7889 /*-----------------------------------------------------------------*/
7890 /* genrshOne - right shift a one byte quantity by known count */
7891 /*-----------------------------------------------------------------*/
7893 genrshOne (operand * result, operand * left,
7894 int shCount, int sign)
7896 D (emitcode (";", "genrshOne"););
7897 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7901 #ifdef BETTER_LITERAL_SHIFT
7902 /*-----------------------------------------------------------------*/
7903 /* genrshTwo - right shift two bytes by known amount != 0 */
7904 /*-----------------------------------------------------------------*/
7906 genrshTwo (operand * result, operand * left,
7907 int shCount, int sign)
7909 D (emitcode (";", "genrshTwo"););
7911 /* if shCount >= 8 */
7915 _startLazyDPSEvaluation();
7918 shiftR1Left2Result (left, MSB16, result, LSB,
7923 movLeft2Result (left, MSB16, result, LSB, sign);
7925 addSign (result, MSB16, sign);
7926 _endLazyDPSEvaluation();
7929 /* 1 <= shCount <= 7 */
7932 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7939 /*-----------------------------------------------------------------*/
7940 /* shiftRLong - shift right one long from left to result */
7941 /* offl = LSB or MSB16 */
7942 /*-----------------------------------------------------------------*/
7944 shiftRLong (operand * left, int offl,
7945 operand * result, int sign)
7947 int isSameRegs=sameRegs(AOP(left),AOP(result));
7949 if (isSameRegs && offl>1) {
7950 // we are in big trouble, but this shouldn't happen
7951 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7954 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7959 emitcode ("rlc", "a");
7960 emitcode ("subb", "a,acc");
7961 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7963 aopPut (AOP(result), zero, MSB32);
7968 emitcode ("clr", "c");
7970 emitcode ("mov", "c,acc.7");
7973 emitcode ("rrc", "a");
7975 if (isSameRegs && offl==MSB16) {
7976 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7978 aopPut (AOP (result), "a", MSB32);
7979 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7982 emitcode ("rrc", "a");
7983 if (isSameRegs && offl==1) {
7984 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7986 aopPut (AOP (result), "a", MSB24);
7987 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7989 emitcode ("rrc", "a");
7990 aopPut (AOP (result), "a", MSB16 - offl);
7994 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7995 emitcode ("rrc", "a");
7996 aopPut (AOP (result), "a", LSB);
8003 /*-----------------------------------------------------------------*/
8004 /* genrshFour - shift four byte by a known amount != 0 */
8005 /*-----------------------------------------------------------------*/
8007 genrshFour (operand * result, operand * left,
8008 int shCount, int sign)
8010 D (emitcode (";", "genrshFour");
8013 /* if shifting more that 3 bytes */
8018 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8020 movLeft2Result (left, MSB32, result, LSB, sign);
8021 addSign (result, MSB16, sign);
8023 else if (shCount >= 16)
8027 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8030 movLeft2Result (left, MSB24, result, LSB, 0);
8031 movLeft2Result (left, MSB32, result, MSB16, sign);
8033 addSign (result, MSB24, sign);
8035 else if (shCount >= 8)
8039 shiftRLong (left, MSB16, result, sign);
8040 else if (shCount == 0)
8042 movLeft2Result (left, MSB16, result, LSB, 0);
8043 movLeft2Result (left, MSB24, result, MSB16, 0);
8044 movLeft2Result (left, MSB32, result, MSB24, sign);
8045 addSign (result, MSB32, sign);
8049 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8050 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8051 /* the last shift is signed */
8052 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8053 addSign (result, MSB32, sign);
8057 { /* 1 <= shCount <= 7 */
8060 shiftRLong (left, LSB, result, sign);
8062 shiftRLong (result, LSB, result, sign);
8066 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8067 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8068 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8074 #ifdef BETTER_LITERAL_SHIFT
8075 /*-----------------------------------------------------------------*/
8076 /* genRightShiftLiteral - right shifting by known count */
8077 /*-----------------------------------------------------------------*/
8079 genRightShiftLiteral (operand * left,
8085 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8088 size = getSize (operandType (result));
8090 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8092 /* We only handle certain easy cases so far. */
8094 && (shCount < (size * 8))
8098 D(emitcode (";", "genRightShiftLiteral wimping out"););
8102 freeAsmop (right, NULL, ic, TRUE);
8104 aopOp (left, ic, FALSE, FALSE);
8105 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8108 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8112 /* test the LEFT size !!! */
8114 /* I suppose that the left size >= result size */
8117 size = getDataSize (result);
8118 _startLazyDPSEvaluation();
8121 movLeft2Result (left, size, result, size, 0);
8123 _endLazyDPSEvaluation();
8125 else if (shCount >= (size * 8))
8129 /* get sign in acc.7 */
8130 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8132 addSign (result, LSB, sign);
8139 genrshOne (result, left, shCount, sign);
8143 genrshTwo (result, left, shCount, sign);
8147 genrshFour (result, left, shCount, sign);
8154 freeAsmop (left, NULL, ic, TRUE);
8155 freeAsmop (result, NULL, ic, TRUE);
8161 /*-----------------------------------------------------------------*/
8162 /* genSignedRightShift - right shift of signed number */
8163 /*-----------------------------------------------------------------*/
8165 genSignedRightShift (iCode * ic)
8167 operand *right, *left, *result;
8170 symbol *tlbl, *tlbl1;
8172 D (emitcode (";", "genSignedRightShift "););
8174 /* we do it the hard way put the shift count in b
8175 and loop thru preserving the sign */
8177 right = IC_RIGHT (ic);
8178 left = IC_LEFT (ic);
8179 result = IC_RESULT (ic);
8181 aopOp (right, ic, FALSE, FALSE);
8183 #ifdef BETTER_LITERAL_SHIFT
8184 if (AOP_TYPE (right) == AOP_LIT)
8186 if (genRightShiftLiteral (left, right, result, ic, 1))
8192 /* shift count is unknown then we have to form
8193 a loop get the loop count in B : Note: we take
8194 only the lower order byte since shifting
8195 more that 32 bits make no sense anyway, ( the
8196 largest size of an object can be only 32 bits ) */
8198 if (AOP_TYPE (right) == AOP_LIT)
8200 /* Really should be handled by genRightShiftLiteral,
8201 * but since I'm too lazy to fix that today, at least we can make
8202 * some small improvement.
8204 emitcode("mov", "b,#0x%02x",
8205 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8209 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8210 emitcode ("inc", "b");
8212 freeAsmop (right, NULL, ic, TRUE);
8213 aopOp (left, ic, FALSE, FALSE);
8214 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8216 /* now move the left to the result if they are not the
8218 if (!sameRegs (AOP (left), AOP (result)) &&
8219 AOP_SIZE (result) > 1)
8222 size = AOP_SIZE (result);
8224 _startLazyDPSEvaluation ();
8227 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8228 if (*l == '@' && IS_AOP_PREG (result))
8231 emitcode ("mov", "a,%s", l);
8232 aopPut (AOP (result), "a", offset);
8235 aopPut (AOP (result), l, offset);
8238 _endLazyDPSEvaluation ();
8241 /* mov the highest order bit to OVR */
8242 tlbl = newiTempLabel (NULL);
8243 tlbl1 = newiTempLabel (NULL);
8245 size = AOP_SIZE (result);
8247 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8248 emitcode ("rlc", "a");
8249 emitcode ("mov", "ov,c");
8250 /* if it is only one byte then */
8253 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8255 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8256 emitcode ("", "%05d$:", tlbl->key + 100);
8257 emitcode ("mov", "c,ov");
8258 emitcode ("rrc", "a");
8259 emitcode ("", "%05d$:", tlbl1->key + 100);
8260 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8261 aopPut (AOP (result), "a", 0);
8265 reAdjustPreg (AOP (result));
8266 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8267 emitcode ("", "%05d$:", tlbl->key + 100);
8268 emitcode ("mov", "c,ov");
8269 _startLazyDPSEvaluation ();
8272 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8274 emitcode ("rrc", "a");
8275 aopPut (AOP (result), "a", offset--);
8277 _endLazyDPSEvaluation ();
8278 reAdjustPreg (AOP (result));
8279 emitcode ("", "%05d$:", tlbl1->key + 100);
8280 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8283 freeAsmop (left, NULL, ic, TRUE);
8284 freeAsmop (result, NULL, ic, TRUE);
8287 /*-----------------------------------------------------------------*/
8288 /* genRightShift - generate code for right shifting */
8289 /*-----------------------------------------------------------------*/
8291 genRightShift (iCode * ic)
8293 operand *right, *left, *result;
8297 symbol *tlbl, *tlbl1;
8299 D (emitcode (";", "genRightShift "););
8301 /* if signed then we do it the hard way preserve the
8302 sign bit moving it inwards */
8303 retype = getSpec (operandType (IC_RESULT (ic)));
8305 if (!SPEC_USIGN (retype))
8307 genSignedRightShift (ic);
8311 /* signed & unsigned types are treated the same : i.e. the
8312 signed is NOT propagated inwards : quoting from the
8313 ANSI - standard : "for E1 >> E2, is equivalent to division
8314 by 2**E2 if unsigned or if it has a non-negative value,
8315 otherwise the result is implementation defined ", MY definition
8316 is that the sign does not get propagated */
8318 right = IC_RIGHT (ic);
8319 left = IC_LEFT (ic);
8320 result = IC_RESULT (ic);
8322 aopOp (right, ic, FALSE, FALSE);
8324 #ifdef BETTER_LITERAL_SHIFT
8325 /* if the shift count is known then do it
8326 as efficiently as possible */
8327 if (AOP_TYPE (right) == AOP_LIT)
8329 if (genRightShiftLiteral (left, right, result, ic, 0))
8336 /* shift count is unknown then we have to form
8337 a loop get the loop count in B : Note: we take
8338 only the lower order byte since shifting
8339 more that 32 bits make no sense anyway, ( the
8340 largest size of an object can be only 32 bits ) */
8342 if (AOP_TYPE (right) == AOP_LIT)
8344 /* Really should be handled by genRightShiftLiteral,
8345 * but since I'm too lazy to fix that today, at least we can make
8346 * some small improvement.
8348 emitcode("mov", "b,#0x%02x",
8349 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8353 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8354 emitcode ("inc", "b");
8356 freeAsmop (right, NULL, ic, TRUE);
8357 aopOp (left, ic, FALSE, FALSE);
8358 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8360 /* now move the left to the result if they are not the
8362 if (!sameRegs (AOP (left), AOP (result)) &&
8363 AOP_SIZE (result) > 1)
8366 size = AOP_SIZE (result);
8368 _startLazyDPSEvaluation ();
8371 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8372 if (*l == '@' && IS_AOP_PREG (result))
8375 emitcode ("mov", "a,%s", l);
8376 aopPut (AOP (result), "a", offset);
8379 aopPut (AOP (result), l, offset);
8382 _endLazyDPSEvaluation ();
8385 tlbl = newiTempLabel (NULL);
8386 tlbl1 = newiTempLabel (NULL);
8387 size = AOP_SIZE (result);
8390 /* if it is only one byte then */
8393 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8395 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8396 emitcode ("", "%05d$:", tlbl->key + 100);
8398 emitcode ("rrc", "a");
8399 emitcode ("", "%05d$:", tlbl1->key + 100);
8400 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8401 aopPut (AOP (result), "a", 0);
8405 reAdjustPreg (AOP (result));
8406 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8407 emitcode ("", "%05d$:", tlbl->key + 100);
8409 _startLazyDPSEvaluation ();
8412 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8414 emitcode ("rrc", "a");
8415 aopPut (AOP (result), "a", offset--);
8417 _endLazyDPSEvaluation ();
8418 reAdjustPreg (AOP (result));
8420 emitcode ("", "%05d$:", tlbl1->key + 100);
8421 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8424 freeAsmop (left, NULL, ic, TRUE);
8425 freeAsmop (result, NULL, ic, TRUE);
8428 /*-----------------------------------------------------------------*/
8429 /* genUnpackBits - generates code for unpacking bits */
8430 /*-----------------------------------------------------------------*/
8432 genUnpackBits (operand * result, char *rname, int ptype)
8439 D (emitcode (";", "genUnpackBits ");
8442 etype = getSpec (operandType (result));
8444 /* read the first byte */
8450 emitcode ("mov", "a,@%s", rname);
8454 emitcode ("movx", "a,@%s", rname);
8458 emitcode ("movx", "a,@dptr");
8462 emitcode ("clr", "a");
8463 emitcode ("movc", "a,@a+dptr");
8467 emitcode ("lcall", "__gptrget");
8471 /* if we have bitdisplacement then it fits */
8472 /* into this byte completely or if length is */
8473 /* less than a byte */
8474 if ((shCnt = SPEC_BSTR (etype)) ||
8475 (SPEC_BLEN (etype) <= 8))
8478 /* shift right acc */
8481 emitcode ("anl", "a,#0x%02x",
8482 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8483 aopPut (AOP (result), "a", offset);
8487 /* bit field did not fit in a byte */
8488 rlen = SPEC_BLEN (etype) - 8;
8489 aopPut (AOP (result), "a", offset++);
8498 emitcode ("inc", "%s", rname);
8499 emitcode ("mov", "a,@%s", rname);
8503 emitcode ("inc", "%s", rname);
8504 emitcode ("movx", "a,@%s", rname);
8508 emitcode ("inc", "dptr");
8509 emitcode ("movx", "a,@dptr");
8513 emitcode ("clr", "a");
8514 emitcode ("inc", "dptr");
8515 emitcode ("movc", "a,@a+dptr");
8519 emitcode ("inc", "dptr");
8520 emitcode ("lcall", "__gptrget");
8525 /* if we are done */
8529 aopPut (AOP (result), "a", offset++);
8535 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
8536 aopPut (AOP (result), "a", offset);
8543 /*-----------------------------------------------------------------*/
8544 /* genDataPointerGet - generates code when ptr offset is known */
8545 /*-----------------------------------------------------------------*/
8547 genDataPointerGet (operand * left,
8553 int size, offset = 0;
8554 aopOp (result, ic, TRUE, FALSE);
8556 /* get the string representation of the name */
8557 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8558 size = AOP_SIZE (result);
8559 _startLazyDPSEvaluation ();
8563 sprintf (buffer, "(%s + %d)", l + 1, offset);
8565 sprintf (buffer, "%s", l + 1);
8566 aopPut (AOP (result), buffer, offset++);
8568 _endLazyDPSEvaluation ();
8570 freeAsmop (left, NULL, ic, TRUE);
8571 freeAsmop (result, NULL, ic, TRUE);
8574 /*-----------------------------------------------------------------*/
8575 /* genNearPointerGet - emitcode for near pointer fetch */
8576 /*-----------------------------------------------------------------*/
8578 genNearPointerGet (operand * left,
8586 sym_link *rtype, *retype, *letype;
8587 sym_link *ltype = operandType (left);
8590 rtype = operandType (result);
8591 retype = getSpec (rtype);
8592 letype = getSpec (ltype);
8594 aopOp (left, ic, FALSE, FALSE);
8596 /* if left is rematerialisable and
8597 result is not bit variable type and
8598 the left is pointer to data space i.e
8599 lower 128 bytes of space */
8600 if (AOP_TYPE (left) == AOP_IMMD &&
8601 !IS_BITVAR (retype) &&
8602 !IS_BITVAR (letype) &&
8603 DCL_TYPE (ltype) == POINTER)
8605 genDataPointerGet (left, result, ic);
8609 /* if the value is already in a pointer register
8610 then don't need anything more */
8611 if (!AOP_INPREG (AOP (left)))
8613 /* otherwise get a free pointer register */
8615 preg = getFreePtr (ic, &aop, FALSE);
8616 emitcode ("mov", "%s,%s",
8618 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8622 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8624 freeAsmop (left, NULL, ic, TRUE);
8625 aopOp (result, ic, FALSE, FALSE);
8627 /* if bitfield then unpack the bits */
8628 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8629 genUnpackBits (result, rname, POINTER);
8632 /* we have can just get the values */
8633 int size = AOP_SIZE (result);
8638 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8641 emitcode ("mov", "a,@%s", rname);
8642 aopPut (AOP (result), "a", offset);
8646 sprintf (buffer, "@%s", rname);
8647 aopPut (AOP (result), buffer, offset);
8651 emitcode ("inc", "%s", rname);
8655 /* now some housekeeping stuff */
8658 /* we had to allocate for this iCode */
8659 if (pi) { /* post increment present */
8660 aopPut(AOP ( left ),rname,0);
8662 freeAsmop (NULL, aop, ic, TRUE);
8666 /* we did not allocate which means left
8667 already in a pointer register, then
8668 if size > 0 && this could be used again
8669 we have to point it back to where it
8671 if (AOP_SIZE (result) > 1 &&
8672 !OP_SYMBOL (left)->remat &&
8673 (OP_SYMBOL (left)->liveTo > ic->seq ||
8677 int size = AOP_SIZE (result) - 1;
8679 emitcode ("dec", "%s", rname);
8684 freeAsmop (result, NULL, ic, TRUE);
8685 if (pi) pi->generated = 1;
8688 /*-----------------------------------------------------------------*/
8689 /* genPagedPointerGet - emitcode for paged pointer fetch */
8690 /*-----------------------------------------------------------------*/
8692 genPagedPointerGet (operand * left,
8700 sym_link *rtype, *retype, *letype;
8702 rtype = operandType (result);
8703 retype = getSpec (rtype);
8704 letype = getSpec (operandType (left));
8705 aopOp (left, ic, FALSE, FALSE);
8707 /* if the value is already in a pointer register
8708 then don't need anything more */
8709 if (!AOP_INPREG (AOP (left)))
8711 /* otherwise get a free pointer register */
8713 preg = getFreePtr (ic, &aop, FALSE);
8714 emitcode ("mov", "%s,%s",
8716 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8720 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8722 freeAsmop (left, NULL, ic, TRUE);
8723 aopOp (result, ic, FALSE, FALSE);
8725 /* if bitfield then unpack the bits */
8726 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8727 genUnpackBits (result, rname, PPOINTER);
8730 /* we have can just get the values */
8731 int size = AOP_SIZE (result);
8737 emitcode ("movx", "a,@%s", rname);
8738 aopPut (AOP (result), "a", offset);
8743 emitcode ("inc", "%s", rname);
8747 /* now some housekeeping stuff */
8750 /* we had to allocate for this iCode */
8751 if (pi) aopPut ( AOP (left), rname, 0);
8752 freeAsmop (NULL, aop, ic, TRUE);
8756 /* we did not allocate which means left
8757 already in a pointer register, then
8758 if size > 0 && this could be used again
8759 we have to point it back to where it
8761 if (AOP_SIZE (result) > 1 &&
8762 !OP_SYMBOL (left)->remat &&
8763 (OP_SYMBOL (left)->liveTo > ic->seq ||
8767 int size = AOP_SIZE (result) - 1;
8769 emitcode ("dec", "%s", rname);
8774 freeAsmop (result, NULL, ic, TRUE);
8775 if (pi) pi->generated = 1;
8778 /*-----------------------------------------------------------------*/
8779 /* genFarPointerGet - gget value from far space */
8780 /*-----------------------------------------------------------------*/
8782 genFarPointerGet (operand * left,
8783 operand * result, iCode * ic, iCode *pi)
8786 sym_link *retype = getSpec (operandType (result));
8787 sym_link *letype = getSpec (operandType (left));
8788 D (emitcode (";", "genFarPointerGet");
8791 aopOp (left, ic, FALSE, FALSE);
8793 /* if the operand is already in dptr
8794 then we do nothing else we move the value to dptr */
8795 if (AOP_TYPE (left) != AOP_STR)
8797 /* if this is remateriazable */
8798 if (AOP_TYPE (left) == AOP_IMMD)
8800 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8804 /* we need to get it byte by byte */
8805 _startLazyDPSEvaluation ();
8806 if (AOP_TYPE (left) != AOP_DPTR)
8808 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8809 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8810 if (options.model == MODEL_FLAT24)
8811 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8815 /* We need to generate a load to DPTR indirect through DPTR. */
8816 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8818 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8819 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8820 if (options.model == MODEL_FLAT24)
8821 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8822 emitcode ("pop", "dph");
8823 emitcode ("pop", "dpl");
8825 _endLazyDPSEvaluation ();
8828 /* so dptr know contains the address */
8829 freeAsmop (left, NULL, ic, TRUE);
8830 aopOp (result, ic, FALSE, TRUE);
8832 /* if bit then unpack */
8833 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8834 genUnpackBits (result, "dptr", FPOINTER);
8837 size = AOP_SIZE (result);
8840 _startLazyDPSEvaluation ();
8847 emitcode ("movx", "a,@dptr");
8848 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
8849 emitcode ("inc", "dptr");
8851 aopPut (AOP (result), "a", offset++);
8853 _endLazyDPSEvaluation ();
8855 if (pi && AOP_TYPE (left) != AOP_IMMD) {
8856 aopPut ( AOP (left), "dpl", 0);
8857 aopPut ( AOP (left), "dph", 1);
8858 if (options.model == MODEL_FLAT24)
8859 aopPut ( AOP (left), "dpx", 2);
8863 freeAsmop (result, NULL, ic, TRUE);
8866 /*-----------------------------------------------------------------*/
8867 /* emitcodePointerGet - gget value from code space */
8868 /*-----------------------------------------------------------------*/
8870 emitcodePointerGet (operand * left,
8871 operand * result, iCode * ic, iCode *pi)
8874 sym_link *retype = getSpec (operandType (result));
8876 aopOp (left, ic, FALSE, FALSE);
8878 /* if the operand is already in dptr
8879 then we do nothing else we move the value to dptr */
8880 if (AOP_TYPE (left) != AOP_STR)
8882 /* if this is remateriazable */
8883 if (AOP_TYPE (left) == AOP_IMMD)
8885 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8888 { /* we need to get it byte by byte */
8889 _startLazyDPSEvaluation ();
8890 if (AOP_TYPE (left) != AOP_DPTR)
8892 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8893 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8894 if (options.model == MODEL_FLAT24)
8895 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8899 /* We need to generate a load to DPTR indirect through DPTR. */
8900 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8902 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8903 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8904 if (options.model == MODEL_FLAT24)
8905 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8906 emitcode ("pop", "dph");
8907 emitcode ("pop", "dpl");
8909 _endLazyDPSEvaluation ();
8912 /* so dptr know contains the address */
8913 aopOp (result, ic, FALSE, TRUE);
8915 /* if bit then unpack */
8916 if (IS_BITVAR (retype))
8917 genUnpackBits (result, "dptr", CPOINTER);
8920 size = AOP_SIZE (result);
8923 _startLazyDPSEvaluation ();
8929 emitcode ("clr", "a");
8930 emitcode ("movc", "a,@a+dptr");
8931 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
8932 emitcode ("inc", "dptr");
8933 aopPut (AOP (result), "a", offset++);
8935 _endLazyDPSEvaluation ();
8937 if (pi && AOP_TYPE (left) != AOP_IMMD) {
8938 aopPut ( AOP (left), "dpl", 0);
8939 aopPut ( AOP (left), "dph", 1);
8940 if (options.model == MODEL_FLAT24)
8941 aopPut ( AOP (left), "dpx", 2);
8945 freeAsmop (left, NULL, ic, TRUE);
8946 freeAsmop (result, NULL, ic, TRUE);
8949 /*-----------------------------------------------------------------*/
8950 /* genGenPointerGet - gget value from generic pointer space */
8951 /*-----------------------------------------------------------------*/
8953 genGenPointerGet (operand * left,
8954 operand * result, iCode * ic, iCode * pi)
8957 sym_link *retype = getSpec (operandType (result));
8958 sym_link *letype = getSpec (operandType (left));
8960 D (emitcode (";", "genGenPointerGet "); );
8962 aopOp (left, ic, FALSE, (OP_SYMBOL(left)->ruonly ? FALSE : TRUE));
8964 /* if the operand is already in dptr
8965 then we do nothing else we move the value to dptr */
8966 if (AOP_TYPE (left) != AOP_STR)
8968 /* if this is remateriazable */
8969 if (AOP_TYPE (left) == AOP_IMMD)
8971 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8972 if (AOP(left)->aopu.aop_immd.from_cast_remat)
8973 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
8975 emitcode ("mov", "b,#%d", pointerCode (retype));
8978 { /* we need to get it byte by byte */
8979 _startLazyDPSEvaluation ();
8980 if (AOP(left)->type==AOP_DPTR2) {
8982 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8985 emitcode ("mov", "dpl,%s", l);
8986 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8989 emitcode ("mov", "dph,%s", l);
8990 if (options.model == MODEL_FLAT24) {
8991 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8994 emitcode ("mov", "dpx,%s", l);
8995 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8997 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9000 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
9001 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
9002 if (options.model == MODEL_FLAT24) {
9003 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9004 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9006 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9009 _endLazyDPSEvaluation ();
9012 /* so dptr know contains the address */
9013 aopOp (result, ic, FALSE, TRUE);
9015 /* if bit then unpack */
9016 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9017 genUnpackBits (result, "dptr", GPOINTER);
9020 size = AOP_SIZE (result);
9025 emitcode ("lcall", "__gptrget");
9026 aopPut (AOP (result), "a", offset++);
9027 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9028 emitcode ("inc", "dptr");
9032 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9033 aopPut ( AOP (left), "dpl", 0);
9034 aopPut ( AOP (left), "dph", 1);
9035 if (options.model == MODEL_FLAT24) {
9036 aopPut ( AOP (left), "dpx", 2);
9037 aopPut ( AOP (left), "b", 3);
9038 } else aopPut ( AOP (left), "b", 2);
9041 freeAsmop (left, NULL, ic, TRUE);
9042 freeAsmop (result, NULL, ic, TRUE);
9045 /*-----------------------------------------------------------------*/
9046 /* genPointerGet - generate code for pointer get */
9047 /*-----------------------------------------------------------------*/
9049 genPointerGet (iCode * ic, iCode *pi)
9051 operand *left, *result;
9052 sym_link *type, *etype;
9055 D (emitcode (";", "genPointerGet ");
9058 left = IC_LEFT (ic);
9059 result = IC_RESULT (ic);
9061 /* depending on the type of pointer we need to
9062 move it to the correct pointer register */
9063 type = operandType (left);
9064 etype = getSpec (type);
9065 /* if left is of type of pointer then it is simple */
9066 if (IS_PTR (type) && !IS_FUNC (type->next))
9067 p_type = DCL_TYPE (type);
9070 /* we have to go by the storage class */
9071 p_type = PTR_TYPE (SPEC_OCLS (etype));
9073 /* special case when cast remat */
9074 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9075 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9076 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9077 type = type = operandType (left);
9078 p_type = DCL_TYPE (type);
9080 /* now that we have the pointer type we assign
9081 the pointer values */
9087 genNearPointerGet (left, result, ic, pi);
9091 genPagedPointerGet (left, result, ic, pi);
9095 genFarPointerGet (left, result, ic, pi);
9099 emitcodePointerGet (left, result, ic, pi);
9103 genGenPointerGet (left, result, ic, pi);
9109 /*-----------------------------------------------------------------*/
9110 /* genPackBits - generates code for packed bit storage */
9111 /*-----------------------------------------------------------------*/
9113 genPackBits (sym_link * etype,
9115 char *rname, int p_type)
9123 blen = SPEC_BLEN (etype);
9124 bstr = SPEC_BSTR (etype);
9126 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9129 /* if the bit lenth is less than or */
9130 /* it exactly fits a byte then */
9131 if (SPEC_BLEN (etype) <= 8)
9133 shCount = SPEC_BSTR (etype);
9135 /* shift left acc */
9138 if (SPEC_BLEN (etype) < 8)
9139 { /* if smaller than a byte */
9145 emitcode ("mov", "b,a");
9146 emitcode ("mov", "a,@%s", rname);
9150 emitcode ("mov", "b,a");
9151 emitcode ("movx", "a,@dptr");
9155 emitcode ("push", "b");
9156 emitcode ("push", "acc");
9157 emitcode ("lcall", "__gptrget");
9158 emitcode ("pop", "b");
9162 emitcode ("anl", "a,#0x%02x", (unsigned char)
9163 ((unsigned char) (0xFF << (blen + bstr)) |
9164 (unsigned char) (0xFF >> (8 - bstr))));
9165 emitcode ("orl", "a,b");
9166 if (p_type == GPOINTER)
9167 emitcode ("pop", "b");
9174 emitcode ("mov", "@%s,a", rname);
9178 emitcode ("movx", "@dptr,a");
9182 emitcode ("lcall", "__gptrput");
9187 if (SPEC_BLEN (etype) <= 8)
9190 emitcode ("inc", "%s", rname);
9191 rLen = SPEC_BLEN (etype);
9193 /* now generate for lengths greater than one byte */
9197 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9209 emitcode ("mov", "@%s,a", rname);
9212 emitcode ("mov", "@%s,%s", rname, l);
9217 emitcode ("movx", "@dptr,a");
9222 emitcode ("lcall", "__gptrput");
9225 emitcode ("inc", "%s", rname);
9230 /* last last was not complete */
9233 /* save the byte & read byte */
9237 emitcode ("mov", "b,a");
9238 emitcode ("mov", "a,@%s", rname);
9242 emitcode ("mov", "b,a");
9243 emitcode ("movx", "a,@dptr");
9247 emitcode ("push", "b");
9248 emitcode ("push", "acc");
9249 emitcode ("lcall", "__gptrget");
9250 emitcode ("pop", "b");
9254 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
9255 emitcode ("orl", "a,b");
9258 if (p_type == GPOINTER)
9259 emitcode ("pop", "b");
9265 emitcode ("mov", "@%s,a", rname);
9269 emitcode ("movx", "@dptr,a");
9273 emitcode ("lcall", "__gptrput");
9277 /*-----------------------------------------------------------------*/
9278 /* genDataPointerSet - remat pointer to data space */
9279 /*-----------------------------------------------------------------*/
9281 genDataPointerSet (operand * right,
9285 int size, offset = 0;
9286 char *l, buffer[256];
9288 aopOp (right, ic, FALSE, FALSE);
9290 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9291 size = AOP_SIZE (right);
9295 sprintf (buffer, "(%s + %d)", l + 1, offset);
9297 sprintf (buffer, "%s", l + 1);
9298 emitcode ("mov", "%s,%s", buffer,
9299 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9302 freeAsmop (right, NULL, ic, TRUE);
9303 freeAsmop (result, NULL, ic, TRUE);
9306 /*-----------------------------------------------------------------*/
9307 /* genNearPointerSet - emitcode for near pointer put */
9308 /*-----------------------------------------------------------------*/
9310 genNearPointerSet (operand * right,
9318 sym_link *retype, *letype;
9319 sym_link *ptype = operandType (result);
9321 retype = getSpec (operandType (right));
9322 letype = getSpec (ptype);
9324 aopOp (result, ic, FALSE, FALSE);
9326 /* if the result is rematerializable &
9327 in data space & not a bit variable */
9328 if (AOP_TYPE (result) == AOP_IMMD &&
9329 DCL_TYPE (ptype) == POINTER &&
9330 !IS_BITVAR (retype) &&
9331 !IS_BITVAR (letype))
9333 genDataPointerSet (right, result, ic);
9337 /* if the value is already in a pointer register
9338 then don't need anything more */
9339 if (!AOP_INPREG (AOP (result)))
9341 /* otherwise get a free pointer register */
9343 preg = getFreePtr (ic, &aop, FALSE);
9344 emitcode ("mov", "%s,%s",
9346 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9350 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9352 aopOp (right, ic, FALSE, FALSE);
9354 /* if bitfield then unpack the bits */
9355 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9356 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9359 /* we have can just get the values */
9360 int size = AOP_SIZE (right);
9365 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9369 emitcode ("mov", "@%s,a", rname);
9372 emitcode ("mov", "@%s,%s", rname, l);
9374 emitcode ("inc", "%s", rname);
9379 /* now some housekeeping stuff */
9382 /* we had to allocate for this iCode */
9383 if (pi) aopPut (AOP (result),rname,0);
9384 freeAsmop (NULL, aop, ic, TRUE);
9388 /* we did not allocate which means left
9389 already in a pointer register, then
9390 if size > 0 && this could be used again
9391 we have to point it back to where it
9393 if (AOP_SIZE (right) > 1 &&
9394 !OP_SYMBOL (result)->remat &&
9395 (OP_SYMBOL (result)->liveTo > ic->seq ||
9399 int size = AOP_SIZE (right) - 1;
9401 emitcode ("dec", "%s", rname);
9406 if (pi) pi->generated = 1;
9407 freeAsmop (result, NULL, ic, TRUE);
9408 freeAsmop (right, NULL, ic, TRUE);
9413 /*-----------------------------------------------------------------*/
9414 /* genPagedPointerSet - emitcode for Paged pointer put */
9415 /*-----------------------------------------------------------------*/
9417 genPagedPointerSet (operand * right,
9425 sym_link *retype, *letype;
9427 retype = getSpec (operandType (right));
9428 letype = getSpec (operandType (result));
9430 aopOp (result, ic, FALSE, FALSE);
9432 /* if the value is already in a pointer register
9433 then don't need anything more */
9434 if (!AOP_INPREG (AOP (result)))
9436 /* otherwise get a free pointer register */
9438 preg = getFreePtr (ic, &aop, FALSE);
9439 emitcode ("mov", "%s,%s",
9441 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9445 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9447 aopOp (right, ic, FALSE, FALSE);
9449 /* if bitfield then unpack the bits */
9450 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9451 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9454 /* we have can just get the values */
9455 int size = AOP_SIZE (right);
9460 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9463 emitcode ("movx", "@%s,a", rname);
9466 emitcode ("inc", "%s", rname);
9472 /* now some housekeeping stuff */
9475 if (pi) aopPut (AOP (result),rname,0);
9476 /* we had to allocate for this iCode */
9477 freeAsmop (NULL, aop, ic, TRUE);
9481 /* we did not allocate which means left
9482 already in a pointer register, then
9483 if size > 0 && this could be used again
9484 we have to point it back to where it
9486 if (AOP_SIZE (right) > 1 &&
9487 !OP_SYMBOL (result)->remat &&
9488 (OP_SYMBOL (result)->liveTo > ic->seq ||
9492 int size = AOP_SIZE (right) - 1;
9494 emitcode ("dec", "%s", rname);
9499 if (pi) pi->generated = 1;
9500 freeAsmop (result, NULL, ic, TRUE);
9501 freeAsmop (right, NULL, ic, TRUE);
9506 /*-----------------------------------------------------------------*/
9507 /* genFarPointerSet - set value from far space */
9508 /*-----------------------------------------------------------------*/
9510 genFarPointerSet (operand * right,
9511 operand * result, iCode * ic, iCode *pi)
9514 sym_link *retype = getSpec (operandType (right));
9515 sym_link *letype = getSpec (operandType (result));
9517 aopOp (result, ic, FALSE, FALSE);
9519 /* if the operand is already in dptr
9520 then we do nothing else we move the value to dptr */
9521 if (AOP_TYPE (result) != AOP_STR)
9523 /* if this is remateriazable */
9524 if (AOP_TYPE (result) == AOP_IMMD)
9525 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9528 /* we need to get it byte by byte */
9529 _startLazyDPSEvaluation ();
9530 if (AOP_TYPE (result) != AOP_DPTR)
9532 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9533 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9534 if (options.model == MODEL_FLAT24)
9535 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9539 /* We need to generate a load to DPTR indirect through DPTR. */
9540 D (emitcode (";", "genFarPointerSet -- indirection special case.");
9542 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9543 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9544 if (options.model == MODEL_FLAT24)
9545 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9546 emitcode ("pop", "dph");
9547 emitcode ("pop", "dpl");
9549 _endLazyDPSEvaluation ();
9552 /* so dptr know contains the address */
9553 aopOp (right, ic, FALSE, TRUE);
9555 /* if bit then unpack */
9556 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9557 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9560 size = AOP_SIZE (right);
9563 _startLazyDPSEvaluation ();
9566 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9572 emitcode ("movx", "@dptr,a");
9573 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
9574 emitcode ("inc", "dptr");
9576 _endLazyDPSEvaluation ();
9579 if (pi && AOP_TYPE (result) != AOP_IMMD) {
9580 aopPut (AOP(result),"dpl",0);
9581 aopPut (AOP(result),"dph",1);
9582 if (options.model == MODEL_FLAT24)
9583 aopPut (AOP(result),"dpx",2);
9586 freeAsmop (result, NULL, ic, TRUE);
9587 freeAsmop (right, NULL, ic, TRUE);
9590 /*-----------------------------------------------------------------*/
9591 /* genGenPointerSet - set value from generic pointer space */
9592 /*-----------------------------------------------------------------*/
9594 genGenPointerSet (operand * right,
9595 operand * result, iCode * ic, iCode *pi)
9598 sym_link *retype = getSpec (operandType (right));
9599 sym_link *letype = getSpec (operandType (result));
9601 aopOp (result, ic, FALSE, OP_SYMBOL(result)->ruonly ? FALSE : TRUE);
9603 /* if the operand is already in dptr
9604 then we do nothing else we move the value to dptr */
9605 if (AOP_TYPE (result) != AOP_STR)
9607 _startLazyDPSEvaluation ();
9608 /* if this is remateriazable */
9609 if (AOP_TYPE (result) == AOP_IMMD)
9611 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9612 if (AOP(result)->aopu.aop_immd.from_cast_remat)
9613 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
9615 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9618 { /* we need to get it byte by byte */
9619 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9620 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9621 if (options.model == MODEL_FLAT24) {
9622 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9623 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9625 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9628 _endLazyDPSEvaluation ();
9630 /* so dptr know contains the address */
9631 aopOp (right, ic, FALSE, TRUE);
9633 /* if bit then unpack */
9634 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9635 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9638 size = AOP_SIZE (right);
9641 _startLazyDPSEvaluation ();
9644 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9650 emitcode ("lcall", "__gptrput");
9651 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
9652 emitcode ("inc", "dptr");
9654 _endLazyDPSEvaluation ();
9657 if (pi && AOP_TYPE (result) != AOP_IMMD) {
9658 aopPut (AOP(result),"dpl",0);
9659 aopPut (AOP(result),"dph",1);
9660 if (options.model == MODEL_FLAT24) {
9661 aopPut (AOP(result),"dpx",2);
9662 aopPut (AOP(result),"b",3);
9664 aopPut (AOP(result),"b",2);
9668 freeAsmop (result, NULL, ic, TRUE);
9669 freeAsmop (right, NULL, ic, TRUE);
9672 /*-----------------------------------------------------------------*/
9673 /* genPointerSet - stores the value into a pointer location */
9674 /*-----------------------------------------------------------------*/
9676 genPointerSet (iCode * ic, iCode *pi)
9678 operand *right, *result;
9679 sym_link *type, *etype;
9682 D (emitcode (";", "genPointerSet ");
9685 right = IC_RIGHT (ic);
9686 result = IC_RESULT (ic);
9688 /* depending on the type of pointer we need to
9689 move it to the correct pointer register */
9690 type = operandType (result);
9691 etype = getSpec (type);
9692 /* if left is of type of pointer then it is simple */
9693 if (IS_PTR (type) && !IS_FUNC (type->next))
9695 p_type = DCL_TYPE (type);
9699 /* we have to go by the storage class */
9700 p_type = PTR_TYPE (SPEC_OCLS (etype));
9702 /* special case when cast remat */
9703 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9704 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9705 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9706 type = type = operandType (result);
9707 p_type = DCL_TYPE (type);
9710 /* now that we have the pointer type we assign
9711 the pointer values */
9717 genNearPointerSet (right, result, ic, pi);
9721 genPagedPointerSet (right, result, ic, pi);
9725 genFarPointerSet (right, result, ic, pi);
9729 genGenPointerSet (right, result, ic, pi);
9735 /*-----------------------------------------------------------------*/
9736 /* genIfx - generate code for Ifx statement */
9737 /*-----------------------------------------------------------------*/
9739 genIfx (iCode * ic, iCode * popIc)
9741 operand *cond = IC_COND (ic);
9744 D (emitcode (";", "genIfx "););
9746 aopOp (cond, ic, FALSE, FALSE);
9748 /* get the value into acc */
9749 if (AOP_TYPE (cond) != AOP_CRY)
9753 /* the result is now in the accumulator */
9754 freeAsmop (cond, NULL, ic, TRUE);
9756 /* if there was something to be popped then do it */
9760 /* if the condition is a bit variable */
9761 if (isbit && IS_ITEMP (cond) &&
9763 genIfxJump (ic, SPIL_LOC (cond)->rname);
9764 else if (isbit && !IS_ITEMP (cond))
9765 genIfxJump (ic, OP_SYMBOL (cond)->rname);
9767 genIfxJump (ic, "a");
9772 /*-----------------------------------------------------------------*/
9773 /* genAddrOf - generates code for address of */
9774 /*-----------------------------------------------------------------*/
9776 genAddrOf (iCode * ic)
9778 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9781 D (emitcode (";", "genAddrOf ");
9784 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9786 /* if the operand is on the stack then we
9787 need to get the stack offset of this
9791 /* if it has an offset then we need to compute
9795 emitcode ("mov", "a,_bp");
9796 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9797 aopPut (AOP (IC_RESULT (ic)), "a", 0);
9801 /* we can just move _bp */
9802 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9804 /* fill the result with zero */
9805 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9808 if (options.stack10bit && size < (FPTRSIZE - 1))
9811 "*** warning: pointer to stack var truncated.\n");
9818 if (options.stack10bit && offset == 2)
9820 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
9824 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9831 /* object not on stack then we need the name */
9832 size = AOP_SIZE (IC_RESULT (ic));
9837 char s[SDCC_NAME_MAX];
9839 sprintf (s, "#(%s >> %d)",
9843 sprintf (s, "#%s", sym->rname);
9844 aopPut (AOP (IC_RESULT (ic)), s, offset++);
9848 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9852 /*-----------------------------------------------------------------*/
9853 /* genArrayInit - generates code for address of */
9854 /*-----------------------------------------------------------------*/
9856 genArrayInit (iCode * ic)
9860 int elementSize = 0, eIndex;
9861 unsigned val, lastVal;
9863 operand *left=IC_LEFT(ic);
9865 D (emitcode (";", "genArrayInit "););
9867 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
9869 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
9871 // Load immediate value into DPTR.
9872 emitcode("mov", "dptr, %s",
9873 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
9875 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
9878 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9879 "Unexpected operand to genArrayInit.\n");
9882 // a regression because of SDCCcse.c:1.52
9883 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9884 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9885 if (options.model == MODEL_FLAT24)
9886 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9890 type = operandType(IC_LEFT(ic));
9892 if (type && type->next)
9894 elementSize = getSize(type->next);
9898 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9899 "can't determine element size in genArrayInit.\n");
9903 iLoop = IC_ARRAYILIST(ic);
9908 bool firstpass = TRUE;
9910 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
9911 iLoop->count, (int)iLoop->literalValue, elementSize);
9917 symbol *tlbl = NULL;
9919 count = ix > 256 ? 256 : ix;
9923 tlbl = newiTempLabel (NULL);
9924 if (firstpass || (count & 0xff))
9926 emitcode("mov", "b, #0x%x", count & 0xff);
9929 emitcode ("", "%05d$:", tlbl->key + 100);
9934 for (eIndex = 0; eIndex < elementSize; eIndex++)
9936 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
9939 emitcode("mov", "a, #0x%x", val);
9943 emitcode("movx", "@dptr, a");
9944 emitcode("inc", "dptr");
9949 emitcode("djnz", "b, %05d$", tlbl->key + 100);
9955 iLoop = iLoop->next;
9958 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
9961 /*-----------------------------------------------------------------*/
9962 /* genFarFarAssign - assignment when both are in far space */
9963 /*-----------------------------------------------------------------*/
9965 genFarFarAssign (operand * result, operand * right, iCode * ic)
9967 int size = AOP_SIZE (right);
9969 symbol *rSym = NULL;
9973 /* quick & easy case. */
9974 D(emitcode(";","genFarFarAssign (1 byte case)"););
9975 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9976 freeAsmop (right, NULL, ic, FALSE);
9977 /* now assign DPTR to result */
9979 aopOp(result, ic, FALSE, FALSE);
9981 aopPut(AOP(result), "a", 0);
9982 freeAsmop(result, NULL, ic, FALSE);
9986 /* See if we've got an underlying symbol to abuse. */
9987 if (IS_SYMOP(result) && OP_SYMBOL(result))
9989 if (IS_TRUE_SYMOP(result))
9991 rSym = OP_SYMBOL(result);
9993 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9995 rSym = OP_SYMBOL(result)->usl.spillLoc;
9999 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10001 /* We can use the '390 auto-toggle feature to good effect here. */
10003 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10004 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
10005 emitcode ("mov", "dptr,#%s", rSym->rname);
10006 /* DP2 = result, DP1 = right, DP1 is current. */
10009 emitcode("movx", "a,@dptr");
10010 emitcode("movx", "@dptr,a");
10013 emitcode("inc", "dptr");
10014 emitcode("inc", "dptr");
10017 emitcode("mov", "dps, #0");
10018 freeAsmop (right, NULL, ic, FALSE);
10020 some alternative code for processors without auto-toggle
10021 no time to test now, so later well put in...kpb
10022 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10023 emitcode("mov", "dps, #0x01"); /* Select DPTR2. */
10024 emitcode ("mov", "dptr,#%s", rSym->rname);
10025 /* DP2 = result, DP1 = right, DP1 is current. */
10029 emitcode("movx", "a,@dptr");
10031 emitcode("inc", "dptr");
10032 emitcode("inc", "dps");
10033 emitcode("movx", "@dptr,a");
10035 emitcode("inc", "dptr");
10036 emitcode("inc", "dps");
10038 emitcode("mov", "dps, #0");
10039 freeAsmop (right, NULL, ic, FALSE);
10044 D (emitcode (";", "genFarFarAssign"););
10045 aopOp (result, ic, TRUE, TRUE);
10047 _startLazyDPSEvaluation ();
10051 aopPut (AOP (result),
10052 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10055 _endLazyDPSEvaluation ();
10056 freeAsmop (result, NULL, ic, FALSE);
10057 freeAsmop (right, NULL, ic, FALSE);
10061 /*-----------------------------------------------------------------*/
10062 /* genAssign - generate code for assignment */
10063 /*-----------------------------------------------------------------*/
10065 genAssign (iCode * ic)
10067 operand *result, *right;
10069 unsigned long lit = 0L;
10071 D (emitcode (";", "genAssign ");
10074 result = IC_RESULT (ic);
10075 right = IC_RIGHT (ic);
10077 /* if they are the same */
10078 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10081 aopOp (right, ic, FALSE, FALSE);
10083 emitcode (";", "genAssign: resultIsFar = %s",
10084 isOperandInFarSpace (result) ?
10087 /* special case both in far space */
10088 if ((AOP_TYPE (right) == AOP_DPTR ||
10089 AOP_TYPE (right) == AOP_DPTR2) &&
10090 /* IS_TRUE_SYMOP(result) && */
10091 isOperandInFarSpace (result))
10093 genFarFarAssign (result, right, ic);
10097 aopOp (result, ic, TRUE, FALSE);
10099 /* if they are the same registers */
10100 if (sameRegs (AOP (right), AOP (result)))
10103 /* if the result is a bit */
10104 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10106 /* if the right size is a literal then
10107 we know what the value is */
10108 if (AOP_TYPE (right) == AOP_LIT)
10110 if (((int) operandLitValue (right)))
10111 aopPut (AOP (result), one, 0);
10113 aopPut (AOP (result), zero, 0);
10117 /* the right is also a bit variable */
10118 if (AOP_TYPE (right) == AOP_CRY)
10120 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10121 aopPut (AOP (result), "c", 0);
10125 /* we need to or */
10127 aopPut (AOP (result), "a", 0);
10131 /* bit variables done */
10133 size = AOP_SIZE (result);
10135 if (AOP_TYPE (right) == AOP_LIT)
10136 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10139 (AOP_TYPE (result) != AOP_REG) &&
10140 (AOP_TYPE (right) == AOP_LIT) &&
10141 !IS_FLOAT (operandType (right)))
10143 _startLazyDPSEvaluation ();
10144 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10146 aopPut (AOP (result),
10147 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10152 /* And now fill the rest with zeros. */
10155 emitcode ("clr", "a");
10159 aopPut (AOP (result), "a", offset++);
10161 _endLazyDPSEvaluation ();
10165 _startLazyDPSEvaluation ();
10168 aopPut (AOP (result),
10169 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10173 _endLazyDPSEvaluation ();
10177 freeAsmop (right, NULL, ic, FALSE);
10178 freeAsmop (result, NULL, ic, TRUE);
10181 /*-----------------------------------------------------------------*/
10182 /* genJumpTab - generates code for jump table */
10183 /*-----------------------------------------------------------------*/
10185 genJumpTab (iCode * ic)
10190 D (emitcode (";", "genJumpTab ");
10193 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10194 /* get the condition into accumulator */
10195 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10197 /* multiply by four! */
10198 emitcode ("add", "a,acc");
10199 emitcode ("add", "a,acc");
10200 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10202 jtab = newiTempLabel (NULL);
10203 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10204 emitcode ("jmp", "@a+dptr");
10205 emitcode ("", "%05d$:", jtab->key + 100);
10206 /* now generate the jump labels */
10207 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10208 jtab = setNextItem (IC_JTLABELS (ic)))
10209 emitcode ("ljmp", "%05d$", jtab->key + 100);
10213 /*-----------------------------------------------------------------*/
10214 /* genCast - gen code for casting */
10215 /*-----------------------------------------------------------------*/
10217 genCast (iCode * ic)
10219 operand *result = IC_RESULT (ic);
10220 sym_link *ctype = operandType (IC_LEFT (ic));
10221 sym_link *rtype = operandType (IC_RIGHT (ic));
10222 operand *right = IC_RIGHT (ic);
10225 D (emitcode (";", "genCast ");
10228 /* if they are equivalent then do nothing */
10229 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10232 aopOp (right, ic, FALSE, FALSE);
10233 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10235 /* if the result is a bit */
10236 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10237 if (IS_BITVAR(OP_SYMBOL(result)->type))
10239 /* if the right size is a literal then
10240 we know what the value is */
10241 if (AOP_TYPE (right) == AOP_LIT)
10243 if (((int) operandLitValue (right)))
10244 aopPut (AOP (result), one, 0);
10246 aopPut (AOP (result), zero, 0);
10251 /* the right is also a bit variable */
10252 if (AOP_TYPE (right) == AOP_CRY)
10254 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10255 aopPut (AOP (result), "c", 0);
10259 /* we need to or */
10261 aopPut (AOP (result), "a", 0);
10265 /* if they are the same size : or less */
10266 if (AOP_SIZE (result) <= AOP_SIZE (right))
10269 /* if they are in the same place */
10270 if (sameRegs (AOP (right), AOP (result)))
10273 /* if they in different places then copy */
10274 size = AOP_SIZE (result);
10276 _startLazyDPSEvaluation ();
10279 aopPut (AOP (result),
10280 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10284 _endLazyDPSEvaluation ();
10289 /* if the result is of type pointer */
10290 if (IS_PTR (ctype))
10294 sym_link *type = operandType (right);
10296 /* pointer to generic pointer */
10297 if (IS_GENPTR (ctype))
10303 p_type = DCL_TYPE (type);
10307 #if OLD_CAST_BEHAVIOR
10308 /* KV: we are converting a non-pointer type to
10309 * a generic pointer. This (ifdef'd out) code
10310 * says that the resulting generic pointer
10311 * should have the same class as the storage
10312 * location of the non-pointer variable.
10314 * For example, converting an int (which happens
10315 * to be stored in DATA space) to a pointer results
10316 * in a DATA generic pointer; if the original int
10317 * in XDATA space, so will be the resulting pointer.
10319 * I don't like that behavior, and thus this change:
10320 * all such conversions will be forced to XDATA and
10321 * throw a warning. If you want some non-XDATA
10322 * type, or you want to suppress the warning, you
10323 * must go through an intermediate cast, like so:
10325 * char _generic *gp = (char _xdata *)(intVar);
10327 sym_link *etype = getSpec (type);
10329 /* we have to go by the storage class */
10330 if (SPEC_OCLS (etype) != generic)
10332 p_type = PTR_TYPE (SPEC_OCLS (etype));
10337 /* Converting unknown class (i.e. register variable)
10338 * to generic pointer. This is not good, but
10339 * we'll make a guess (and throw a warning).
10342 werror (W_INT_TO_GEN_PTR_CAST);
10346 /* the first two bytes are known */
10347 size = GPTRSIZE - 1;
10349 _startLazyDPSEvaluation ();
10352 aopPut (AOP (result),
10353 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10357 _endLazyDPSEvaluation ();
10359 /* the last byte depending on type */
10377 /* this should never happen */
10378 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10379 "got unknown pointer type");
10382 aopPut (AOP (result), l, GPTRSIZE - 1);
10386 /* just copy the pointers */
10387 size = AOP_SIZE (result);
10389 _startLazyDPSEvaluation ();
10392 aopPut (AOP (result),
10393 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10397 _endLazyDPSEvaluation ();
10401 /* so we now know that the size of destination is greater
10402 than the size of the source */
10403 /* we move to result for the size of source */
10404 size = AOP_SIZE (right);
10406 _startLazyDPSEvaluation ();
10409 aopPut (AOP (result),
10410 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10414 _endLazyDPSEvaluation ();
10416 /* now depending on the sign of the source && destination */
10417 size = AOP_SIZE (result) - AOP_SIZE (right);
10418 /* if unsigned or not an integral type */
10419 /* also, if the source is a bit, we don't need to sign extend, because
10420 * it can't possibly have set the sign bit.
10422 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10426 aopPut (AOP (result), zero, offset++);
10431 /* we need to extend the sign :{ */
10432 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10433 FALSE, FALSE, TRUE);
10435 emitcode ("rlc", "a");
10436 emitcode ("subb", "a,acc");
10438 aopPut (AOP (result), "a", offset++);
10441 /* we are done hurray !!!! */
10444 freeAsmop (right, NULL, ic, TRUE);
10445 freeAsmop (result, NULL, ic, TRUE);
10449 /*-----------------------------------------------------------------*/
10450 /* genDjnz - generate decrement & jump if not zero instrucion */
10451 /*-----------------------------------------------------------------*/
10453 genDjnz (iCode * ic, iCode * ifx)
10455 symbol *lbl, *lbl1;
10459 /* if the if condition has a false label
10460 then we cannot save */
10461 if (IC_FALSE (ifx))
10464 /* if the minus is not of the form
10466 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10467 !IS_OP_LITERAL (IC_RIGHT (ic)))
10470 if (operandLitValue (IC_RIGHT (ic)) != 1)
10473 /* if the size of this greater than one then no
10475 if (getSize (operandType (IC_RESULT (ic))) > 1)
10478 /* otherwise we can save BIG */
10479 D(emitcode(";", "genDjnz"););
10481 lbl = newiTempLabel (NULL);
10482 lbl1 = newiTempLabel (NULL);
10484 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10486 if (AOP_NEEDSACC(IC_RESULT(ic)))
10488 /* If the result is accessed indirectly via
10489 * the accumulator, we must explicitly write
10490 * it back after the decrement.
10492 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10494 if (strcmp(rByte, "a"))
10496 /* Something is hopelessly wrong */
10497 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10498 __FILE__, __LINE__);
10499 /* We can just give up; the generated code will be inefficient,
10500 * but what the hey.
10502 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10505 emitcode ("dec", "%s", rByte);
10506 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10507 emitcode ("jnz", "%05d$", lbl->key + 100);
10509 else if (IS_AOP_PREG (IC_RESULT (ic)))
10511 emitcode ("dec", "%s",
10512 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10513 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10514 emitcode ("jnz", "%05d$", lbl->key + 100);
10518 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10521 emitcode ("sjmp", "%05d$", lbl1->key + 100);
10522 emitcode ("", "%05d$:", lbl->key + 100);
10523 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10524 emitcode ("", "%05d$:", lbl1->key + 100);
10526 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10527 ifx->generated = 1;
10531 /*-----------------------------------------------------------------*/
10532 /* genReceive - generate code for a receive iCode */
10533 /*-----------------------------------------------------------------*/
10535 genReceive (iCode * ic)
10538 D (emitcode (";", "genReceive ");
10541 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10542 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10543 IS_TRUE_SYMOP (IC_RESULT (ic))))
10545 int size = getSize (operandType (IC_RESULT (ic)));
10546 int offset = fReturnSizeDS390 - size;
10549 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10550 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10553 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10554 size = AOP_SIZE (IC_RESULT (ic));
10558 emitcode ("pop", "acc");
10559 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10566 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10568 assignResultValue (IC_RESULT (ic));
10571 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10574 /*-----------------------------------------------------------------*/
10575 /* gen390Code - generate code for Dallas 390 based controllers */
10576 /*-----------------------------------------------------------------*/
10578 gen390Code (iCode * lic)
10583 lineHead = lineCurr = NULL;
10585 if (options.model == MODEL_FLAT24) {
10586 fReturnSizeDS390 = 5;
10587 fReturn = fReturn24;
10589 fReturnSizeDS390 = 4;
10590 fReturn = fReturn16;
10591 options.stack10bit=0;
10595 /* print the allocation information */
10597 printAllocInfo (currFunc, codeOutFile);
10599 /* if debug information required */
10600 if (options.debug && currFunc)
10602 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
10604 if (IS_STATIC (currFunc->etype))
10605 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
10607 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
10610 /* stack pointer name */
10611 if (options.useXstack)
10617 for (ic = lic; ic; ic = ic->next)
10620 if (cln != ic->lineno)
10625 emitcode ("", "C$%s$%d$%d$%d ==.",
10626 FileBaseName (ic->filename), ic->lineno,
10627 ic->level, ic->block);
10630 emitcode (";", "%s %d", ic->filename, ic->lineno);
10633 /* if the result is marked as
10634 spilt and rematerializable or code for
10635 this has already been generated then
10637 if (resultRemat (ic) || ic->generated)
10640 /* depending on the operation */
10660 /* IPOP happens only when trying to restore a
10661 spilt live range, if there is an ifx statement
10662 following this pop then the if statement might
10663 be using some of the registers being popped which
10664 would destory the contents of the register so
10665 we need to check for this condition and handle it */
10667 ic->next->op == IFX &&
10668 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10669 genIfx (ic->next, ic);
10687 genEndFunction (ic);
10707 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10724 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10728 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10735 /* note these two are xlated by algebraic equivalence
10736 during parsing SDCC.y */
10737 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10738 "got '>=' or '<=' shouldn't have come here");
10742 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10754 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10758 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10762 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10786 genRightShift (ic);
10789 case GET_VALUE_AT_ADDRESS:
10790 genPointerGet (ic,hasInc(IC_LEFT(ic),ic));
10794 if (POINTER_SET (ic))
10795 genPointerSet (ic,hasInc(IC_RESULT(ic),ic));
10821 addSet (&_G.sendSet, ic);
10834 /* now we are ready to call the
10835 peep hole optimizer */
10836 if (!options.nopeep)
10837 peepHole (&lineHead);
10839 /* now do the actual printing */
10840 printLine (lineHead, codeOutFile);