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,_bpx");
464 emitcode ("clr","c");
465 emitcode ("subb", "a,#0x%02x",
467 ((short) (sym->stack - _G.nRegsSaved)) :
468 ((short) sym->stack)) & 0xff);
469 emitcode ("mov","b,a");
470 emitcode ("mov","a,#0x%02x",(-((sym->stack < 0) ?
471 ((short) (sym->stack - _G.nRegsSaved)) :
472 ((short) sym->stack)) >> 8) & 0xff);
473 emitcode ("subb","a,_bpx+1");
475 if (options.model == MODEL_FLAT24)
476 emitcode ("mov", "dpx1,#0x40");
478 emitcode ("mov", "dph1,a");
479 emitcode ("mov", "dpl1,b");
481 if (options.model == MODEL_FLAT24)
482 emitcode ("mov", "dpx,#0x40");
483 emitcode ("mov", "dph,a");
484 emitcode ("mov", "dpl,b");
488 emitcode ("pop", "acc");
490 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
491 aop->size = getSize (sym->type);
495 /* if in bit space */
496 if (IN_BITSPACE (space))
498 sym->aop = aop = newAsmop (AOP_CRY);
499 aop->aopu.aop_dir = sym->rname;
500 aop->size = getSize (sym->type);
503 /* if it is in direct space */
504 if (IN_DIRSPACE (space))
506 sym->aop = aop = newAsmop (AOP_DIR);
507 aop->aopu.aop_dir = sym->rname;
508 aop->size = getSize (sym->type);
512 /* special case for a function */
513 if (IS_FUNC (sym->type))
515 sym->aop = aop = newAsmop (AOP_IMMD);
516 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
517 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
518 aop->size = FPTRSIZE;
522 /* only remaining is far space */
523 /* in which case DPTR gets the address */
524 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
529 emitcode ("mov", "dptr,#%s", sym->rname);
534 emitcode ("mov", "dptr,#%s", sym->rname);
536 aop->size = getSize (sym->type);
538 /* if it is in code space */
539 if (IN_CODESPACE (space))
545 /*-----------------------------------------------------------------*/
546 /* aopForRemat - rematerialzes an object */
547 /*-----------------------------------------------------------------*/
549 aopForRemat (symbol * sym)
551 iCode *ic = sym->rematiCode;
552 asmop *aop = newAsmop (AOP_IMMD);
559 val += (int) operandLitValue (IC_RIGHT (ic));
560 else if (ic->op == '-')
561 val -= (int) operandLitValue (IC_RIGHT (ic));
562 else if (IS_CAST_ICODE(ic)) {
563 sym_link *from_type = operandType(IC_RIGHT(ic));
564 aop->aopu.aop_immd.from_cast_remat = 1;
565 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
566 ptr_type = DCL_TYPE(from_type);
567 if (ptr_type == IPOINTER) {
574 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
578 sprintf (buffer, "(%s %c 0x%04x)",
579 OP_SYMBOL (IC_LEFT (ic))->rname,
580 val >= 0 ? '+' : '-',
583 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
585 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
586 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
587 /* set immd2 field if required */
588 if (aop->aopu.aop_immd.from_cast_remat) {
589 sprintf(buffer,"#0x%02x",ptr_type);
590 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
591 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
597 /*-----------------------------------------------------------------*/
598 /* regsInCommon - two operands have some registers in common */
599 /*-----------------------------------------------------------------*/
601 regsInCommon (operand * op1, operand * op2)
606 /* if they have registers in common */
607 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
610 sym1 = OP_SYMBOL (op1);
611 sym2 = OP_SYMBOL (op2);
613 if (sym1->nRegs == 0 || sym2->nRegs == 0)
616 for (i = 0; i < sym1->nRegs; i++)
622 for (j = 0; j < sym2->nRegs; j++)
627 if (sym2->regs[j] == sym1->regs[i])
635 /*-----------------------------------------------------------------*/
636 /* operandsEqu - equivalent */
637 /*-----------------------------------------------------------------*/
639 operandsEqu (operand * op1, operand * op2)
643 /* if they not symbols */
644 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
647 sym1 = OP_SYMBOL (op1);
648 sym2 = OP_SYMBOL (op2);
650 /* if both are itemps & one is spilt
651 and the other is not then false */
652 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
653 sym1->isspilt != sym2->isspilt)
656 /* if they are the same */
660 if (strcmp (sym1->rname, sym2->rname) == 0)
664 /* if left is a tmp & right is not */
665 if (IS_ITEMP (op1) &&
668 (sym1->usl.spillLoc == sym2))
671 if (IS_ITEMP (op2) &&
675 (sym2->usl.spillLoc == sym1))
681 /*-----------------------------------------------------------------*/
682 /* sameRegs - two asmops have the same registers */
683 /*-----------------------------------------------------------------*/
685 sameRegs (asmop * aop1, asmop * aop2)
691 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
698 if (aop1->type != AOP_REG ||
699 aop2->type != AOP_REG)
702 if (aop1->size != aop2->size)
705 for (i = 0; i < aop1->size; i++)
706 if (aop1->aopu.aop_reg[i] !=
707 aop2->aopu.aop_reg[i])
713 /*-----------------------------------------------------------------*/
714 /* aopOp - allocates an asmop for an operand : */
715 /*-----------------------------------------------------------------*/
717 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
726 /* if this a literal */
727 if (IS_OP_LITERAL (op))
729 op->aop = aop = newAsmop (AOP_LIT);
730 aop->aopu.aop_lit = op->operand.valOperand;
731 aop->size = getSize (operandType (op));
735 /* if already has a asmop then continue */
739 /* if the underlying symbol has a aop */
740 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
742 op->aop = OP_SYMBOL (op)->aop;
746 /* if this is a true symbol */
747 if (IS_TRUE_SYMOP (op))
749 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
753 /* this is a temporary : this has
759 e) can be a return use only */
761 sym = OP_SYMBOL (op);
764 /* if the type is a conditional */
765 if (sym->regType == REG_CND)
767 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
772 /* if it is spilt then two situations
774 b) has a spill location */
775 if (sym->isspilt || sym->nRegs == 0)
778 /* rematerialize it NOW */
781 sym->aop = op->aop = aop =
783 aop->size = getSize (sym->type);
790 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
791 aop->size = getSize (sym->type);
792 for (i = 0; i < 2; i++)
793 aop->aopu.aop_str[i] = accUse[i];
803 /* a AOP_STR uses DPTR, but DPTR is already in use;
806 fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use! for operand %s\n",sym->name);
809 aop = op->aop = sym->aop = newAsmop (AOP_STR);
810 aop->size = getSize (sym->type);
811 for (i = 0; i < (int) fReturnSizeDS390; i++)
812 aop->aopu.aop_str[i] = fReturn[i];
816 /* else spill location */
817 sym->aop = op->aop = aop =
818 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
819 aop->size = getSize (sym->type);
823 /* must be in a register */
824 sym->aop = op->aop = aop = newAsmop (AOP_REG);
825 aop->size = sym->nRegs;
826 for (i = 0; i < sym->nRegs; i++)
827 aop->aopu.aop_reg[i] = sym->regs[i];
830 /*-----------------------------------------------------------------*/
831 /* freeAsmop - free up the asmop given to an operand */
832 /*----------------------------------------------------------------*/
834 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
851 /* depending on the asmop type only three cases need work AOP_RO
852 , AOP_R1 && AOP_STK */
860 emitcode ("pop", "ar0");
864 bitVectUnSetBit (ic->rUsed, R0_IDX);
872 emitcode ("pop", "ar1");
876 bitVectUnSetBit (ic->rUsed, R1_IDX);
882 int stk = aop->aopu.aop_stk + aop->size;
883 bitVectUnSetBit (ic->rUsed, R0_IDX);
884 bitVectUnSetBit (ic->rUsed, R1_IDX);
886 getFreePtr (ic, &aop, FALSE);
888 if (options.stack10bit)
890 /* I'm not sure what to do here yet... */
893 "*** Warning: probably generating bad code for "
894 "10 bit stack mode.\n");
899 emitcode ("mov", "a,_bp");
900 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
901 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
905 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
910 emitcode ("pop", "acc");
911 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
914 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
917 freeAsmop (op, NULL, ic, TRUE);
920 emitcode ("pop", "ar0");
926 emitcode ("pop", "ar1");
933 /* all other cases just dealloc */
939 OP_SYMBOL (op)->aop = NULL;
940 /* if the symbol has a spill */
942 SPIL_LOC (op)->aop = NULL;
947 /*------------------------------------------------------------------*/
948 /* aopGet - for fetching value of the aop */
950 /* Set canClobberACC if you are sure it is OK to clobber the value */
951 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
952 /* just less efficient. */
953 /*------------------------------------------------------------------*/
965 /* offset is greater than
967 if (offset > (aop->size - 1) &&
968 aop->type != AOP_LIT)
971 /* depending on type */
977 /* if we need to increment it */
978 while (offset > aop->coff)
980 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
984 while (offset < aop->coff)
986 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
993 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
994 return (dname ? "acc" : "a");
996 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
997 rs = Safe_calloc (1, strlen (s) + 1);
1004 if (aop->type == AOP_DPTR2)
1010 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1016 while (offset > aop->coff)
1018 emitcode ("inc", "dptr");
1022 while (offset < aop->coff)
1024 emitcode ("lcall", "__decdptr");
1031 emitcode ("clr", "a");
1032 emitcode ("movc", "a,@a+dptr");
1036 emitcode ("movx", "a,@dptr");
1039 if (aop->type == AOP_DPTR2)
1045 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1046 return DP2_RESULT_REG;
1049 return (dname ? "acc" : "a");
1052 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1053 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1055 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1057 sprintf (s, "#(%s >> %d)",
1058 aop->aopu.aop_immd.aop_immd1,
1062 aop->aopu.aop_immd.aop_immd1);
1063 rs = Safe_calloc (1, strlen (s) + 1);
1069 sprintf (s, "(%s + %d)",
1073 sprintf (s, "%s", aop->aopu.aop_dir);
1074 rs = Safe_calloc (1, strlen (s) + 1);
1080 return aop->aopu.aop_reg[offset]->dname;
1082 return aop->aopu.aop_reg[offset]->name;
1085 emitcode ("clr", "a");
1086 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1087 emitcode ("rlc", "a");
1088 return (dname ? "acc" : "a");
1091 if (!offset && dname)
1093 return aop->aopu.aop_str[offset];
1096 return aopLiteral (aop->aopu.aop_lit, offset);
1100 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1104 return aop->aopu.aop_str[offset];
1108 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1109 "aopget got unsupported aop->type");
1112 /*-----------------------------------------------------------------*/
1113 /* aopPut - puts a string for a aop */
1114 /*-----------------------------------------------------------------*/
1116 aopPut (asmop * aop, char *s, int offset)
1120 if (aop->size && offset > (aop->size - 1))
1122 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1123 "aopPut got offset > aop->size");
1127 /* will assign value to value */
1128 /* depending on where it is ofcourse */
1133 sprintf (d, "(%s + %d)",
1134 aop->aopu.aop_dir, offset);
1136 sprintf (d, "%s", aop->aopu.aop_dir);
1139 emitcode ("mov", "%s,%s", d, s);
1144 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1145 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1148 strcmp (s, "r0") == 0 ||
1149 strcmp (s, "r1") == 0 ||
1150 strcmp (s, "r2") == 0 ||
1151 strcmp (s, "r3") == 0 ||
1152 strcmp (s, "r4") == 0 ||
1153 strcmp (s, "r5") == 0 ||
1154 strcmp (s, "r6") == 0 ||
1155 strcmp (s, "r7") == 0)
1156 emitcode ("mov", "%s,%s",
1157 aop->aopu.aop_reg[offset]->dname, s);
1159 emitcode ("mov", "%s,%s",
1160 aop->aopu.aop_reg[offset]->name, s);
1167 if (aop->type == AOP_DPTR2)
1175 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1176 "aopPut writting to code space");
1180 while (offset > aop->coff)
1183 emitcode ("inc", "dptr");
1186 while (offset < aop->coff)
1189 emitcode ("lcall", "__decdptr");
1194 /* if not in accumulater */
1197 emitcode ("movx", "@dptr,a");
1199 if (aop->type == AOP_DPTR2)
1207 while (offset > aop->coff)
1210 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1212 while (offset < aop->coff)
1215 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1222 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1228 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1230 else if (strcmp (s, "r0") == 0 ||
1231 strcmp (s, "r1") == 0 ||
1232 strcmp (s, "r2") == 0 ||
1233 strcmp (s, "r3") == 0 ||
1234 strcmp (s, "r4") == 0 ||
1235 strcmp (s, "r5") == 0 ||
1236 strcmp (s, "r6") == 0 ||
1237 strcmp (s, "r7") == 0)
1240 sprintf (buffer, "a%s", s);
1241 emitcode ("mov", "@%s,%s",
1242 aop->aopu.aop_ptr->name, buffer);
1245 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1250 if (strcmp (s, "a") == 0)
1251 emitcode ("push", "acc");
1255 emitcode ("push", "acc");
1257 emitcode ("push", s);
1263 /* if bit variable */
1264 if (!aop->aopu.aop_dir)
1266 emitcode ("clr", "a");
1267 emitcode ("rlc", "a");
1272 emitcode ("clr", "%s", aop->aopu.aop_dir);
1274 emitcode ("setb", "%s", aop->aopu.aop_dir);
1275 else if (!strcmp (s, "c"))
1276 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1279 if (strcmp (s, "a"))
1284 symbol *lbl = newiTempLabel (NULL);
1285 emitcode ("clr", "c");
1286 emitcode ("jz", "%05d$", lbl->key + 100);
1287 emitcode ("cpl", "c");
1288 emitcode ("", "%05d$:", lbl->key + 100);
1289 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1297 if (strcmp (aop->aopu.aop_str[offset], s))
1298 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1303 if (!offset && (strcmp (s, "acc") == 0))
1306 if (strcmp (aop->aopu.aop_str[offset], s))
1307 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1311 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1312 "aopPut got unsupported aop->type");
1319 /*--------------------------------------------------------------------*/
1320 /* reAdjustPreg - points a register back to where it should (coff==0) */
1321 /*--------------------------------------------------------------------*/
1323 reAdjustPreg (asmop * aop)
1325 if ((aop->coff==0) || (aop->size <= 1)) {
1334 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1338 if (aop->type == AOP_DPTR2)
1345 emitcode ("lcall", "__decdptr");
1348 if (aop->type == AOP_DPTR2)
1358 #define AOP(op) op->aop
1359 #define AOP_TYPE(op) AOP(op)->type
1360 #define AOP_SIZE(op) AOP(op)->size
1361 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1362 AOP_TYPE(x) == AOP_R0))
1364 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1365 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1368 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1369 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1370 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1372 /* Workaround for DS80C390 bug: div ab may return bogus results
1373 * if A is accessed in instruction immediately before the div.
1375 * Will be fixed in B4 rev of processor, Dallas claims.
1378 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1379 if (!AOP_NEEDSACC(RIGHT)) \
1381 /* We can load A first, then B, since \
1382 * B (the RIGHT operand) won't clobber A, \
1383 * thus avoiding touching A right before the div. \
1385 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1386 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1388 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1392 /* Just stuff in a nop after loading A. */ \
1393 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1394 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1396 emitcode("nop", "; workaround for DS80C390 div bug."); \
1399 /*-----------------------------------------------------------------*/
1400 /* genNotFloat - generates not for float operations */
1401 /*-----------------------------------------------------------------*/
1403 genNotFloat (operand * op, operand * res)
1409 D (emitcode (";", "genNotFloat ");
1412 /* we will put 127 in the first byte of
1414 aopPut (AOP (res), "#127", 0);
1415 size = AOP_SIZE (op) - 1;
1418 _startLazyDPSEvaluation ();
1419 l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1424 emitcode ("orl", "a,%s",
1426 offset++, FALSE, FALSE, FALSE));
1428 _endLazyDPSEvaluation ();
1430 tlbl = newiTempLabel (NULL);
1431 aopPut (res->aop, one, 1);
1432 emitcode ("jz", "%05d$", (tlbl->key + 100));
1433 aopPut (res->aop, zero, 1);
1434 emitcode ("", "%05d$:", (tlbl->key + 100));
1436 size = res->aop->size - 2;
1438 /* put zeros in the rest */
1440 aopPut (res->aop, zero, offset++);
1443 /*-----------------------------------------------------------------*/
1444 /* opIsGptr: returns non-zero if the passed operand is */
1445 /* a generic pointer type. */
1446 /*-----------------------------------------------------------------*/
1448 opIsGptr (operand * op)
1450 sym_link *type = operandType (op);
1452 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1459 /*-----------------------------------------------------------------*/
1460 /* getDataSize - get the operand data size */
1461 /*-----------------------------------------------------------------*/
1463 getDataSize (operand * op)
1466 size = AOP_SIZE (op);
1467 if (size == GPTRSIZE)
1469 sym_link *type = operandType (op);
1470 if (IS_GENPTR (type))
1472 /* generic pointer; arithmetic operations
1473 * should ignore the high byte (pointer type).
1481 /*-----------------------------------------------------------------*/
1482 /* outAcc - output Acc */
1483 /*-----------------------------------------------------------------*/
1485 outAcc (operand * result)
1488 size = getDataSize (result);
1491 aopPut (AOP (result), "a", 0);
1494 /* unsigned or positive */
1497 aopPut (AOP (result), zero, offset++);
1502 /*-----------------------------------------------------------------*/
1503 /* outBitC - output a bit C */
1504 /*-----------------------------------------------------------------*/
1506 outBitC (operand * result)
1508 /* if the result is bit */
1509 if (AOP_TYPE (result) == AOP_CRY)
1511 aopPut (AOP (result), "c", 0);
1515 emitcode ("clr", "a");
1516 emitcode ("rlc", "a");
1521 /*-----------------------------------------------------------------*/
1522 /* toBoolean - emit code for orl a,operator(sizeop) */
1523 /*-----------------------------------------------------------------*/
1525 toBoolean (operand * oper)
1527 int size = AOP_SIZE (oper) - 1;
1531 /* The generic part of a generic pointer should
1532 * not participate in it's truth value.
1534 * i.e. 0x10000000 is zero.
1536 if (opIsGptr (oper))
1538 D (emitcode (";", "toBoolean: generic ptr special case.");
1543 _startLazyDPSEvaluation ();
1544 if (AOP_NEEDSACC (oper) && size)
1547 emitcode ("push", "b");
1548 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1552 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1558 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1562 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1565 _endLazyDPSEvaluation ();
1569 emitcode ("mov", "a,b");
1570 emitcode ("pop", "b");
1575 /*-----------------------------------------------------------------*/
1576 /* genNot - generate code for ! operation */
1577 /*-----------------------------------------------------------------*/
1582 sym_link *optype = operandType (IC_LEFT (ic));
1584 D (emitcode (";", "genNot ");
1587 /* assign asmOps to operand & result */
1588 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1589 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1591 /* if in bit space then a special case */
1592 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1594 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1595 emitcode ("cpl", "c");
1596 outBitC (IC_RESULT (ic));
1600 /* if type float then do float */
1601 if (IS_FLOAT (optype))
1603 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1607 toBoolean (IC_LEFT (ic));
1609 tlbl = newiTempLabel (NULL);
1610 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1611 emitcode ("", "%05d$:", tlbl->key + 100);
1612 outBitC (IC_RESULT (ic));
1615 /* release the aops */
1616 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1617 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1621 /*-----------------------------------------------------------------*/
1622 /* genCpl - generate code for complement */
1623 /*-----------------------------------------------------------------*/
1630 D (emitcode (";", "genCpl ");
1634 /* assign asmOps to operand & result */
1635 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1636 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1638 /* if both are in bit space then
1640 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1641 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1644 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1645 emitcode ("cpl", "c");
1646 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1650 size = AOP_SIZE (IC_RESULT (ic));
1651 _startLazyDPSEvaluation ();
1654 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1656 emitcode ("cpl", "a");
1657 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1659 _endLazyDPSEvaluation ();
1663 /* release the aops */
1664 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1665 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1668 /*-----------------------------------------------------------------*/
1669 /* genUminusFloat - unary minus for floating points */
1670 /*-----------------------------------------------------------------*/
1672 genUminusFloat (operand * op, operand * result)
1674 int size, offset = 0;
1676 /* for this we just need to flip the
1677 first it then copy the rest in place */
1678 D (emitcode (";", "genUminusFloat");
1681 _startLazyDPSEvaluation ();
1682 size = AOP_SIZE (op) - 1;
1683 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1686 emitcode ("cpl", "acc.7");
1687 aopPut (AOP (result), "a", 3);
1691 aopPut (AOP (result),
1692 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1696 _endLazyDPSEvaluation ();
1699 /*-----------------------------------------------------------------*/
1700 /* genUminus - unary minus code generation */
1701 /*-----------------------------------------------------------------*/
1703 genUminus (iCode * ic)
1706 sym_link *optype, *rtype;
1708 D (emitcode (";", "genUminus ");
1713 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1714 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1716 /* if both in bit space then special
1718 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1719 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1722 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1723 emitcode ("cpl", "c");
1724 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1728 optype = operandType (IC_LEFT (ic));
1729 rtype = operandType (IC_RESULT (ic));
1731 /* if float then do float stuff */
1732 if (IS_FLOAT (optype))
1734 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1738 /* otherwise subtract from zero */
1739 size = AOP_SIZE (IC_LEFT (ic));
1741 _startLazyDPSEvaluation ();
1744 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1745 if (!strcmp (l, "a"))
1749 emitcode ("cpl", "a");
1750 emitcode ("addc", "a,#0");
1756 emitcode ("clr", "a");
1757 emitcode ("subb", "a,%s", l);
1759 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1761 _endLazyDPSEvaluation ();
1763 /* if any remaining bytes in the result */
1764 /* we just need to propagate the sign */
1765 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1767 emitcode ("rlc", "a");
1768 emitcode ("subb", "a,acc");
1770 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1774 /* release the aops */
1775 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1776 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1779 /*-----------------------------------------------------------------*/
1780 /* saveRegisters - will look for a call and save the registers */
1781 /*-----------------------------------------------------------------*/
1783 saveRegisters (iCode * lic)
1791 for (ic = lic; ic; ic = ic->next)
1792 if (ic->op == CALL || ic->op == PCALL)
1797 fprintf (stderr, "found parameter push with no function call\n");
1801 /* if the registers have been saved already then
1803 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type) ||
1804 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))))
1807 /* find the registers in use at this time
1808 and push them away to safety */
1809 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1813 if (options.useXstack)
1815 if (bitVectBitValue (rsave, R0_IDX))
1816 emitcode ("mov", "b,r0");
1817 emitcode ("mov", "r0,%s", spname);
1818 for (i = 0; i < ds390_nRegs; i++)
1820 if (bitVectBitValue (rsave, i))
1823 emitcode ("mov", "a,b");
1825 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1826 emitcode ("movx", "@r0,a");
1827 emitcode ("inc", "r0");
1830 emitcode ("mov", "%s,r0", spname);
1831 if (bitVectBitValue (rsave, R0_IDX))
1832 emitcode ("mov", "r0,b");
1835 for (i = 0; i < ds390_nRegs; i++)
1837 if (bitVectBitValue (rsave, i))
1838 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1841 detype = getSpec (operandType (IC_LEFT (ic)));
1844 /*-----------------------------------------------------------------*/
1845 /* unsaveRegisters - pop the pushed registers */
1846 /*-----------------------------------------------------------------*/
1848 unsaveRegisters (iCode * ic)
1852 /* find the registers in use at this time
1853 and push them away to safety */
1854 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1857 if (options.useXstack)
1859 emitcode ("mov", "r0,%s", spname);
1860 for (i = ds390_nRegs; i >= 0; i--)
1862 if (bitVectBitValue (rsave, i))
1864 emitcode ("dec", "r0");
1865 emitcode ("movx", "a,@r0");
1867 emitcode ("mov", "b,a");
1869 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1873 emitcode ("mov", "%s,r0", spname);
1874 if (bitVectBitValue (rsave, R0_IDX))
1875 emitcode ("mov", "r0,b");
1878 for (i = ds390_nRegs; i >= 0; i--)
1880 if (bitVectBitValue (rsave, i))
1881 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1887 /*-----------------------------------------------------------------*/
1889 /*-----------------------------------------------------------------*/
1891 pushSide (operand * oper, int size)
1894 _startLazyDPSEvaluation ();
1897 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1898 if (AOP_TYPE (oper) != AOP_REG &&
1899 AOP_TYPE (oper) != AOP_DIR &&
1902 emitcode ("mov", "a,%s", l);
1903 emitcode ("push", "acc");
1906 emitcode ("push", "%s", l);
1908 _endLazyDPSEvaluation ();
1911 /*-----------------------------------------------------------------*/
1912 /* assignResultValue - */
1913 /*-----------------------------------------------------------------*/
1915 assignResultValue (operand * oper)
1918 int size = AOP_SIZE (oper);
1920 _startLazyDPSEvaluation ();
1923 aopPut (AOP (oper), fReturn[offset], offset);
1926 _endLazyDPSEvaluation ();
1930 /*-----------------------------------------------------------------*/
1931 /* genXpush - pushes onto the external stack */
1932 /*-----------------------------------------------------------------*/
1934 genXpush (iCode * ic)
1936 asmop *aop = newAsmop (0);
1938 int size, offset = 0;
1940 D (emitcode (";", "genXpush ");
1943 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1944 r = getFreePtr (ic, &aop, FALSE);
1947 emitcode ("mov", "%s,_spx", r->name);
1949 size = AOP_SIZE (IC_LEFT (ic));
1950 _startLazyDPSEvaluation ();
1954 char *l = aopGet (AOP (IC_LEFT (ic)),
1955 offset++, FALSE, FALSE, TRUE);
1957 emitcode ("movx", "@%s,a", r->name);
1958 emitcode ("inc", "%s", r->name);
1961 _endLazyDPSEvaluation ();
1964 emitcode ("mov", "_spx,%s", r->name);
1966 freeAsmop (NULL, aop, ic, TRUE);
1967 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1970 /*-----------------------------------------------------------------*/
1971 /* genIpush - genrate code for pushing this gets a little complex */
1972 /*-----------------------------------------------------------------*/
1974 genIpush (iCode * ic)
1976 int size, offset = 0;
1979 D (emitcode (";", "genIpush ");
1982 /* if this is not a parm push : ie. it is spill push
1983 and spill push is always done on the local stack */
1987 /* and the item is spilt then do nothing */
1988 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1991 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1992 size = AOP_SIZE (IC_LEFT (ic));
1993 /* push it on the stack */
1994 _startLazyDPSEvaluation ();
1997 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
2003 emitcode ("push", "%s", l);
2005 _endLazyDPSEvaluation ();
2009 /* this is a paramter push: in this case we call
2010 the routine to find the call and save those
2011 registers that need to be saved */
2014 /* if use external stack then call the external
2015 stack pushing routine */
2016 if (options.useXstack)
2022 /* then do the push */
2023 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2025 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2026 size = AOP_SIZE (IC_LEFT (ic));
2028 _startLazyDPSEvaluation ();
2031 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2032 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2033 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2036 emitcode ("mov", "a,%s", l);
2037 emitcode ("push", "acc");
2040 emitcode ("push", "%s", l);
2042 _endLazyDPSEvaluation ();
2044 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2047 /*-----------------------------------------------------------------*/
2048 /* genIpop - recover the registers: can happen only for spilling */
2049 /*-----------------------------------------------------------------*/
2051 genIpop (iCode * ic)
2055 D (emitcode (";", "genIpop ");
2059 /* if the temp was not pushed then */
2060 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2063 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2064 size = AOP_SIZE (IC_LEFT (ic));
2065 offset = (size - 1);
2066 _startLazyDPSEvaluation ();
2069 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2070 FALSE, TRUE, TRUE));
2072 _endLazyDPSEvaluation ();
2074 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2077 /*-----------------------------------------------------------------*/
2078 /* unsaveRBank - restores the resgister bank from stack */
2079 /*-----------------------------------------------------------------*/
2081 unsaveRBank (int bank, iCode * ic, bool popPsw)
2087 if (options.useXstack)
2091 /* Assume r0 is available for use. */
2092 r = ds390_regWithIdx (R0_IDX);;
2097 r = getFreePtr (ic, &aop, FALSE);
2099 emitcode ("mov", "%s,_spx", r->name);
2104 if (options.useXstack)
2106 emitcode ("movx", "a,@%s", r->name);
2107 emitcode ("mov", "psw,a");
2108 emitcode ("dec", "%s", r->name);
2112 emitcode ("pop", "psw");
2116 for (i = (ds390_nRegs - 1); i >= 0; i--)
2118 if (options.useXstack)
2120 emitcode ("movx", "a,@%s", r->name);
2121 emitcode ("mov", "(%s+%d),a",
2122 regs390[i].base, 8 * bank + regs390[i].offset);
2123 emitcode ("dec", "%s", r->name);
2127 emitcode ("pop", "(%s+%d)",
2128 regs390[i].base, 8 * bank + regs390[i].offset);
2131 if (options.useXstack)
2133 emitcode ("mov", "_spx,%s", r->name);
2138 freeAsmop (NULL, aop, ic, TRUE);
2142 /*-----------------------------------------------------------------*/
2143 /* saveRBank - saves an entire register bank on the stack */
2144 /*-----------------------------------------------------------------*/
2146 saveRBank (int bank, iCode * ic, bool pushPsw)
2152 if (options.useXstack)
2156 /* Assume r0 is available for use. */
2157 r = ds390_regWithIdx (R0_IDX);;
2162 r = getFreePtr (ic, &aop, FALSE);
2164 emitcode ("mov", "%s,_spx", r->name);
2167 for (i = 0; i < ds390_nRegs; i++)
2169 if (options.useXstack)
2171 emitcode ("inc", "%s", r->name);
2172 emitcode ("mov", "a,(%s+%d)",
2173 regs390[i].base, 8 * bank + regs390[i].offset);
2174 emitcode ("movx", "@%s,a", r->name);
2177 emitcode ("push", "(%s+%d)",
2178 regs390[i].base, 8 * bank + regs390[i].offset);
2183 if (options.useXstack)
2185 emitcode ("mov", "a,psw");
2186 emitcode ("movx", "@%s,a", r->name);
2187 emitcode ("inc", "%s", r->name);
2188 emitcode ("mov", "_spx,%s", r->name);
2192 emitcode ("push", "psw");
2195 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2200 freeAsmop (NULL, aop, ic, TRUE);
2209 /*-----------------------------------------------------------------*/
2210 /* genCall - generates a call statement */
2211 /*-----------------------------------------------------------------*/
2213 genCall (iCode * ic)
2216 bool restoreBank = FALSE;
2217 bool swapBanks = FALSE;
2219 D (emitcode (";", "genCall "););
2221 /* if we are calling a not _naked function that is not using
2222 the same register bank then we need to save the
2223 destination registers on the stack */
2224 dtype = operandType (IC_LEFT (ic));
2225 if (dtype && !IFFUNC_ISNAKED(dtype) &&
2226 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2227 IFFUNC_ISISR (currFunc->type))
2231 /* This is unexpected; the bank should have been saved in
2234 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2240 /* if caller saves & we have not saved then */
2244 /* if send set is not empty the assign */
2245 /* We've saved all the registers we care about;
2246 * therefore, we may clobber any register not used
2247 * in the calling convention (i.e. anything not in
2254 for (sic = setFirstItem (_G.sendSet); sic;
2255 sic = setNextItem (_G.sendSet))
2257 int size, offset = 0;
2259 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2260 size = AOP_SIZE (IC_LEFT (sic));
2262 _startLazyDPSEvaluation ();
2265 char *l = aopGet (AOP(IC_LEFT(sic)), offset,
2266 FALSE, FALSE, TRUE);
2267 if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size)
2269 emitcode("mov", "%s,%s", regs390[offset].name, l);
2271 else if (strcmp (l, fReturn[offset]))
2273 emitcode ("mov", "%s,%s",
2279 _endLazyDPSEvaluation ();
2280 if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR)
2282 size = AOP_SIZE (IC_LEFT (sic));
2290 emitcode("mov", "%s,%s",
2291 fReturn[size], regs390[size].name);
2294 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2301 emitcode ("mov", "psw,#0x%02x",
2302 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2306 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2307 OP_SYMBOL (IC_LEFT (ic))->rname :
2308 OP_SYMBOL (IC_LEFT (ic))->name));
2312 emitcode ("mov", "psw,#0x%02x",
2313 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2316 /* if we need assign a result value */
2317 if ((IS_ITEMP (IC_RESULT (ic)) &&
2318 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2319 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2320 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2321 IS_TRUE_SYMOP (IC_RESULT (ic)))
2323 if (isOperandInFarSpace (IC_RESULT (ic))
2324 && getSize (operandType (IC_RESULT (ic))) <= 2)
2326 int size = getSize (operandType (IC_RESULT (ic)));
2328 /* Special case for 1 or 2 byte return in far space. */
2332 emitcode ("mov", "b,%s", fReturn[1]);
2335 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2336 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2340 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2342 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2347 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2350 assignResultValue (IC_RESULT (ic));
2352 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2356 /* adjust the stack for parameters if
2358 if (ic->parmBytes) {
2359 if (options.stack10bit) {
2360 emitcode ("clr","c");
2361 emitcode ("mov","a,sp");
2362 emitcode ("subb","a,#0x%02x",ic->parmBytes & 0xff);
2363 emitcode ("mov","sp,a");
2364 emitcode ("mov","a,#0x%02x",(ic->parmBytes >> 8) & 0xff);
2365 emitcode ("subb","a,_ESP");
2366 emitcode ("mov","_ESP,a");
2369 if (ic->parmBytes > 3) {
2370 emitcode ("mov", "a,%s", spname);
2371 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2372 emitcode ("mov", "%s,a", spname);
2374 for (i = 0; i < ic->parmBytes; i++)
2375 emitcode ("dec", "%s", spname);
2379 /* if we hade saved some registers then unsave them */
2380 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2381 unsaveRegisters (ic);
2383 /* if register bank was saved then pop them */
2385 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2388 /*-----------------------------------------------------------------*/
2389 /* genPcall - generates a call by pointer statement */
2390 /*-----------------------------------------------------------------*/
2392 genPcall (iCode * ic)
2395 symbol *rlbl = newiTempLabel (NULL);
2396 bool restoreBank=FALSE;
2398 D (emitcode (";", "genPcall ");
2402 /* if caller saves & we have not saved then */
2406 /* if we are calling a function that is not using
2407 the same register bank then we need to save the
2408 destination registers on the stack */
2409 dtype = operandType (IC_LEFT (ic));
2410 if (dtype && !IFFUNC_ISNAKED(dtype) &&
2411 IFFUNC_ISISR (currFunc->type) &&
2412 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2413 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2417 /* push the return address on to the stack */
2418 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2419 emitcode ("push", "acc");
2420 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2421 emitcode ("push", "acc");
2423 if (options.model == MODEL_FLAT24)
2425 emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2426 emitcode ("push", "acc");
2429 /* now push the calling address */
2430 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2432 pushSide (IC_LEFT (ic), FPTRSIZE);
2434 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2436 /* if send set is not empty the assign */
2441 for (sic = setFirstItem (_G.sendSet); sic;
2442 sic = setNextItem (_G.sendSet))
2444 int size, offset = 0;
2446 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2447 size = AOP_SIZE (IC_LEFT (sic));
2448 _startLazyDPSEvaluation ();
2451 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2452 FALSE, FALSE, TRUE);
2453 if (strcmp (l, fReturn[offset]))
2455 emitcode ("mov", "%s,%s",
2461 _endLazyDPSEvaluation ();
2462 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2467 emitcode ("ret", "");
2468 emitcode ("", "%05d$:", (rlbl->key + 100));
2471 /* if we need assign a result value */
2472 if ((IS_ITEMP (IC_RESULT (ic)) &&
2473 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2474 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2475 IS_TRUE_SYMOP (IC_RESULT (ic)))
2479 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2482 assignResultValue (IC_RESULT (ic));
2484 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2487 /* adjust the stack for parameters if
2492 if (ic->parmBytes > 3)
2494 emitcode ("mov", "a,%s", spname);
2495 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2496 emitcode ("mov", "%s,a", spname);
2499 for (i = 0; i < ic->parmBytes; i++)
2500 emitcode ("dec", "%s", spname);
2504 /* if register bank was saved then unsave them */
2506 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2508 /* if we hade saved some registers then
2510 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2511 unsaveRegisters (ic);
2515 /*-----------------------------------------------------------------*/
2516 /* resultRemat - result is rematerializable */
2517 /*-----------------------------------------------------------------*/
2519 resultRemat (iCode * ic)
2521 if (SKIP_IC (ic) || ic->op == IFX)
2524 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2526 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2527 if (sym->remat && !POINTER_SET (ic))
2534 #if defined(__BORLANDC__) || defined(_MSC_VER)
2535 #define STRCASECMP stricmp
2537 #define STRCASECMP strcasecmp
2540 /*-----------------------------------------------------------------*/
2541 /* inExcludeList - return 1 if the string is in exclude Reg list */
2542 /*-----------------------------------------------------------------*/
2544 inExcludeList (char *s)
2548 if (options.excludeRegs[i] &&
2549 STRCASECMP (options.excludeRegs[i], "none") == 0)
2552 for (i = 0; options.excludeRegs[i]; i++)
2554 if (options.excludeRegs[i] &&
2555 STRCASECMP (s, options.excludeRegs[i]) == 0)
2561 /*-----------------------------------------------------------------*/
2562 /* genFunction - generated code for function entry */
2563 /*-----------------------------------------------------------------*/
2565 genFunction (iCode * ic)
2569 bool switchedPSW = FALSE;
2571 D (emitcode (";", "genFunction "););
2574 /* create the function header */
2575 emitcode (";", "-----------------------------------------");
2576 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2577 emitcode (";", "-----------------------------------------");
2579 emitcode ("", "%s:", sym->rname);
2580 ftype = operandType (IC_LEFT (ic));
2582 if (IFFUNC_ISNAKED(ftype))
2584 emitcode(";", "naked function: no prologue.");
2588 /* if critical function then turn interrupts off */
2589 if (IFFUNC_ISCRITICAL (ftype))
2590 emitcode ("clr", "ea");
2592 /* here we need to generate the equates for the
2593 register bank if required */
2594 if (FUNC_REGBANK (ftype) != rbank)
2598 rbank = FUNC_REGBANK (ftype);
2599 for (i = 0; i < ds390_nRegs; i++)
2601 if (regs390[i].print) {
2602 if (strcmp (regs390[i].base, "0") == 0)
2603 emitcode ("", "%s = 0x%02x",
2605 8 * rbank + regs390[i].offset);
2607 emitcode ("", "%s = %s + 0x%02x",
2610 8 * rbank + regs390[i].offset);
2615 /* if this is an interrupt service routine then
2616 save acc, b, dpl, dph */
2617 if (IFFUNC_ISISR (sym->type))
2620 if (!inExcludeList ("acc"))
2621 emitcode ("push", "acc");
2622 if (!inExcludeList ("b"))
2623 emitcode ("push", "b");
2624 if (!inExcludeList ("dpl"))
2625 emitcode ("push", "dpl");
2626 if (!inExcludeList ("dph"))
2627 emitcode ("push", "dph");
2628 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2630 emitcode ("push", "dpx");
2631 /* Make sure we're using standard DPTR */
2632 emitcode ("push", "dps");
2633 emitcode ("mov", "dps, #0x00");
2634 if (options.stack10bit)
2636 /* This ISR could conceivably use DPTR2. Better save it. */
2637 emitcode ("push", "dpl1");
2638 emitcode ("push", "dph1");
2639 emitcode ("push", "dpx1");
2640 emitcode ("push", DP2_RESULT_REG);
2643 /* if this isr has no bank i.e. is going to
2644 run with bank 0 , then we need to save more
2646 if (!FUNC_REGBANK (sym->type))
2649 /* if this function does not call any other
2650 function then we can be economical and
2651 save only those registers that are used */
2652 if (!IFFUNC_HASFCALL(sym->type))
2656 /* if any registers used */
2659 /* save the registers used */
2660 for (i = 0; i < sym->regsUsed->size; i++)
2662 if (bitVectBitValue (sym->regsUsed, i) ||
2663 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2664 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2671 /* this function has a function call cannot
2672 determines register usage so we will have to push the
2674 saveRBank (0, ic, FALSE);
2679 /* This ISR uses a non-zero bank.
2681 * We assume that the bank is available for our
2684 * However, if this ISR calls a function which uses some
2685 * other bank, we must save that bank entirely.
2687 unsigned long banksToSave = 0;
2689 if (IFFUNC_HASFCALL(sym->type))
2692 #define MAX_REGISTER_BANKS 4
2697 for (i = ic; i; i = i->next)
2699 if (i->op == ENDFUNCTION)
2701 /* we got to the end OK. */
2709 dtype = operandType (IC_LEFT(i));
2711 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2713 /* Mark this bank for saving. */
2714 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2716 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2720 banksToSave |= (1 << FUNC_REGBANK(dtype));
2723 /* And note that we don't need to do it in
2731 /* This is a mess; we have no idea what
2732 * register bank the called function might
2735 * The only thing I can think of to do is
2736 * throw a warning and hope.
2738 werror(W_FUNCPTR_IN_USING_ISR);
2742 if (banksToSave && options.useXstack)
2744 /* Since we aren't passing it an ic,
2745 * saveRBank will assume r0 is available to abuse.
2747 * So switch to our (trashable) bank now, so
2748 * the caller's R0 isn't trashed.
2750 emitcode ("push", "psw");
2751 emitcode ("mov", "psw,#0x%02x",
2752 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2756 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2758 if (banksToSave & (1 << ix))
2760 saveRBank(ix, NULL, FALSE);
2764 // jwk: this needs a closer look
2765 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2770 /* if callee-save to be used for this function
2771 then save the registers being used in this function */
2772 if (IFFUNC_CALLEESAVES(sym->type))
2776 /* if any registers used */
2779 /* save the registers used */
2780 for (i = 0; i < sym->regsUsed->size; i++)
2782 if (bitVectBitValue (sym->regsUsed, i) ||
2783 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2785 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2793 /* set the register bank to the desired value */
2794 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2797 emitcode ("push", "psw");
2798 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2801 if (IFFUNC_ISREENT (sym->type) || options.stackAuto) {
2802 if (options.stack10bit) {
2803 emitcode ("push","_bpx");
2804 emitcode ("push","_bpx+1");
2805 emitcode ("mov","_bpx,%s",spname);
2806 emitcode ("mov","_bpx+1,_ESP");
2807 emitcode ("anl","_bpx+1,#3");
2809 if (options.useXstack) {
2810 emitcode ("mov", "r0,%s", spname);
2811 emitcode ("mov", "a,_bp");
2812 emitcode ("movx", "@r0,a");
2813 emitcode ("inc", "%s", spname);
2815 /* set up the stack */
2816 emitcode ("push", "_bp"); /* save the callers stack */
2818 emitcode ("mov", "_bp,%s", spname);
2822 /* adjust the stack for the function */
2825 if (options.stack10bit) {
2826 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
2827 assert (sym->recvSize <= 4);
2828 emitcode ("mov","a,sp");
2829 emitcode ("add","a,#0x%02x", ((short) sym->stack & 0xff));
2830 emitcode ("mov","sp,a");
2831 emitcode ("mov","a,_ESP");
2832 emitcode ("addc","a,0x%02x", (((short) sym->stack) >> 8) & 0xff);
2833 emitcode ("mov","_ESP,a");
2836 werror (W_STACK_OVERFLOW, sym->name);
2838 if (i > 3 && sym->recvSize < 4) {
2840 emitcode ("mov", "a,sp");
2841 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2842 emitcode ("mov", "sp,a");
2846 emitcode ("inc", "sp");
2853 emitcode ("mov", "a,_spx");
2854 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2855 emitcode ("mov", "_spx,a");
2860 /*-----------------------------------------------------------------*/
2861 /* genEndFunction - generates epilogue for functions */
2862 /*-----------------------------------------------------------------*/
2864 genEndFunction (iCode * ic)
2866 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2868 D (emitcode (";", "genEndFunction "););
2870 if (IFFUNC_ISNAKED(sym->type))
2872 emitcode(";", "naked function: no epilogue.");
2876 if (IFFUNC_ISREENT (sym->type) || options.stackAuto) {
2877 if (options.stack10bit) {
2878 emitcode ("mov", "sp,_bpx", spname);
2879 emitcode ("mov", "_ESP,_bpx+1", spname);
2881 emitcode ("mov", "%s,_bp", spname);
2885 /* if use external stack but some variables were
2886 added to the local stack then decrement the
2888 if (options.useXstack && sym->stack) {
2889 emitcode ("mov", "a,sp");
2890 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2891 emitcode ("mov", "sp,a");
2895 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto)) {
2896 if (options.useXstack) {
2897 emitcode ("mov", "r0,%s", spname);
2898 emitcode ("movx", "a,@r0");
2899 emitcode ("mov", "_bp,a");
2900 emitcode ("dec", "%s", spname);
2902 if (options.stack10bit) {
2903 emitcode ("pop", "_bpx+1");
2904 emitcode ("pop", "_bpx");
2906 emitcode ("pop", "_bp");
2911 /* restore the register bank */
2912 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2914 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
2915 || !options.useXstack)
2917 /* Special case of ISR using non-zero bank with useXstack
2920 emitcode ("pop", "psw");
2924 if (IFFUNC_ISISR (sym->type))
2927 /* now we need to restore the registers */
2928 /* if this isr has no bank i.e. is going to
2929 run with bank 0 , then we need to save more
2931 if (!FUNC_REGBANK (sym->type))
2933 /* if this function does not call any other
2934 function then we can be economical and
2935 save only those registers that are used */
2936 if (!IFFUNC_HASFCALL(sym->type))
2940 /* if any registers used */
2943 /* save the registers used */
2944 for (i = sym->regsUsed->size; i >= 0; i--)
2946 if (bitVectBitValue (sym->regsUsed, i) ||
2947 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2948 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2955 /* this function has a function call cannot
2956 determines register usage so we will have to pop the
2958 unsaveRBank (0, ic, FALSE);
2963 /* This ISR uses a non-zero bank.
2965 * Restore any register banks saved by genFunction
2968 // jwk: this needs a closer look
2969 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2972 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2974 if (savedBanks & (1 << ix))
2976 unsaveRBank(ix, NULL, FALSE);
2980 if (options.useXstack)
2982 /* Restore bank AFTER calling unsaveRBank,
2983 * since it can trash r0.
2985 emitcode ("pop", "psw");
2989 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2991 if (options.stack10bit)
2993 emitcode ("pop", DP2_RESULT_REG);
2994 emitcode ("pop", "dpx1");
2995 emitcode ("pop", "dph1");
2996 emitcode ("pop", "dpl1");
2998 emitcode ("pop", "dps");
2999 emitcode ("pop", "dpx");
3001 if (!inExcludeList ("dph"))
3002 emitcode ("pop", "dph");
3003 if (!inExcludeList ("dpl"))
3004 emitcode ("pop", "dpl");
3005 if (!inExcludeList ("b"))
3006 emitcode ("pop", "b");
3007 if (!inExcludeList ("acc"))
3008 emitcode ("pop", "acc");
3010 if (IFFUNC_ISCRITICAL (sym->type))
3011 emitcode ("setb", "ea");
3013 /* if debug then send end of function */
3014 if (options.debug && currFunc) {
3016 emitcode ("", "C$%s$%d$%d$%d ==.",
3017 FileBaseName (ic->filename), currFunc->lastLine,
3018 ic->level, ic->block);
3019 if (IS_STATIC (currFunc->etype))
3020 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3022 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3026 emitcode ("reti", "");
3030 if (IFFUNC_ISCRITICAL (sym->type))
3031 emitcode ("setb", "ea");
3033 if (IFFUNC_CALLEESAVES(sym->type))
3037 /* if any registers used */
3040 /* save the registers used */
3041 for (i = sym->regsUsed->size; i >= 0; i--)
3043 if (bitVectBitValue (sym->regsUsed, i) ||
3044 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3045 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3051 /* if debug then send end of function */
3052 if (options.debug && currFunc)
3055 emitcode ("", "C$%s$%d$%d$%d ==.",
3056 FileBaseName (ic->filename), currFunc->lastLine,
3057 ic->level, ic->block);
3058 if (IS_STATIC (currFunc->etype))
3059 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3061 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3065 emitcode ("ret", "");
3070 /*-----------------------------------------------------------------*/
3071 /* genRet - generate code for return statement */
3072 /*-----------------------------------------------------------------*/
3076 int size, offset = 0, pushed = 0;
3078 D (emitcode (";", "genRet ");
3081 /* if we have no return value then
3082 just generate the "ret" */
3086 /* we have something to return then
3087 move the return value into place */
3088 aopOp (IC_LEFT (ic), ic, FALSE,
3089 (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3090 size = AOP_SIZE (IC_LEFT (ic));
3092 _startLazyDPSEvaluation ();
3096 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3098 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3099 FALSE, TRUE, FALSE);
3100 emitcode ("push", "%s", l);
3105 /* Since A is the last element of fReturn,
3106 * is is OK to clobber it in the aopGet.
3108 l = aopGet (AOP (IC_LEFT (ic)), offset,
3109 FALSE, FALSE, TRUE);
3110 if (strcmp (fReturn[offset], l))
3111 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3114 _endLazyDPSEvaluation ();
3121 if (strcmp (fReturn[pushed], "a"))
3122 emitcode ("pop", fReturn[pushed]);
3124 emitcode ("pop", "acc");
3127 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3130 /* generate a jump to the return label
3131 if the next is not the return statement */
3132 if (!(ic->next && ic->next->op == LABEL &&
3133 IC_LABEL (ic->next) == returnLabel))
3135 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3139 /*-----------------------------------------------------------------*/
3140 /* genLabel - generates a label */
3141 /*-----------------------------------------------------------------*/
3143 genLabel (iCode * ic)
3145 /* special case never generate */
3146 if (IC_LABEL (ic) == entryLabel)
3149 D (emitcode (";", "genLabel ");
3152 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3155 /*-----------------------------------------------------------------*/
3156 /* genGoto - generates a ljmp */
3157 /*-----------------------------------------------------------------*/
3159 genGoto (iCode * ic)
3161 D (emitcode (";", "genGoto ");
3163 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3166 /*-----------------------------------------------------------------*/
3167 /* findLabelBackwards: walks back through the iCode chain looking */
3168 /* for the given label. Returns number of iCode instructions */
3169 /* between that label and given ic. */
3170 /* Returns zero if label not found. */
3171 /*-----------------------------------------------------------------*/
3173 findLabelBackwards (iCode * ic, int key)
3182 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3184 /* printf("findLabelBackwards = %d\n", count); */
3192 /*-----------------------------------------------------------------*/
3193 /* genPlusIncr :- does addition with increment if possible */
3194 /*-----------------------------------------------------------------*/
3196 genPlusIncr (iCode * ic)
3198 unsigned int icount;
3199 unsigned int size = getDataSize (IC_RESULT (ic));
3201 /* will try to generate an increment */
3202 /* if the right side is not a literal
3204 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3207 /* if the literal value of the right hand side
3208 is greater than 4 then it is not worth it */
3209 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3212 /* if increment 16 bits in register */
3214 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3215 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3216 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3224 /* If the next instruction is a goto and the goto target
3225 * is <= 5 instructions previous to this, we can generate
3226 * jumps straight to that target.
3228 if (ic->next && ic->next->op == GOTO
3229 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3232 emitcode (";", "tail increment optimized (range %d)", labelRange);
3233 tlbl = IC_LABEL (ic->next);
3238 tlbl = newiTempLabel (NULL);
3241 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3242 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3243 IS_AOP_PREG (IC_RESULT (ic)))
3244 emitcode ("cjne", "%s,#0x00,%05d$"
3245 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3249 emitcode ("clr", "a");
3250 emitcode ("cjne", "a,%s,%05d$"
3251 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3255 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3258 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3259 IS_AOP_PREG (IC_RESULT (ic)))
3260 emitcode ("cjne", "%s,#0x00,%05d$"
3261 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3264 emitcode ("cjne", "a,%s,%05d$"
3265 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3268 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3272 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3273 IS_AOP_PREG (IC_RESULT (ic)))
3274 emitcode ("cjne", "%s,#0x00,%05d$"
3275 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3279 emitcode ("cjne", "a,%s,%05d$"
3280 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3283 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3288 emitcode ("", "%05d$:", tlbl->key + 100);
3293 /* if the sizes are greater than 1 then we cannot */
3294 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3295 AOP_SIZE (IC_LEFT (ic)) > 1)
3298 /* we can if the aops of the left & result match or
3299 if they are in registers and the registers are the
3302 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3303 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3304 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3309 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3310 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3311 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3316 _startLazyDPSEvaluation ();
3319 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3321 _endLazyDPSEvaluation ();
3330 /*-----------------------------------------------------------------*/
3331 /* outBitAcc - output a bit in acc */
3332 /*-----------------------------------------------------------------*/
3334 outBitAcc (operand * result)
3336 symbol *tlbl = newiTempLabel (NULL);
3337 /* if the result is a bit */
3338 if (AOP_TYPE (result) == AOP_CRY)
3340 aopPut (AOP (result), "a", 0);
3344 emitcode ("jz", "%05d$", tlbl->key + 100);
3345 emitcode ("mov", "a,%s", one);
3346 emitcode ("", "%05d$:", tlbl->key + 100);
3351 /*-----------------------------------------------------------------*/
3352 /* genPlusBits - generates code for addition of two bits */
3353 /*-----------------------------------------------------------------*/
3355 genPlusBits (iCode * ic)
3357 D (emitcode (";", "genPlusBits ");
3359 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3361 symbol *lbl = newiTempLabel (NULL);
3362 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3363 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3364 emitcode ("cpl", "c");
3365 emitcode ("", "%05d$:", (lbl->key + 100));
3366 outBitC (IC_RESULT (ic));
3370 emitcode ("clr", "a");
3371 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3372 emitcode ("rlc", "a");
3373 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3374 emitcode ("addc", "a,#0x00");
3375 outAcc (IC_RESULT (ic));
3380 adjustArithmeticResult (iCode * ic)
3382 if (opIsGptr (IC_RESULT (ic)) &&
3383 opIsGptr (IC_LEFT (ic)) &&
3384 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3386 aopPut (AOP (IC_RESULT (ic)),
3387 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3391 if (opIsGptr (IC_RESULT (ic)) &&
3392 opIsGptr (IC_RIGHT (ic)) &&
3393 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3395 aopPut (AOP (IC_RESULT (ic)),
3396 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3400 if (opIsGptr (IC_RESULT (ic)) &&
3401 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3402 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3403 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3404 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3407 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3408 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3412 #if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
3413 // Please don't bring it back without a really good reason.
3414 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3415 // (because all three operands are in far space).
3416 #define AOP_OP_3(ic) \
3417 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3418 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3419 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3420 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3421 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3422 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3424 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3426 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3430 // Macro to aopOp all three operands of an ic. If this cannot be done,
3431 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3432 // will be set TRUE. The caller must then handle the case specially, noting
3433 // that the IC_RESULT operand is not aopOp'd.
3434 #define AOP_OP_3_NOFATAL(ic, rc) \
3435 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3436 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR) || \
3437 (OP_SYMBOL(IC_RESULT(ic))->ruonly)); \
3438 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3439 (isOperandInFarSpace(IC_RESULT(ic)) || OP_SYMBOL(IC_RESULT(ic))->ruonly )) \
3441 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3446 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3447 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3449 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3450 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3452 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3454 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3458 // aopOp the left & right operands of an ic.
3459 #define AOP_OP_2(ic) \
3460 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3461 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3463 // convienience macro.
3464 #define AOP_SET_LOCALS(ic) \
3465 left = IC_LEFT(ic); \
3466 right = IC_RIGHT(ic); \
3467 result = IC_RESULT(ic);
3470 // Given an integer value of pushedSize bytes on the stack,
3471 // adjust it to be resultSize bytes, either by discarding
3472 // the most significant bytes or by zero-padding.
3474 // On exit from this macro, pushedSize will have been adjusted to
3475 // equal resultSize, and ACC may be trashed.
3476 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3477 /* If the pushed data is bigger than the result, \
3478 * simply discard unused bytes. Icky, but works. \
3480 while (pushedSize > resultSize) \
3482 D (emitcode (";", "discarding unused result byte."););\
3483 emitcode ("pop", "acc"); \
3486 if (pushedSize < resultSize) \
3488 emitcode ("clr", "a"); \
3489 /* Conversly, we haven't pushed enough here. \
3490 * just zero-pad, and all is well. \
3492 while (pushedSize < resultSize) \
3494 emitcode("push", "acc"); \
3498 assert(pushedSize == resultSize);
3500 /*-----------------------------------------------------------------*/
3501 /* genPlus - generates code for addition */
3502 /*-----------------------------------------------------------------*/
3504 genPlus (iCode * ic)
3506 int size, offset = 0;
3507 bool pushResult = FALSE;
3510 D (emitcode (";", "genPlus "););
3512 /* special cases :- */
3513 if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) &&
3514 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3515 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3516 size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3517 while (size--) emitcode ("inc","dptr");
3518 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3521 if ( IS_SYMOP(IC_LEFT(ic)) &&
3522 OP_SYMBOL(IC_LEFT(ic))->remat &&
3523 isOperandInFarSpace(IC_RIGHT(ic))) {
3524 operand *op = IC_RIGHT(ic);
3525 IC_RIGHT(ic) = IC_LEFT(ic);
3529 AOP_OP_3_NOFATAL (ic, pushResult);
3532 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3537 /* if literal, literal on the right or
3538 if left requires ACC or right is already
3540 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3541 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3542 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3544 operand *t = IC_RIGHT (ic);
3545 IC_RIGHT (ic) = IC_LEFT (ic);
3547 emitcode (";", "Swapped plus args.");
3550 /* if both left & right are in bit
3552 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3553 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3559 /* if left in bit space & right literal */
3560 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3561 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3563 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3564 /* if result in bit space */
3565 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3567 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3568 emitcode ("cpl", "c");
3569 outBitC (IC_RESULT (ic));
3573 size = getDataSize (IC_RESULT (ic));
3574 _startLazyDPSEvaluation ();
3577 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3578 emitcode ("addc", "a,#00");
3579 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3581 _endLazyDPSEvaluation ();
3586 /* if I can do an increment instead
3587 of add then GOOD for ME */
3588 if (genPlusIncr (ic) == TRUE)
3590 emitcode (";", "did genPlusIncr");
3595 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3597 _startLazyDPSEvaluation ();
3600 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3602 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3604 emitcode ("add", "a,%s",
3605 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3607 emitcode ("addc", "a,%s",
3608 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3612 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3614 /* right is going to use ACC or we would have taken the
3617 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3619 D(emitcode(";", "+ AOP_ACC special case."););
3620 emitcode("xch", "a, %s", DP2_RESULT_REG);
3622 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3625 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3628 emitcode("add", "a, %s", DP2_RESULT_REG);
3632 emitcode ("add", "a,%s",
3633 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3638 emitcode ("addc", "a,%s",
3639 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3644 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3648 emitcode ("push", "acc");
3652 _endLazyDPSEvaluation ();
3656 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3658 size = getDataSize (IC_LEFT (ic));
3659 rSize = getDataSize (IC_RESULT (ic));
3661 ADJUST_PUSHED_RESULT(size, rSize);
3663 _startLazyDPSEvaluation ();
3666 emitcode ("pop", "acc");
3667 aopPut (AOP (IC_RESULT (ic)), "a", size);
3669 _endLazyDPSEvaluation ();
3672 adjustArithmeticResult (ic);
3675 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3676 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3677 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3680 /*-----------------------------------------------------------------*/
3681 /* genMinusDec :- does subtraction with deccrement if possible */
3682 /*-----------------------------------------------------------------*/
3684 genMinusDec (iCode * ic)
3686 unsigned int icount;
3687 unsigned int size = getDataSize (IC_RESULT (ic));
3689 /* will try to generate an increment */
3690 /* if the right side is not a literal
3692 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3695 /* if the literal value of the right hand side
3696 is greater than 4 then it is not worth it */
3697 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3700 /* if decrement 16 bits in register */
3701 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3702 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3703 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3711 /* If the next instruction is a goto and the goto target
3712 * is <= 5 instructions previous to this, we can generate
3713 * jumps straight to that target.
3715 if (ic->next && ic->next->op == GOTO
3716 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3719 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3720 tlbl = IC_LABEL (ic->next);
3725 tlbl = newiTempLabel (NULL);
3729 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3730 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3731 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3732 IS_AOP_PREG (IC_RESULT (ic)))
3733 emitcode ("cjne", "%s,#0xff,%05d$"
3734 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3738 emitcode ("mov", "a,#0xff");
3739 emitcode ("cjne", "a,%s,%05d$"
3740 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3743 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3746 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3747 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3748 IS_AOP_PREG (IC_RESULT (ic)))
3749 emitcode ("cjne", "%s,#0xff,%05d$"
3750 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3754 emitcode ("cjne", "a,%s,%05d$"
3755 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3758 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3762 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3763 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3764 IS_AOP_PREG (IC_RESULT (ic)))
3765 emitcode ("cjne", "%s,#0xff,%05d$"
3766 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3770 emitcode ("cjne", "a,%s,%05d$"
3771 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3774 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3778 emitcode ("", "%05d$:", tlbl->key + 100);
3783 /* if the sizes are greater than 1 then we cannot */
3784 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3785 AOP_SIZE (IC_LEFT (ic)) > 1)
3788 /* we can if the aops of the left & result match or
3789 if they are in registers and the registers are the
3792 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3793 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3794 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3797 _startLazyDPSEvaluation ();
3800 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3802 _endLazyDPSEvaluation ();
3810 /*-----------------------------------------------------------------*/
3811 /* addSign - complete with sign */
3812 /*-----------------------------------------------------------------*/
3814 addSign (operand * result, int offset, int sign)
3816 int size = (getDataSize (result) - offset);
3819 _startLazyDPSEvaluation();
3822 emitcode ("rlc", "a");
3823 emitcode ("subb", "a,acc");
3826 aopPut (AOP (result), "a", offset++);
3833 aopPut (AOP (result), zero, offset++);
3836 _endLazyDPSEvaluation();
3840 /*-----------------------------------------------------------------*/
3841 /* genMinusBits - generates code for subtraction of two bits */
3842 /*-----------------------------------------------------------------*/
3844 genMinusBits (iCode * ic)
3846 symbol *lbl = newiTempLabel (NULL);
3848 D (emitcode (";", "genMinusBits "););
3850 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3852 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3853 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3854 emitcode ("cpl", "c");
3855 emitcode ("", "%05d$:", (lbl->key + 100));
3856 outBitC (IC_RESULT (ic));
3860 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3861 emitcode ("subb", "a,acc");
3862 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3863 emitcode ("inc", "a");
3864 emitcode ("", "%05d$:", (lbl->key + 100));
3865 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3866 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3870 /*-----------------------------------------------------------------*/
3871 /* genMinus - generates code for subtraction */
3872 /*-----------------------------------------------------------------*/
3874 genMinus (iCode * ic)
3876 int size, offset = 0;
3878 unsigned long lit = 0L;
3879 bool pushResult = FALSE;
3881 D (emitcode (";", "genMinus "););
3883 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3884 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3885 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3886 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3892 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3894 /* special cases :- */
3895 /* if both left & right are in bit space */
3896 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3897 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3903 /* if I can do an decrement instead
3904 of subtract then GOOD for ME */
3905 if (genMinusDec (ic) == TRUE)
3910 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3912 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3918 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3923 /* if literal, add a,#-lit, else normal subb */
3924 _startLazyDPSEvaluation ();
3927 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3928 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3929 emitcode ("subb", "a,%s",
3930 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3933 /* first add without previous c */
3935 if (!size && lit==-1) {
3936 emitcode ("dec", "a");
3938 emitcode ("add", "a,#0x%02x",
3939 (unsigned int) (lit & 0x0FFL));
3942 emitcode ("addc", "a,#0x%02x",
3943 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3949 emitcode ("push", "acc");
3953 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3957 _endLazyDPSEvaluation ();
3961 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3963 size = getDataSize (IC_LEFT (ic));
3964 rSize = getDataSize (IC_RESULT (ic));
3966 ADJUST_PUSHED_RESULT(size, rSize);
3968 _startLazyDPSEvaluation ();
3971 emitcode ("pop", "acc");
3972 aopPut (AOP (IC_RESULT (ic)), "a", size);
3974 _endLazyDPSEvaluation ();
3977 adjustArithmeticResult (ic);
3980 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3981 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3982 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3986 /*-----------------------------------------------------------------*/
3987 /* genMultbits :- multiplication of bits */
3988 /*-----------------------------------------------------------------*/
3990 genMultbits (operand * left,
3995 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3996 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3997 aopOp(result, ic, TRUE, FALSE);
4002 /*-----------------------------------------------------------------*/
4003 /* genMultOneByte : 8*8=8/16 bit multiplication */
4004 /*-----------------------------------------------------------------*/
4006 genMultOneByte (operand * left,
4011 sym_link *opetype = operandType (result);
4015 /* (if two literals: the value is computed before) */
4016 /* if one literal, literal on the right */
4017 if (AOP_TYPE (left) == AOP_LIT)
4022 emitcode (";", "swapped left and right");
4025 if (SPEC_USIGN(opetype)
4026 // ignore the sign of left and right, what else can we do?
4027 || (SPEC_USIGN(operandType(left)) &&
4028 SPEC_USIGN(operandType(right)))) {
4029 // just an unsigned 8*8=8/16 multiply
4030 //emitcode (";","unsigned");
4031 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4032 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4033 emitcode ("mul", "ab");
4036 aopOp(result, ic, TRUE, FALSE);
4038 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4040 // this should never happen
4041 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4042 AOP_SIZE(result), __FILE__, lineno);
4046 aopPut (AOP (result), "a", 0);
4048 if (AOP_SIZE(result)==2)
4050 aopPut (AOP (result), "b", 1);
4055 // we have to do a signed multiply
4057 emitcode (";", "signed");
4058 emitcode ("clr", "F0"); // reset sign flag
4059 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4061 lbl=newiTempLabel(NULL);
4062 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
4063 // left side is negative, 8-bit two's complement, this fails for -128
4064 emitcode ("setb", "F0"); // set sign flag
4065 emitcode ("cpl", "a");
4066 emitcode ("inc", "a");
4068 emitcode ("", "%05d$:", lbl->key+100);
4071 if (AOP_TYPE(right)==AOP_LIT) {
4072 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4073 /* AND literal negative */
4074 if ((int) val < 0) {
4075 emitcode ("cpl", "F0"); // complement sign flag
4076 emitcode ("mov", "b,#0x%02x", -val);
4078 emitcode ("mov", "b,#0x%02x", val);
4081 lbl=newiTempLabel(NULL);
4082 emitcode ("mov", "b,a");
4083 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4084 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
4085 // right side is negative, 8-bit two's complement
4086 emitcode ("cpl", "F0"); // complement sign flag
4087 emitcode ("cpl", "a");
4088 emitcode ("inc", "a");
4089 emitcode ("", "%05d$:", lbl->key+100);
4091 emitcode ("mul", "ab");
4094 aopOp(result, ic, TRUE, FALSE);
4096 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4098 // this should never happen
4099 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4100 AOP_SIZE(result), __FILE__, lineno);
4104 lbl=newiTempLabel(NULL);
4105 emitcode ("jnb", "F0,%05d$", lbl->key+100);
4106 // only ONE op was negative, we have to do a 8/16-bit two's complement
4107 emitcode ("cpl", "a"); // lsb
4108 if (AOP_SIZE(result)==1) {
4109 emitcode ("inc", "a");
4111 emitcode ("add", "a,#1");
4112 emitcode ("xch", "a,b");
4113 emitcode ("cpl", "a"); // msb
4114 emitcode ("addc", "a,#0");
4115 emitcode ("xch", "a,b");
4118 emitcode ("", "%05d$:", lbl->key+100);
4119 aopPut (AOP (result), "a", 0);
4121 if (AOP_SIZE(result)==2) {
4122 aopPut (AOP (result), "b", 1);
4126 /*-----------------------------------------------------------------*/
4127 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4128 /*-----------------------------------------------------------------*/
4129 static void genMultTwoByte (operand *left, operand *right,
4130 operand *result, iCode *ic)
4132 sym_link *retype = getSpec(operandType(right));
4133 sym_link *letype = getSpec(operandType(left));
4134 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4137 if (AOP_TYPE (left) == AOP_LIT) {
4142 /* save EA bit in F1 */
4143 lbl = newiTempLabel(NULL);
4144 emitcode ("setb","F1");
4145 emitcode ("jbc","EA,%05d$",lbl->key+100);
4146 emitcode ("clr","F1");
4147 emitcode("","%05d$:",lbl->key+100);
4149 /* load up MB with right */
4151 emitcode("clr","F0");
4152 if (AOP_TYPE(right) == AOP_LIT) {
4153 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4155 emitcode("setb","F0");
4158 emitcode ("mov","mb,#0x%02x",val & 0xff);
4159 emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4161 lbl = newiTempLabel(NULL);
4162 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4163 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4164 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4165 emitcode ("xch", "a,b");
4166 emitcode ("cpl","a");
4167 emitcode ("add", "a,#1");
4168 emitcode ("xch", "a,b");
4169 emitcode ("cpl", "a"); // msb
4170 emitcode ("addc", "a,#0");
4171 emitcode ("setb","F0");
4172 emitcode ("","%05d$:",lbl->key+100);
4173 emitcode ("mov","mb,b");
4174 emitcode ("mov","mb,a");
4177 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4178 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4180 /* load up MA with left */
4182 lbl = newiTempLabel(NULL);
4183 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4184 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4185 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4186 emitcode ("xch", "a,b");
4187 emitcode ("cpl","a");
4188 emitcode ("add", "a,#1");
4189 emitcode ("xch", "a,b");
4190 emitcode ("cpl", "a"); // msb
4191 emitcode ("addc","a,#0");
4192 emitcode ("jbc","F0,%05d$",lbl->key+100);
4193 emitcode ("setb","F0");
4194 emitcode ("","%05d$:",lbl->key+100);
4195 emitcode ("mov","ma,b");
4196 emitcode ("mov","ma,a");
4198 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4199 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4201 /* wait for multiplication to finish */
4202 lbl = newiTempLabel(NULL);
4203 emitcode("","%05d$:", lbl->key+100);
4204 emitcode("mov","a,mcnt1");
4205 emitcode("anl","a,#0x80");
4206 emitcode("jnz","%05d$",lbl->key+100);
4208 freeAsmop (left, NULL, ic, TRUE);
4209 freeAsmop (right, NULL, ic,TRUE);
4210 aopOp(result, ic, TRUE, FALSE);
4212 /* if unsigned then simple */
4214 emitcode ("mov","a,ma");
4215 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4216 emitcode ("mov","a,ma");
4217 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4218 aopPut(AOP(result),"ma",1);
4219 aopPut(AOP(result),"ma",0);
4221 emitcode("push","ma");
4222 emitcode("push","ma");
4223 emitcode("push","ma");
4225 /* negate result if needed */
4226 lbl = newiTempLabel(NULL);
4227 emitcode("jnb","F0,%05d$",lbl->key+100);
4228 emitcode("cpl","a");
4229 emitcode("add","a,#1");
4230 emitcode("","%05d$:", lbl->key+100);
4231 if (AOP_TYPE(result) == AOP_ACC)
4233 D(emitcode(";", "ACC special case."););
4234 /* We know result is the only live aop, and
4235 * it's obviously not a DPTR2, so AP is available.
4237 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4241 aopPut(AOP(result),"a",0);
4244 emitcode("pop","acc");
4245 lbl = newiTempLabel(NULL);
4246 emitcode("jnb","F0,%05d$",lbl->key+100);
4247 emitcode("cpl","a");
4248 emitcode("addc","a,#0");
4249 emitcode("","%05d$:", lbl->key+100);
4250 aopPut(AOP(result),"a",1);
4251 emitcode("pop","acc");
4252 if (AOP_SIZE(result) >= 3) {
4253 lbl = newiTempLabel(NULL);
4254 emitcode("jnb","F0,%05d$",lbl->key+100);
4255 emitcode("cpl","a");
4256 emitcode("addc","a,#0");
4257 emitcode("","%05d$:", lbl->key+100);
4258 aopPut(AOP(result),"a",2);
4260 emitcode("pop","acc");
4261 if (AOP_SIZE(result) >= 4) {
4262 lbl = newiTempLabel(NULL);
4263 emitcode("jnb","F0,%05d$",lbl->key+100);
4264 emitcode("cpl","a");
4265 emitcode("addc","a,#0");
4266 emitcode("","%05d$:", lbl->key+100);
4267 aopPut(AOP(result),"a",3);
4269 if (AOP_TYPE(result) == AOP_ACC)
4271 /* We stashed the result away above. */
4272 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4276 freeAsmop (result, NULL, ic, TRUE);
4278 /* restore EA bit in F1 */
4279 lbl = newiTempLabel(NULL);
4280 emitcode ("jnb","F1,%05d$",lbl->key+100);
4281 emitcode ("setb","EA");
4282 emitcode("","%05d$:",lbl->key+100);
4286 /*-----------------------------------------------------------------*/
4287 /* genMult - generates code for multiplication */
4288 /*-----------------------------------------------------------------*/
4290 genMult (iCode * ic)
4292 operand *left = IC_LEFT (ic);
4293 operand *right = IC_RIGHT (ic);
4294 operand *result = IC_RESULT (ic);
4296 D (emitcode (";", "genMult "););
4298 /* assign the amsops */
4301 /* special cases first */
4303 if (AOP_TYPE (left) == AOP_CRY &&
4304 AOP_TYPE (right) == AOP_CRY)
4306 genMultbits (left, right, result, ic);
4310 /* if both are of size == 1 */
4311 if (AOP_SIZE (left) == 1 &&
4312 AOP_SIZE (right) == 1)
4314 genMultOneByte (left, right, result, ic);
4318 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4319 /* use the ds390 ARITHMETIC accel UNIT */
4320 genMultTwoByte (left, right, result, ic);
4323 /* should have been converted to function call */
4327 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4328 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4329 freeAsmop (result, NULL, ic, TRUE);
4332 /*-----------------------------------------------------------------*/
4333 /* genDivbits :- division of bits */
4334 /*-----------------------------------------------------------------*/
4336 genDivbits (operand * left,
4344 /* the result must be bit */
4345 LOAD_AB_FOR_DIV (left, right, l);
4346 emitcode ("div", "ab");
4347 emitcode ("rrc", "a");
4348 aopOp(result, ic, TRUE, FALSE);
4350 aopPut (AOP (result), "c", 0);
4353 /*-----------------------------------------------------------------*/
4354 /* genDivOneByte : 8 bit division */
4355 /*-----------------------------------------------------------------*/
4357 genDivOneByte (operand * left,
4362 sym_link *opetype = operandType (result);
4368 /* signed or unsigned */
4369 if (SPEC_USIGN (opetype))
4371 /* unsigned is easy */
4372 LOAD_AB_FOR_DIV (left, right, l);
4373 emitcode ("div", "ab");
4376 aopOp(result, ic, TRUE, FALSE);
4377 aopPut (AOP (result), "a", 0);
4380 size = AOP_SIZE (result) - 1;
4384 aopPut (AOP (result), zero, offset++);
4389 /* signed is a little bit more difficult */
4391 /* save the signs of the operands */
4392 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4394 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4395 emitcode ("push", "acc"); /* save it on the stack */
4397 /* now sign adjust for both left & right */
4398 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4400 lbl = newiTempLabel (NULL);
4401 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4402 emitcode ("cpl", "a");
4403 emitcode ("inc", "a");
4404 emitcode ("", "%05d$:", (lbl->key + 100));
4405 emitcode ("mov", "b,a");
4407 /* sign adjust left side */
4408 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4411 lbl = newiTempLabel (NULL);
4412 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4413 emitcode ("cpl", "a");
4414 emitcode ("inc", "a");
4415 emitcode ("", "%05d$:", (lbl->key + 100));
4417 /* now the division */
4418 emitcode ("nop", "; workaround for DS80C390 div bug.");
4419 emitcode ("div", "ab");
4420 /* we are interested in the lower order
4422 emitcode ("mov", "b,a");
4423 lbl = newiTempLabel (NULL);
4424 emitcode ("pop", "acc");
4425 /* if there was an over flow we don't
4426 adjust the sign of the result */
4427 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4428 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4430 emitcode ("clr", "a");
4431 emitcode ("subb", "a,b");
4432 emitcode ("mov", "b,a");
4433 emitcode ("", "%05d$:", (lbl->key + 100));
4435 /* now we are done */
4437 aopOp(result, ic, TRUE, FALSE);
4439 aopPut (AOP (result), "b", 0);
4441 size = AOP_SIZE (result) - 1;
4445 emitcode ("mov", "c,b.7");
4446 emitcode ("subb", "a,acc");
4450 aopPut (AOP (result), "a", offset++);
4456 /*-----------------------------------------------------------------*/
4457 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4458 /*-----------------------------------------------------------------*/
4459 static void genDivTwoByte (operand *left, operand *right,
4460 operand *result, iCode *ic)
4462 sym_link *retype = getSpec(operandType(right));
4463 sym_link *letype = getSpec(operandType(left));
4464 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4467 /* save EA bit in F1 */
4468 lbl = newiTempLabel(NULL);
4469 emitcode ("setb","F1");
4470 emitcode ("jbc","EA,%05d$",lbl->key+100);
4471 emitcode ("clr","F1");
4472 emitcode("","%05d$:",lbl->key+100);
4474 /* load up MA with left */
4476 emitcode("clr","F0");
4477 lbl = newiTempLabel(NULL);
4478 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4479 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4480 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4481 emitcode ("xch", "a,b");
4482 emitcode ("cpl","a");
4483 emitcode ("add", "a,#1");
4484 emitcode ("xch", "a,b");
4485 emitcode ("cpl", "a"); // msb
4486 emitcode ("addc","a,#0");
4487 emitcode ("setb","F0");
4488 emitcode ("","%05d$:",lbl->key+100);
4489 emitcode ("mov","ma,b");
4490 emitcode ("mov","ma,a");
4492 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4493 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4496 /* load up MB with right */
4498 if (AOP_TYPE(right) == AOP_LIT) {
4499 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4501 lbl = newiTempLabel(NULL);
4502 emitcode ("jbc","F0,%05d$",lbl->key+100);
4503 emitcode("setb","F0");
4504 emitcode ("","%05d$:",lbl->key+100);
4507 emitcode ("mov","mb,#0x%02x",val & 0xff);
4508 emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4510 lbl = newiTempLabel(NULL);
4511 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4512 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4513 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4514 emitcode ("xch", "a,b");
4515 emitcode ("cpl","a");
4516 emitcode ("add", "a,#1");
4517 emitcode ("xch", "a,b");
4518 emitcode ("cpl", "a"); // msb
4519 emitcode ("addc", "a,#0");
4520 emitcode ("jbc","F0,%05d$",lbl->key+100);
4521 emitcode ("setb","F0");
4522 emitcode ("","%05d$:",lbl->key+100);
4523 emitcode ("mov","mb,b");
4524 emitcode ("mov","mb,a");
4527 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4528 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4531 /* wait for multiplication to finish */
4532 lbl = newiTempLabel(NULL);
4533 emitcode("","%05d$:", lbl->key+100);
4534 emitcode("mov","a,mcnt1");
4535 emitcode("anl","a,#0x80");
4536 emitcode("jnz","%05d$",lbl->key+100);
4538 freeAsmop (left, NULL, ic, TRUE);
4539 freeAsmop (right, NULL, ic,TRUE);
4540 aopOp(result, ic, TRUE, FALSE);
4542 /* if unsigned then simple */
4544 aopPut(AOP(result),"ma",1);
4545 aopPut(AOP(result),"ma",0);
4547 emitcode("push","ma");
4549 /* negate result if needed */
4550 lbl = newiTempLabel(NULL);
4551 emitcode("jnb","F0,%05d$",lbl->key+100);
4552 emitcode("cpl","a");
4553 emitcode("add","a,#1");
4554 emitcode("","%05d$:", lbl->key+100);
4555 aopPut(AOP(result),"a",0);
4556 emitcode("pop","acc");
4557 lbl = newiTempLabel(NULL);
4558 emitcode("jnb","F0,%05d$",lbl->key+100);
4559 emitcode("cpl","a");
4560 emitcode("addc","a,#0");
4561 emitcode("","%05d$:", lbl->key+100);
4562 aopPut(AOP(result),"a",1);
4564 freeAsmop (result, NULL, ic, TRUE);
4565 /* restore EA bit in F1 */
4566 lbl = newiTempLabel(NULL);
4567 emitcode ("jnb","F1,%05d$",lbl->key+100);
4568 emitcode ("setb","EA");
4569 emitcode("","%05d$:",lbl->key+100);
4573 /*-----------------------------------------------------------------*/
4574 /* genDiv - generates code for division */
4575 /*-----------------------------------------------------------------*/
4579 operand *left = IC_LEFT (ic);
4580 operand *right = IC_RIGHT (ic);
4581 operand *result = IC_RESULT (ic);
4583 D (emitcode (";", "genDiv "););
4585 /* assign the amsops */
4588 /* special cases first */
4590 if (AOP_TYPE (left) == AOP_CRY &&
4591 AOP_TYPE (right) == AOP_CRY)
4593 genDivbits (left, right, result, ic);
4597 /* if both are of size == 1 */
4598 if (AOP_SIZE (left) == 1 &&
4599 AOP_SIZE (right) == 1)
4601 genDivOneByte (left, right, result, ic);
4605 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4606 /* use the ds390 ARITHMETIC accel UNIT */
4607 genDivTwoByte (left, right, result, ic);
4610 /* should have been converted to function call */
4613 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4614 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4615 freeAsmop (result, NULL, ic, TRUE);
4618 /*-----------------------------------------------------------------*/
4619 /* genModbits :- modulus of bits */
4620 /*-----------------------------------------------------------------*/
4622 genModbits (operand * left,
4630 /* the result must be bit */
4631 LOAD_AB_FOR_DIV (left, right, l);
4632 emitcode ("div", "ab");
4633 emitcode ("mov", "a,b");
4634 emitcode ("rrc", "a");
4635 aopOp(result, ic, TRUE, FALSE);
4636 aopPut (AOP (result), "c", 0);
4639 /*-----------------------------------------------------------------*/
4640 /* genModOneByte : 8 bit modulus */
4641 /*-----------------------------------------------------------------*/
4643 genModOneByte (operand * left,
4648 sym_link *opetype = operandType (result);
4652 /* signed or unsigned */
4653 if (SPEC_USIGN (opetype))
4655 /* unsigned is easy */
4656 LOAD_AB_FOR_DIV (left, right, l);
4657 emitcode ("div", "ab");
4658 aopOp(result, ic, TRUE, FALSE);
4659 aopPut (AOP (result), "b", 0);
4663 /* signed is a little bit more difficult */
4665 /* save the signs of the operands */
4666 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4669 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4670 emitcode ("push", "acc"); /* save it on the stack */
4672 /* now sign adjust for both left & right */
4673 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4676 lbl = newiTempLabel (NULL);
4677 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4678 emitcode ("cpl", "a");
4679 emitcode ("inc", "a");
4680 emitcode ("", "%05d$:", (lbl->key + 100));
4681 emitcode ("mov", "b,a");
4683 /* sign adjust left side */
4684 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4687 lbl = newiTempLabel (NULL);
4688 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4689 emitcode ("cpl", "a");
4690 emitcode ("inc", "a");
4691 emitcode ("", "%05d$:", (lbl->key + 100));
4693 /* now the multiplication */
4694 emitcode ("nop", "; workaround for DS80C390 div bug.");
4695 emitcode ("div", "ab");
4696 /* we are interested in the lower order
4698 lbl = newiTempLabel (NULL);
4699 emitcode ("pop", "acc");
4700 /* if there was an over flow we don't
4701 adjust the sign of the result */
4702 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4703 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4705 emitcode ("clr", "a");
4706 emitcode ("subb", "a,b");
4707 emitcode ("mov", "b,a");
4708 emitcode ("", "%05d$:", (lbl->key + 100));
4710 /* now we are done */
4711 aopOp(result, ic, TRUE, FALSE);
4712 aopPut (AOP (result), "b", 0);
4716 /*-----------------------------------------------------------------*/
4717 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
4718 /*-----------------------------------------------------------------*/
4719 static void genModTwoByte (operand *left, operand *right,
4720 operand *result, iCode *ic)
4722 sym_link *retype = getSpec(operandType(right));
4723 sym_link *letype = getSpec(operandType(left));
4724 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4727 /* load up MA with left */
4728 /* save EA bit in F1 */
4729 lbl = newiTempLabel(NULL);
4730 emitcode ("setb","F1");
4731 emitcode ("jbc","EA,%05d$",lbl->key+100);
4732 emitcode ("clr","F1");
4733 emitcode("","%05d$:",lbl->key+100);
4736 lbl = newiTempLabel(NULL);
4737 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4738 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4739 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4740 emitcode ("xch", "a,b");
4741 emitcode ("cpl","a");
4742 emitcode ("add", "a,#1");
4743 emitcode ("xch", "a,b");
4744 emitcode ("cpl", "a"); // msb
4745 emitcode ("addc","a,#0");
4746 emitcode ("","%05d$:",lbl->key+100);
4747 emitcode ("mov","ma,b");
4748 emitcode ("mov","ma,a");
4750 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4751 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4754 /* load up MB with right */
4756 if (AOP_TYPE(right) == AOP_LIT) {
4757 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4761 emitcode ("mov","mb,#0x%02x",val & 0xff);
4762 emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4764 lbl = newiTempLabel(NULL);
4765 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4766 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4767 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4768 emitcode ("xch", "a,b");
4769 emitcode ("cpl","a");
4770 emitcode ("add", "a,#1");
4771 emitcode ("xch", "a,b");
4772 emitcode ("cpl", "a"); // msb
4773 emitcode ("addc", "a,#0");
4774 emitcode ("","%05d$:",lbl->key+100);
4775 emitcode ("mov","mb,b");
4776 emitcode ("mov","mb,a");
4779 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4780 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4783 /* wait for multiplication to finish */
4784 lbl = newiTempLabel(NULL);
4785 emitcode("","%05d$:", lbl->key+100);
4786 emitcode("mov","a,mcnt1");
4787 emitcode("anl","a,#0x80");
4788 emitcode("jnz","%05d$",lbl->key+100);
4790 freeAsmop (left, NULL, ic, TRUE);
4791 freeAsmop (right, NULL, ic,TRUE);
4792 aopOp(result, ic, TRUE, FALSE);
4794 aopPut(AOP(result),"mb",1);
4795 aopPut(AOP(result),"mb",0);
4796 freeAsmop (result, NULL, ic, TRUE);
4798 /* restore EA bit in F1 */
4799 lbl = newiTempLabel(NULL);
4800 emitcode ("jnb","F1,%05d$",lbl->key+100);
4801 emitcode ("setb","EA");
4802 emitcode("","%05d$:",lbl->key+100);
4806 /*-----------------------------------------------------------------*/
4807 /* genMod - generates code for division */
4808 /*-----------------------------------------------------------------*/
4812 operand *left = IC_LEFT (ic);
4813 operand *right = IC_RIGHT (ic);
4814 operand *result = IC_RESULT (ic);
4816 D (emitcode (";", "genMod "); );
4818 /* assign the amsops */
4821 /* special cases first */
4823 if (AOP_TYPE (left) == AOP_CRY &&
4824 AOP_TYPE (right) == AOP_CRY)
4826 genModbits (left, right, result, ic);
4830 /* if both are of size == 1 */
4831 if (AOP_SIZE (left) == 1 &&
4832 AOP_SIZE (right) == 1)
4834 genModOneByte (left, right, result, ic);
4838 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4839 /* use the ds390 ARITHMETIC accel UNIT */
4840 genModTwoByte (left, right, result, ic);
4844 /* should have been converted to function call */
4848 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4849 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4850 freeAsmop (result, NULL, ic, TRUE);
4853 /*-----------------------------------------------------------------*/
4854 /* genIfxJump :- will create a jump depending on the ifx */
4855 /*-----------------------------------------------------------------*/
4857 genIfxJump (iCode * ic, char *jval)
4860 symbol *tlbl = newiTempLabel (NULL);
4863 D (emitcode (";", "genIfxJump ");
4866 /* if true label then we jump if condition
4870 jlbl = IC_TRUE (ic);
4871 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4872 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4876 /* false label is present */
4877 jlbl = IC_FALSE (ic);
4878 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4879 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4881 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4882 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4884 emitcode (inst, "%05d$", tlbl->key + 100);
4885 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4886 emitcode ("", "%05d$:", tlbl->key + 100);
4888 /* mark the icode as generated */
4892 /*-----------------------------------------------------------------*/
4893 /* genCmp :- greater or less than comparison */
4894 /*-----------------------------------------------------------------*/
4896 genCmp (operand * left, operand * right,
4897 iCode * ic, iCode * ifx, int sign)
4899 int size, offset = 0;
4900 unsigned long lit = 0L;
4903 D (emitcode (";", "genCmp");
4906 result = IC_RESULT (ic);
4908 /* if left & right are bit variables */
4909 if (AOP_TYPE (left) == AOP_CRY &&
4910 AOP_TYPE (right) == AOP_CRY)
4912 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4913 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4917 /* subtract right from left if at the
4918 end the carry flag is set then we know that
4919 left is greater than right */
4920 size = max (AOP_SIZE (left), AOP_SIZE (right));
4922 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4923 if ((size == 1) && !sign &&
4924 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4926 symbol *lbl = newiTempLabel (NULL);
4927 emitcode ("cjne", "%s,%s,%05d$",
4928 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4929 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4931 emitcode ("", "%05d$:", lbl->key + 100);
4935 if (AOP_TYPE (right) == AOP_LIT)
4937 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4938 /* optimize if(x < 0) or if(x >= 0) */
4947 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4949 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4950 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4952 aopOp (result, ic, FALSE, FALSE);
4954 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4956 freeAsmop (result, NULL, ic, TRUE);
4957 genIfxJump (ifx, "acc.7");
4962 emitcode ("rlc", "a");
4964 goto release_freedLR;
4972 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4973 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4974 emitcode (";", "genCmp #2");
4975 if (sign && (size == 0))
4977 emitcode (";", "genCmp #3");
4978 emitcode ("xrl", "a,#0x80");
4979 if (AOP_TYPE (right) == AOP_LIT)
4981 unsigned long lit = (unsigned long)
4982 floatFromVal (AOP (right)->aopu.aop_lit);
4983 emitcode (";", "genCmp #3.1");
4984 emitcode ("subb", "a,#0x%02x",
4985 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4989 emitcode (";", "genCmp #3.2");
4990 if (AOP_NEEDSACC (right))
4992 emitcode ("push", "acc");
4994 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4995 FALSE, FALSE, FALSE));
4996 emitcode ("xrl", "b,#0x80");
4997 if (AOP_NEEDSACC (right))
4999 emitcode ("pop", "acc");
5001 emitcode ("subb", "a,b");
5008 emitcode (";", "genCmp #4");
5009 if (AOP_NEEDSACC (right))
5012 emitcode (";", "genCmp #4.1");
5013 emitcode ("xch", "a, b");
5014 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
5015 emitcode ("xch", "a, b");
5020 emitcode (";", "genCmp #4.2");
5021 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
5024 emitcode ("subb", "a,%s", s);
5031 /* Don't need the left & right operands any more; do need the result. */
5032 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5033 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5035 aopOp (result, ic, FALSE, FALSE);
5039 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5045 /* if the result is used in the next
5046 ifx conditional branch then generate
5047 code a little differently */
5050 genIfxJump (ifx, "c");
5056 /* leave the result in acc */
5058 freeAsmop (result, NULL, ic, TRUE);
5061 /*-----------------------------------------------------------------*/
5062 /* genCmpGt :- greater than comparison */
5063 /*-----------------------------------------------------------------*/
5065 genCmpGt (iCode * ic, iCode * ifx)
5067 operand *left, *right;
5068 sym_link *letype, *retype;
5071 D (emitcode (";", "genCmpGt ");
5074 left = IC_LEFT (ic);
5075 right = IC_RIGHT (ic);
5077 letype = getSpec (operandType (left));
5078 retype = getSpec (operandType (right));
5079 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5081 /* assign the left & right amsops */
5084 genCmp (right, left, ic, ifx, sign);
5087 /*-----------------------------------------------------------------*/
5088 /* genCmpLt - less than comparisons */
5089 /*-----------------------------------------------------------------*/
5091 genCmpLt (iCode * ic, iCode * ifx)
5093 operand *left, *right;
5094 sym_link *letype, *retype;
5097 D (emitcode (";", "genCmpLt "););
5099 left = IC_LEFT (ic);
5100 right = IC_RIGHT (ic);
5102 letype = getSpec (operandType (left));
5103 retype = getSpec (operandType (right));
5104 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5106 /* assign the left & right amsops */
5109 genCmp (left, right, ic, ifx, sign);
5112 /*-----------------------------------------------------------------*/
5113 /* gencjneshort - compare and jump if not equal */
5114 /*-----------------------------------------------------------------*/
5116 gencjneshort (operand * left, operand * right, symbol * lbl)
5118 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5120 unsigned long lit = 0L;
5122 D (emitcode (";", "gencjneshort");
5125 /* if the left side is a literal or
5126 if the right is in a pointer register and left
5128 if ((AOP_TYPE (left) == AOP_LIT) ||
5129 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5136 if (AOP_TYPE (right) == AOP_LIT)
5137 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5139 if (opIsGptr (left) || opIsGptr (right))
5141 /* We are comparing a generic pointer to something.
5142 * Exclude the generic type byte from the comparison.
5145 D (emitcode (";", "cjneshort: generic ptr special case.");
5150 /* if the right side is a literal then anything goes */
5151 if (AOP_TYPE (right) == AOP_LIT &&
5152 AOP_TYPE (left) != AOP_DIR)
5156 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5158 emitcode ("cjne", "a,%s,%05d$",
5159 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5165 /* if the right side is in a register or in direct space or
5166 if the left is a pointer register & right is not */
5167 else if (AOP_TYPE (right) == AOP_REG ||
5168 AOP_TYPE (right) == AOP_DIR ||
5169 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5170 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5174 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5175 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5176 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5177 emitcode ("jnz", "%05d$", lbl->key + 100);
5179 emitcode ("cjne", "a,%s,%05d$",
5180 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5187 /* right is a pointer reg need both a & b */
5190 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5191 if (strcmp (l, "b"))
5192 emitcode ("mov", "b,%s", l);
5193 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5194 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5200 /*-----------------------------------------------------------------*/
5201 /* gencjne - compare and jump if not equal */
5202 /*-----------------------------------------------------------------*/
5204 gencjne (operand * left, operand * right, symbol * lbl)
5206 symbol *tlbl = newiTempLabel (NULL);
5208 D (emitcode (";", "gencjne");
5211 gencjneshort (left, right, lbl);
5213 emitcode ("mov", "a,%s", one);
5214 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5215 emitcode ("", "%05d$:", lbl->key + 100);
5216 emitcode ("clr", "a");
5217 emitcode ("", "%05d$:", tlbl->key + 100);
5220 /*-----------------------------------------------------------------*/
5221 /* genCmpEq - generates code for equal to */
5222 /*-----------------------------------------------------------------*/
5224 genCmpEq (iCode * ic, iCode * ifx)
5226 operand *left, *right, *result;
5228 D (emitcode (";", "genCmpEq ");
5232 AOP_SET_LOCALS (ic);
5234 /* if literal, literal on the right or
5235 if the right is in a pointer register and left
5237 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5238 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5240 operand *t = IC_RIGHT (ic);
5241 IC_RIGHT (ic) = IC_LEFT (ic);
5245 if (ifx && /* !AOP_SIZE(result) */
5246 OP_SYMBOL (result) &&
5247 OP_SYMBOL (result)->regType == REG_CND)
5250 /* if they are both bit variables */
5251 if (AOP_TYPE (left) == AOP_CRY &&
5252 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5254 if (AOP_TYPE (right) == AOP_LIT)
5256 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5259 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5260 emitcode ("cpl", "c");
5264 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5268 emitcode ("clr", "c");
5270 /* AOP_TYPE(right) == AOP_CRY */
5274 symbol *lbl = newiTempLabel (NULL);
5275 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5276 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5277 emitcode ("cpl", "c");
5278 emitcode ("", "%05d$:", (lbl->key + 100));
5280 /* if true label then we jump if condition
5282 tlbl = newiTempLabel (NULL);
5285 emitcode ("jnc", "%05d$", tlbl->key + 100);
5286 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5290 emitcode ("jc", "%05d$", tlbl->key + 100);
5291 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5293 emitcode ("", "%05d$:", tlbl->key + 100);
5297 tlbl = newiTempLabel (NULL);
5298 gencjneshort (left, right, tlbl);
5301 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5302 emitcode ("", "%05d$:", tlbl->key + 100);
5306 symbol *lbl = newiTempLabel (NULL);
5307 emitcode ("sjmp", "%05d$", lbl->key + 100);
5308 emitcode ("", "%05d$:", tlbl->key + 100);
5309 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5310 emitcode ("", "%05d$:", lbl->key + 100);
5313 /* mark the icode as generated */
5316 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5317 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5321 /* if they are both bit variables */
5322 if (AOP_TYPE (left) == AOP_CRY &&
5323 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5325 if (AOP_TYPE (right) == AOP_LIT)
5327 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5330 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5331 emitcode ("cpl", "c");
5335 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5339 emitcode ("clr", "c");
5341 /* AOP_TYPE(right) == AOP_CRY */
5345 symbol *lbl = newiTempLabel (NULL);
5346 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5347 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5348 emitcode ("cpl", "c");
5349 emitcode ("", "%05d$:", (lbl->key + 100));
5352 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5353 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5355 aopOp (result, ic, TRUE, FALSE);
5358 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5365 genIfxJump (ifx, "c");
5368 /* if the result is used in an arithmetic operation
5369 then put the result in place */
5374 gencjne (left, right, newiTempLabel (NULL));
5376 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5377 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5379 aopOp (result, ic, TRUE, FALSE);
5381 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5383 aopPut (AOP (result), "a", 0);
5388 genIfxJump (ifx, "a");
5391 /* if the result is used in an arithmetic operation
5392 then put the result in place */
5393 if (AOP_TYPE (result) != AOP_CRY)
5395 /* leave the result in acc */
5399 freeAsmop (result, NULL, ic, TRUE);
5402 /*-----------------------------------------------------------------*/
5403 /* ifxForOp - returns the icode containing the ifx for operand */
5404 /*-----------------------------------------------------------------*/
5406 ifxForOp (operand * op, iCode * ic)
5408 /* if true symbol then needs to be assigned */
5409 if (IS_TRUE_SYMOP (op))
5412 /* if this has register type condition and
5413 the next instruction is ifx with the same operand
5414 and live to of the operand is upto the ifx only then */
5416 ic->next->op == IFX &&
5417 IC_COND (ic->next)->key == op->key &&
5418 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5423 /*-----------------------------------------------------------------*/
5424 /* hasInc - operand is incremented before any other use */
5425 /*-----------------------------------------------------------------*/
5427 hasInc (operand *op, iCode *ic)
5429 sym_link *type = operandType(op);
5430 sym_link *retype = getSpec (type);
5431 iCode *lic = ic->next;
5434 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5435 if (!IS_SYMOP(op)) return NULL;
5437 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5438 isize = getSize(type->next);
5440 /* if operand of the form op = op + <sizeof *op> */
5441 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5442 isOperandEqual(IC_RESULT(lic),op) &&
5443 isOperandLiteral(IC_RIGHT(lic)) &&
5444 operandLitValue(IC_RIGHT(lic)) == isize) {
5447 /* if the operand used or deffed */
5448 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5451 /* if GOTO or IFX */
5452 if (lic->op == IFX || lic->op == GOTO) break;
5458 /*-----------------------------------------------------------------*/
5459 /* genAndOp - for && operation */
5460 /*-----------------------------------------------------------------*/
5462 genAndOp (iCode * ic)
5464 operand *left, *right, *result;
5467 D (emitcode (";", "genAndOp "););
5469 /* note here that && operations that are in an
5470 if statement are taken away by backPatchLabels
5471 only those used in arthmetic operations remain */
5473 AOP_SET_LOCALS (ic);
5475 /* if both are bit variables */
5476 if (AOP_TYPE (left) == AOP_CRY &&
5477 AOP_TYPE (right) == AOP_CRY)
5479 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5480 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5481 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5482 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5484 aopOp (result,ic,FALSE, FALSE);
5489 tlbl = newiTempLabel (NULL);
5491 emitcode ("jz", "%05d$", tlbl->key + 100);
5493 emitcode ("", "%05d$:", tlbl->key + 100);
5494 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5495 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5497 aopOp (result,ic,FALSE, FALSE);
5500 freeAsmop (result, NULL, ic, TRUE);
5504 /*-----------------------------------------------------------------*/
5505 /* genOrOp - for || operation */
5506 /*-----------------------------------------------------------------*/
5508 genOrOp (iCode * ic)
5510 operand *left, *right, *result;
5513 D (emitcode (";", "genOrOp "););
5515 /* note here that || operations that are in an
5516 if statement are taken away by backPatchLabels
5517 only those used in arthmetic operations remain */
5519 AOP_SET_LOCALS (ic);
5521 /* if both are bit variables */
5522 if (AOP_TYPE (left) == AOP_CRY &&
5523 AOP_TYPE (right) == AOP_CRY)
5525 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5526 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5527 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5528 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5530 aopOp (result,ic,FALSE, FALSE);
5536 tlbl = newiTempLabel (NULL);
5538 emitcode ("jnz", "%05d$", tlbl->key + 100);
5540 emitcode ("", "%05d$:", tlbl->key + 100);
5541 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5542 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5544 aopOp (result,ic,FALSE, FALSE);
5549 freeAsmop (result, NULL, ic, TRUE);
5552 /*-----------------------------------------------------------------*/
5553 /* isLiteralBit - test if lit == 2^n */
5554 /*-----------------------------------------------------------------*/
5556 isLiteralBit (unsigned long lit)
5558 unsigned long pw[32] =
5559 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5560 0x100L, 0x200L, 0x400L, 0x800L,
5561 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5562 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5563 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5564 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5565 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5568 for (idx = 0; idx < 32; idx++)
5574 /*-----------------------------------------------------------------*/
5575 /* continueIfTrue - */
5576 /*-----------------------------------------------------------------*/
5578 continueIfTrue (iCode * ic)
5581 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5585 /*-----------------------------------------------------------------*/
5587 /*-----------------------------------------------------------------*/
5589 jumpIfTrue (iCode * ic)
5592 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5596 /*-----------------------------------------------------------------*/
5597 /* jmpTrueOrFalse - */
5598 /*-----------------------------------------------------------------*/
5600 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5602 // ugly but optimized by peephole
5605 symbol *nlbl = newiTempLabel (NULL);
5606 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5607 emitcode ("", "%05d$:", tlbl->key + 100);
5608 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5609 emitcode ("", "%05d$:", nlbl->key + 100);
5613 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5614 emitcode ("", "%05d$:", tlbl->key + 100);
5619 // Generate code to perform a bit-wise logic operation
5620 // on two operands in far space (assumed to already have been
5621 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5622 // in far space. This requires pushing the result on the stack
5623 // then popping it into the result.
5625 genFarFarLogicOp(iCode *ic, char *logicOp)
5627 int size, resultSize, compSize;
5631 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5632 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5633 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5635 _startLazyDPSEvaluation();
5636 for (size = compSize; (size--); offset++)
5638 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5639 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5640 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5642 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5643 emitcode ("push", "acc");
5645 _endLazyDPSEvaluation();
5647 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5648 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5649 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5651 resultSize = AOP_SIZE(IC_RESULT(ic));
5653 ADJUST_PUSHED_RESULT(compSize, resultSize);
5655 _startLazyDPSEvaluation();
5658 emitcode ("pop", "acc");
5659 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5661 _endLazyDPSEvaluation();
5662 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5666 /*-----------------------------------------------------------------*/
5667 /* genAnd - code for and */
5668 /*-----------------------------------------------------------------*/
5670 genAnd (iCode * ic, iCode * ifx)
5672 operand *left, *right, *result;
5673 int size, offset = 0;
5674 unsigned long lit = 0L;
5679 D (emitcode (";", "genAnd "););
5681 AOP_OP_3_NOFATAL (ic, pushResult);
5682 AOP_SET_LOCALS (ic);
5686 genFarFarLogicOp(ic, "anl");
5691 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5693 AOP_TYPE (left), AOP_TYPE (right));
5694 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5696 AOP_SIZE (left), AOP_SIZE (right));
5699 /* if left is a literal & right is not then exchange them */
5700 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5701 #ifdef LOGIC_OPS_BROKEN
5702 || AOP_NEEDSACC (left)
5706 operand *tmp = right;
5711 /* if result = right then exchange them */
5712 if (sameRegs (AOP (result), AOP (right)))
5714 operand *tmp = right;
5719 /* if right is bit then exchange them */
5720 if (AOP_TYPE (right) == AOP_CRY &&
5721 AOP_TYPE (left) != AOP_CRY)
5723 operand *tmp = right;
5727 if (AOP_TYPE (right) == AOP_LIT)
5728 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5730 size = AOP_SIZE (result);
5733 // result = bit & yy;
5734 if (AOP_TYPE (left) == AOP_CRY)
5736 // c = bit & literal;
5737 if (AOP_TYPE (right) == AOP_LIT)
5741 if (size && sameRegs (AOP (result), AOP (left)))
5744 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5749 if (size && (AOP_TYPE (result) == AOP_CRY))
5751 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5754 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5759 emitcode ("clr", "c");
5764 if (AOP_TYPE (right) == AOP_CRY)
5767 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5768 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5773 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5775 emitcode ("rrc", "a");
5776 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5784 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5785 genIfxJump (ifx, "c");
5789 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5790 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5791 if ((AOP_TYPE (right) == AOP_LIT) &&
5792 (AOP_TYPE (result) == AOP_CRY) &&
5793 (AOP_TYPE (left) != AOP_CRY))
5795 int posbit = isLiteralBit (lit);
5800 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5803 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5809 sprintf (buffer, "acc.%d", posbit & 0x07);
5810 genIfxJump (ifx, buffer);
5817 symbol *tlbl = newiTempLabel (NULL);
5818 int sizel = AOP_SIZE (left);
5820 emitcode ("setb", "c");
5823 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5825 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5827 if ((posbit = isLiteralBit (bytelit)) != 0)
5828 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5831 if (bytelit != 0x0FFL)
5832 emitcode ("anl", "a,%s",
5833 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5834 emitcode ("jnz", "%05d$", tlbl->key + 100);
5839 // bit = left & literal
5842 emitcode ("clr", "c");
5843 emitcode ("", "%05d$:", tlbl->key + 100);
5845 // if(left & literal)
5849 jmpTrueOrFalse (ifx, tlbl);
5857 /* if left is same as result */
5858 if (sameRegs (AOP (result), AOP (left)))
5860 for (; size--; offset++)
5862 if (AOP_TYPE (right) == AOP_LIT)
5864 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5866 else if (bytelit == 0)
5867 aopPut (AOP (result), zero, offset);
5868 else if (IS_AOP_PREG (result))
5870 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5871 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5872 aopPut (AOP (result), "a", offset);
5875 emitcode ("anl", "%s,%s",
5876 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5877 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5881 if (AOP_TYPE (left) == AOP_ACC)
5882 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5885 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5886 if (IS_AOP_PREG (result))
5888 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5889 aopPut (AOP (result), "a", offset);
5893 emitcode ("anl", "%s,a",
5894 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5901 // left & result in different registers
5902 if (AOP_TYPE (result) == AOP_CRY)
5905 // if(size), result in bit
5906 // if(!size && ifx), conditional oper: if(left & right)
5907 symbol *tlbl = newiTempLabel (NULL);
5908 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5910 emitcode ("setb", "c");
5913 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5914 emitcode ("anl", "a,%s",
5915 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5917 if (AOP_TYPE(left)==AOP_ACC) {
5918 emitcode("mov", "b,a");
5919 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5920 emitcode("anl", "a,b");
5922 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5923 emitcode ("anl", "a,%s",
5924 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5927 emitcode ("jnz", "%05d$", tlbl->key + 100);
5933 emitcode ("", "%05d$:", tlbl->key + 100);
5937 jmpTrueOrFalse (ifx, tlbl);
5941 for (; (size--); offset++)
5944 // result = left & right
5945 if (AOP_TYPE (right) == AOP_LIT)
5947 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5949 aopPut (AOP (result),
5950 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5954 else if (bytelit == 0)
5956 aopPut (AOP (result), zero, offset);
5959 D (emitcode (";", "better literal AND."););
5960 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5961 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5962 FALSE, FALSE, FALSE));
5967 // faster than result <- left, anl result,right
5968 // and better if result is SFR
5969 if (AOP_TYPE (left) == AOP_ACC)
5971 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5972 FALSE, FALSE, FALSE));
5976 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
5977 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
5979 emitcode("mov", "b,a");
5983 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5984 emitcode ("anl", "a,%s", rOp);
5987 aopPut (AOP (result), "a", offset);
5993 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5994 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5995 freeAsmop (result, NULL, ic, TRUE);
5999 /*-----------------------------------------------------------------*/
6000 /* genOr - code for or */
6001 /*-----------------------------------------------------------------*/
6003 genOr (iCode * ic, iCode * ifx)
6005 operand *left, *right, *result;
6006 int size, offset = 0;
6007 unsigned long lit = 0L;
6010 D (emitcode (";", "genOr "););
6012 AOP_OP_3_NOFATAL (ic, pushResult);
6013 AOP_SET_LOCALS (ic);
6017 genFarFarLogicOp(ic, "orl");
6023 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6025 AOP_TYPE (left), AOP_TYPE (right));
6026 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6028 AOP_SIZE (left), AOP_SIZE (right));
6031 /* if left is a literal & right is not then exchange them */
6032 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6033 #ifdef LOGIC_OPS_BROKEN
6034 || AOP_NEEDSACC (left) // I think this is a net loss now.
6038 operand *tmp = right;
6043 /* if result = right then exchange them */
6044 if (sameRegs (AOP (result), AOP (right)))
6046 operand *tmp = right;
6051 /* if right is bit then exchange them */
6052 if (AOP_TYPE (right) == AOP_CRY &&
6053 AOP_TYPE (left) != AOP_CRY)
6055 operand *tmp = right;
6059 if (AOP_TYPE (right) == AOP_LIT)
6060 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6062 size = AOP_SIZE (result);
6066 if (AOP_TYPE (left) == AOP_CRY)
6068 if (AOP_TYPE (right) == AOP_LIT)
6070 // c = bit & literal;
6073 // lit != 0 => result = 1
6074 if (AOP_TYPE (result) == AOP_CRY)
6077 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6079 continueIfTrue (ifx);
6082 emitcode ("setb", "c");
6086 // lit == 0 => result = left
6087 if (size && sameRegs (AOP (result), AOP (left)))
6089 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6094 if (AOP_TYPE (right) == AOP_CRY)
6097 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6098 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6103 symbol *tlbl = newiTempLabel (NULL);
6104 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6105 emitcode ("setb", "c");
6106 emitcode ("jb", "%s,%05d$",
6107 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6109 emitcode ("jnz", "%05d$", tlbl->key + 100);
6110 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6112 jmpTrueOrFalse (ifx, tlbl);
6118 emitcode ("", "%05d$:", tlbl->key + 100);
6127 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6128 genIfxJump (ifx, "c");
6132 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6133 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6134 if ((AOP_TYPE (right) == AOP_LIT) &&
6135 (AOP_TYPE (result) == AOP_CRY) &&
6136 (AOP_TYPE (left) != AOP_CRY))
6142 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6144 continueIfTrue (ifx);
6149 // lit = 0, result = boolean(left)
6151 emitcode ("setb", "c");
6155 symbol *tlbl = newiTempLabel (NULL);
6156 emitcode ("jnz", "%05d$", tlbl->key + 100);
6158 emitcode ("", "%05d$:", tlbl->key + 100);
6162 genIfxJump (ifx, "a");
6170 /* if left is same as result */
6171 if (sameRegs (AOP (result), AOP (left)))
6173 for (; size--; offset++)
6175 if (AOP_TYPE (right) == AOP_LIT)
6177 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6183 if (IS_AOP_PREG (left))
6185 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6186 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6187 aopPut (AOP (result), "a", offset);
6191 emitcode ("orl", "%s,%s",
6192 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6193 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6199 if (AOP_TYPE (left) == AOP_ACC)
6201 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6205 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6206 if (IS_AOP_PREG (left))
6208 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6209 aopPut (AOP (result), "a", offset);
6213 emitcode ("orl", "%s,a",
6214 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6222 // left & result in different registers
6223 if (AOP_TYPE (result) == AOP_CRY)
6226 // if(size), result in bit
6227 // if(!size && ifx), conditional oper: if(left | right)
6228 symbol *tlbl = newiTempLabel (NULL);
6229 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6231 emitcode ("setb", "c");
6234 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6235 emitcode ("orl", "a,%s",
6236 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6238 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6239 emitcode ("orl", "a,%s",
6240 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6242 emitcode ("jnz", "%05d$", tlbl->key + 100);
6248 emitcode ("", "%05d$:", tlbl->key + 100);
6252 jmpTrueOrFalse (ifx, tlbl);
6256 _startLazyDPSEvaluation();
6257 for (; (size--); offset++)
6260 // result = left & right
6261 if (AOP_TYPE (right) == AOP_LIT)
6263 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6265 aopPut (AOP (result),
6266 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6270 D (emitcode (";", "better literal OR."););
6271 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6272 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6273 FALSE, FALSE, FALSE));
6278 // faster than result <- left, anl result,right
6279 // and better if result is SFR
6280 if (AOP_TYPE (left) == AOP_ACC)
6282 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6283 FALSE, FALSE, FALSE));
6287 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6289 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6291 emitcode("mov", "b,a");
6295 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6296 emitcode ("orl", "a,%s", rOp);
6299 aopPut (AOP (result), "a", offset);
6301 _endLazyDPSEvaluation();
6306 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6307 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6308 freeAsmop (result, NULL, ic, TRUE);
6311 /*-----------------------------------------------------------------*/
6312 /* genXor - code for xclusive or */
6313 /*-----------------------------------------------------------------*/
6315 genXor (iCode * ic, iCode * ifx)
6317 operand *left, *right, *result;
6318 int size, offset = 0;
6319 unsigned long lit = 0L;
6322 D (emitcode (";", "genXor "););
6324 AOP_OP_3_NOFATAL (ic, pushResult);
6325 AOP_SET_LOCALS (ic);
6329 genFarFarLogicOp(ic, "xrl");
6334 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6336 AOP_TYPE (left), AOP_TYPE (right));
6337 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6339 AOP_SIZE (left), AOP_SIZE (right));
6342 /* if left is a literal & right is not ||
6343 if left needs acc & right does not */
6344 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6345 #ifdef LOGIC_OPS_BROKEN
6346 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6350 operand *tmp = right;
6355 /* if result = right then exchange them */
6356 if (sameRegs (AOP (result), AOP (right)))
6358 operand *tmp = right;
6363 /* if right is bit then exchange them */
6364 if (AOP_TYPE (right) == AOP_CRY &&
6365 AOP_TYPE (left) != AOP_CRY)
6367 operand *tmp = right;
6371 if (AOP_TYPE (right) == AOP_LIT)
6372 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6374 size = AOP_SIZE (result);
6378 if (AOP_TYPE (left) == AOP_CRY)
6380 if (AOP_TYPE (right) == AOP_LIT)
6382 // c = bit & literal;
6385 // lit>>1 != 0 => result = 1
6386 if (AOP_TYPE (result) == AOP_CRY)
6389 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6391 continueIfTrue (ifx);
6394 emitcode ("setb", "c");
6401 // lit == 0, result = left
6402 if (size && sameRegs (AOP (result), AOP (left)))
6404 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6408 // lit == 1, result = not(left)
6409 if (size && sameRegs (AOP (result), AOP (left)))
6411 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6416 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6417 emitcode ("cpl", "c");
6426 symbol *tlbl = newiTempLabel (NULL);
6427 if (AOP_TYPE (right) == AOP_CRY)
6430 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6434 int sizer = AOP_SIZE (right);
6436 // if val>>1 != 0, result = 1
6437 emitcode ("setb", "c");
6440 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6442 // test the msb of the lsb
6443 emitcode ("anl", "a,#0xfe");
6444 emitcode ("jnz", "%05d$", tlbl->key + 100);
6448 emitcode ("rrc", "a");
6450 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6451 emitcode ("cpl", "c");
6452 emitcode ("", "%05d$:", (tlbl->key + 100));
6459 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6460 genIfxJump (ifx, "c");
6464 if (sameRegs (AOP (result), AOP (left)))
6466 /* if left is same as result */
6467 for (; size--; offset++)
6469 if (AOP_TYPE (right) == AOP_LIT)
6471 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6473 else if (IS_AOP_PREG (left))
6475 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6476 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6477 aopPut (AOP (result), "a", offset);
6480 emitcode ("xrl", "%s,%s",
6481 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6482 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6486 if (AOP_TYPE (left) == AOP_ACC)
6487 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6490 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6491 if (IS_AOP_PREG (left))
6493 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6494 aopPut (AOP (result), "a", offset);
6497 emitcode ("xrl", "%s,a",
6498 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6505 // left & result in different registers
6506 if (AOP_TYPE (result) == AOP_CRY)
6509 // if(size), result in bit
6510 // if(!size && ifx), conditional oper: if(left ^ right)
6511 symbol *tlbl = newiTempLabel (NULL);
6512 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6515 emitcode ("setb", "c");
6518 if ((AOP_TYPE (right) == AOP_LIT) &&
6519 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6521 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6525 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6526 emitcode ("xrl", "a,%s",
6527 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6529 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6530 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6532 emitcode("mov", "b,a");
6536 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6537 emitcode ("xrl", "a,%s", rOp);
6540 emitcode ("jnz", "%05d$", tlbl->key + 100);
6546 emitcode ("", "%05d$:", tlbl->key + 100);
6550 jmpTrueOrFalse (ifx, tlbl);
6554 for (; (size--); offset++)
6557 // result = left & right
6558 if (AOP_TYPE (right) == AOP_LIT)
6560 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6562 aopPut (AOP (result),
6563 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6567 D (emitcode (";", "better literal XOR."););
6568 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6569 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6570 FALSE, FALSE, FALSE));
6574 // faster than result <- left, anl result,right
6575 // and better if result is SFR
6576 if (AOP_TYPE (left) == AOP_ACC)
6578 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6579 FALSE, FALSE, FALSE));
6583 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6584 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6586 emitcode("mov", "b,a");
6590 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6591 emitcode ("xrl", "a,%s", rOp);
6594 aopPut (AOP (result), "a", offset);
6601 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6602 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6603 freeAsmop (result, NULL, ic, TRUE);
6606 /*-----------------------------------------------------------------*/
6607 /* genInline - write the inline code out */
6608 /*-----------------------------------------------------------------*/
6610 genInline (iCode * ic)
6612 char *buffer, *bp, *bp1;
6614 D (emitcode (";", "genInline ");
6617 _G.inLine += (!options.asmpeep);
6619 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6620 strcpy (buffer, IC_INLINE (ic));
6622 /* emit each line as a code */
6647 /* emitcode("",buffer); */
6648 _G.inLine -= (!options.asmpeep);
6651 /*-----------------------------------------------------------------*/
6652 /* genRRC - rotate right with carry */
6653 /*-----------------------------------------------------------------*/
6657 operand *left, *result;
6658 int size, offset = 0;
6661 D (emitcode (";", "genRRC ");
6664 /* rotate right with carry */
6665 left = IC_LEFT (ic);
6666 result = IC_RESULT (ic);
6667 aopOp (left, ic, FALSE, FALSE);
6668 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6670 /* move it to the result */
6671 size = AOP_SIZE (result);
6675 _startLazyDPSEvaluation ();
6678 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6680 emitcode ("rrc", "a");
6681 if (AOP_SIZE (result) > 1)
6682 aopPut (AOP (result), "a", offset--);
6684 _endLazyDPSEvaluation ();
6686 /* now we need to put the carry into the
6687 highest order byte of the result */
6688 if (AOP_SIZE (result) > 1)
6690 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6693 emitcode ("mov", "acc.7,c");
6694 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6695 freeAsmop (left, NULL, ic, TRUE);
6696 freeAsmop (result, NULL, ic, TRUE);
6699 /*-----------------------------------------------------------------*/
6700 /* genRLC - generate code for rotate left with carry */
6701 /*-----------------------------------------------------------------*/
6705 operand *left, *result;
6706 int size, offset = 0;
6709 D (emitcode (";", "genRLC ");
6712 /* rotate right with carry */
6713 left = IC_LEFT (ic);
6714 result = IC_RESULT (ic);
6715 aopOp (left, ic, FALSE, FALSE);
6716 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6718 /* move it to the result */
6719 size = AOP_SIZE (result);
6723 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6725 emitcode ("add", "a,acc");
6726 if (AOP_SIZE (result) > 1)
6728 aopPut (AOP (result), "a", offset++);
6731 _startLazyDPSEvaluation ();
6734 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6736 emitcode ("rlc", "a");
6737 if (AOP_SIZE (result) > 1)
6738 aopPut (AOP (result), "a", offset++);
6740 _endLazyDPSEvaluation ();
6742 /* now we need to put the carry into the
6743 highest order byte of the result */
6744 if (AOP_SIZE (result) > 1)
6746 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6749 emitcode ("mov", "acc.0,c");
6750 aopPut (AOP (result), "a", 0);
6751 freeAsmop (left, NULL, ic, TRUE);
6752 freeAsmop (result, NULL, ic, TRUE);
6755 /*-----------------------------------------------------------------*/
6756 /* genGetHbit - generates code get highest order bit */
6757 /*-----------------------------------------------------------------*/
6759 genGetHbit (iCode * ic)
6761 operand *left, *result;
6762 left = IC_LEFT (ic);
6763 result = IC_RESULT (ic);
6764 aopOp (left, ic, FALSE, FALSE);
6765 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6767 D (emitcode (";", "genGetHbit ");
6770 /* get the highest order byte into a */
6771 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6772 if (AOP_TYPE (result) == AOP_CRY)
6774 emitcode ("rlc", "a");
6779 emitcode ("rl", "a");
6780 emitcode ("anl", "a,#0x01");
6785 freeAsmop (left, NULL, ic, TRUE);
6786 freeAsmop (result, NULL, ic, TRUE);
6789 /*-----------------------------------------------------------------*/
6790 /* AccRol - rotate left accumulator by known count */
6791 /*-----------------------------------------------------------------*/
6793 AccRol (int shCount)
6795 shCount &= 0x0007; // shCount : 0..7
6802 emitcode ("rl", "a");
6805 emitcode ("rl", "a");
6806 emitcode ("rl", "a");
6809 emitcode ("swap", "a");
6810 emitcode ("rr", "a");
6813 emitcode ("swap", "a");
6816 emitcode ("swap", "a");
6817 emitcode ("rl", "a");
6820 emitcode ("rr", "a");
6821 emitcode ("rr", "a");
6824 emitcode ("rr", "a");
6829 /*-----------------------------------------------------------------*/
6830 /* AccLsh - left shift accumulator by known count */
6831 /*-----------------------------------------------------------------*/
6833 AccLsh (int shCount)
6838 emitcode ("add", "a,acc");
6839 else if (shCount == 2)
6841 emitcode ("add", "a,acc");
6842 emitcode ("add", "a,acc");
6846 /* rotate left accumulator */
6848 /* and kill the lower order bits */
6849 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6854 /*-----------------------------------------------------------------*/
6855 /* AccRsh - right shift accumulator by known count */
6856 /*-----------------------------------------------------------------*/
6858 AccRsh (int shCount)
6865 emitcode ("rrc", "a");
6869 /* rotate right accumulator */
6870 AccRol (8 - shCount);
6871 /* and kill the higher order bits */
6872 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6877 #ifdef BETTER_LITERAL_SHIFT
6878 /*-----------------------------------------------------------------*/
6879 /* AccSRsh - signed right shift accumulator by known count */
6880 /*-----------------------------------------------------------------*/
6882 AccSRsh (int shCount)
6889 emitcode ("mov", "c,acc.7");
6890 emitcode ("rrc", "a");
6892 else if (shCount == 2)
6894 emitcode ("mov", "c,acc.7");
6895 emitcode ("rrc", "a");
6896 emitcode ("mov", "c,acc.7");
6897 emitcode ("rrc", "a");
6901 tlbl = newiTempLabel (NULL);
6902 /* rotate right accumulator */
6903 AccRol (8 - shCount);
6904 /* and kill the higher order bits */
6905 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6906 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6907 emitcode ("orl", "a,#0x%02x",
6908 (unsigned char) ~SRMask[shCount]);
6909 emitcode ("", "%05d$:", tlbl->key + 100);
6915 #ifdef BETTER_LITERAL_SHIFT
6916 /*-----------------------------------------------------------------*/
6917 /* shiftR1Left2Result - shift right one byte from left to result */
6918 /*-----------------------------------------------------------------*/
6920 shiftR1Left2Result (operand * left, int offl,
6921 operand * result, int offr,
6922 int shCount, int sign)
6924 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6925 /* shift right accumulator */
6930 aopPut (AOP (result), "a", offr);
6934 #ifdef BETTER_LITERAL_SHIFT
6935 /*-----------------------------------------------------------------*/
6936 /* shiftL1Left2Result - shift left one byte from left to result */
6937 /*-----------------------------------------------------------------*/
6939 shiftL1Left2Result (operand * left, int offl,
6940 operand * result, int offr, int shCount)
6942 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6943 /* shift left accumulator */
6945 aopPut (AOP (result), "a", offr);
6949 #ifdef BETTER_LITERAL_SHIFT
6950 /*-----------------------------------------------------------------*/
6951 /* movLeft2Result - move byte from left to result */
6952 /*-----------------------------------------------------------------*/
6954 movLeft2Result (operand * left, int offl,
6955 operand * result, int offr, int sign)
6958 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6960 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6962 if (*l == '@' && (IS_AOP_PREG (result)))
6964 emitcode ("mov", "a,%s", l);
6965 aopPut (AOP (result), "a", offr);
6971 aopPut (AOP (result), l, offr);
6975 /* MSB sign in acc.7 ! */
6976 if (getDataSize (left) == offl + 1)
6978 emitcode ("mov", "a,%s", l);
6979 aopPut (AOP (result), "a", offr);
6987 #ifdef BETTER_LITERAL_SHIFT
6988 /*-----------------------------------------------------------------*/
6989 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6990 /*-----------------------------------------------------------------*/
6994 emitcode ("rrc", "a");
6995 emitcode ("xch", "a,%s", x);
6996 emitcode ("rrc", "a");
6997 emitcode ("xch", "a,%s", x);
7001 #ifdef BETTER_LITERAL_SHIFT
7003 /*-----------------------------------------------------------------*/
7004 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7005 /*-----------------------------------------------------------------*/
7009 emitcode ("xch", "a,%s", x);
7010 emitcode ("rlc", "a");
7011 emitcode ("xch", "a,%s", x);
7012 emitcode ("rlc", "a");
7016 #ifdef BETTER_LITERAL_SHIFT
7017 /*-----------------------------------------------------------------*/
7018 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7019 /*-----------------------------------------------------------------*/
7023 emitcode ("xch", "a,%s", x);
7024 emitcode ("add", "a,acc");
7025 emitcode ("xch", "a,%s", x);
7026 emitcode ("rlc", "a");
7030 #ifdef BETTER_LITERAL_SHIFT
7031 /*-----------------------------------------------------------------*/
7032 /* AccAXLsh - left shift a:x by known count (0..7) */
7033 /*-----------------------------------------------------------------*/
7035 AccAXLsh (char *x, int shCount)
7050 case 5: // AAAAABBB:CCCCCDDD
7052 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7054 emitcode ("anl", "a,#0x%02x",
7055 SLMask[shCount]); // BBB00000:CCCCCDDD
7057 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7059 AccRol (shCount); // DDDCCCCC:BBB00000
7061 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7063 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7065 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7067 emitcode ("anl", "a,#0x%02x",
7068 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7070 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7072 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7075 case 6: // AAAAAABB:CCCCCCDD
7076 emitcode ("anl", "a,#0x%02x",
7077 SRMask[shCount]); // 000000BB:CCCCCCDD
7078 emitcode ("mov", "c,acc.0"); // c = B
7079 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7081 AccAXRrl1 (x); // BCCCCCCD:D000000B
7082 AccAXRrl1 (x); // BBCCCCCC:DD000000
7084 emitcode("rrc","a");
7085 emitcode("xch","a,%s", x);
7086 emitcode("rrc","a");
7087 emitcode("mov","c,acc.0"); //<< get correct bit
7088 emitcode("xch","a,%s", x);
7090 emitcode("rrc","a");
7091 emitcode("xch","a,%s", x);
7092 emitcode("rrc","a");
7093 emitcode("xch","a,%s", x);
7096 case 7: // a:x <<= 7
7098 emitcode ("anl", "a,#0x%02x",
7099 SRMask[shCount]); // 0000000B:CCCCCCCD
7101 emitcode ("mov", "c,acc.0"); // c = B
7103 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7105 AccAXRrl1 (x); // BCCCCCCC:D0000000
7114 #ifdef BETTER_LITERAL_SHIFT
7116 /*-----------------------------------------------------------------*/
7117 /* AccAXRsh - right shift a:x known count (0..7) */
7118 /*-----------------------------------------------------------------*/
7120 AccAXRsh (char *x, int shCount)
7128 AccAXRrl1 (x); // 0->a:x
7133 AccAXRrl1 (x); // 0->a:x
7136 AccAXRrl1 (x); // 0->a:x
7141 case 5: // AAAAABBB:CCCCCDDD = a:x
7143 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7145 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7147 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7149 emitcode ("anl", "a,#0x%02x",
7150 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7152 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7154 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7156 emitcode ("anl", "a,#0x%02x",
7157 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7159 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7161 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7163 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7166 case 6: // AABBBBBB:CCDDDDDD
7168 emitcode ("mov", "c,acc.7");
7169 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7171 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7173 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7175 emitcode ("anl", "a,#0x%02x",
7176 SRMask[shCount]); // 000000AA:BBBBBBCC
7179 case 7: // ABBBBBBB:CDDDDDDD
7181 emitcode ("mov", "c,acc.7"); // c = A
7183 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7185 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7187 emitcode ("anl", "a,#0x%02x",
7188 SRMask[shCount]); // 0000000A:BBBBBBBC
7197 #ifdef BETTER_LITERAL_SHIFT
7198 /*-----------------------------------------------------------------*/
7199 /* AccAXRshS - right shift signed a:x known count (0..7) */
7200 /*-----------------------------------------------------------------*/
7202 AccAXRshS (char *x, int shCount)
7210 emitcode ("mov", "c,acc.7");
7211 AccAXRrl1 (x); // s->a:x
7215 emitcode ("mov", "c,acc.7");
7216 AccAXRrl1 (x); // s->a:x
7218 emitcode ("mov", "c,acc.7");
7219 AccAXRrl1 (x); // s->a:x
7224 case 5: // AAAAABBB:CCCCCDDD = a:x
7226 tlbl = newiTempLabel (NULL);
7227 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7229 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7231 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7233 emitcode ("anl", "a,#0x%02x",
7234 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7236 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7238 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7240 emitcode ("anl", "a,#0x%02x",
7241 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7243 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7245 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7247 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7249 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7250 emitcode ("orl", "a,#0x%02x",
7251 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7253 emitcode ("", "%05d$:", tlbl->key + 100);
7254 break; // SSSSAAAA:BBBCCCCC
7256 case 6: // AABBBBBB:CCDDDDDD
7258 tlbl = newiTempLabel (NULL);
7259 emitcode ("mov", "c,acc.7");
7260 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7262 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7264 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7266 emitcode ("anl", "a,#0x%02x",
7267 SRMask[shCount]); // 000000AA:BBBBBBCC
7269 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7270 emitcode ("orl", "a,#0x%02x",
7271 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7273 emitcode ("", "%05d$:", tlbl->key + 100);
7275 case 7: // ABBBBBBB:CDDDDDDD
7277 tlbl = newiTempLabel (NULL);
7278 emitcode ("mov", "c,acc.7"); // c = A
7280 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7282 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7284 emitcode ("anl", "a,#0x%02x",
7285 SRMask[shCount]); // 0000000A:BBBBBBBC
7287 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7288 emitcode ("orl", "a,#0x%02x",
7289 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7291 emitcode ("", "%05d$:", tlbl->key + 100);
7299 #ifdef BETTER_LITERAL_SHIFT
7301 _loadLeftIntoAx(char **lsb,
7307 // Get the initial value from left into a pair of registers.
7308 // MSB must be in A, LSB can be any register.
7310 // If the result is held in registers, it is an optimization
7311 // if the LSB can be held in the register which will hold the,
7312 // result LSB since this saves us from having to copy it into
7313 // the result following AccAXLsh.
7315 // If the result is addressed indirectly, this is not a gain.
7316 if (AOP_NEEDSACC(result))
7320 _startLazyDPSEvaluation();
7321 if (AOP_TYPE(left) == AOP_DPTR2)
7324 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7325 // get LSB in DP2_RESULT_REG.
7326 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7327 assert(!strcmp(leftByte, DP2_RESULT_REG));
7331 // get LSB into DP2_RESULT_REG
7332 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7333 if (strcmp(leftByte, DP2_RESULT_REG))
7336 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7339 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7340 assert(strcmp(leftByte, DP2_RESULT_REG));
7343 _endLazyDPSEvaluation();
7344 *lsb = DP2_RESULT_REG;
7348 if (sameRegs (AOP (result), AOP (left)) &&
7349 ((offl + MSB16) == offr))
7351 /* don't crash result[offr] */
7352 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7353 emitcode ("xch", "a,%s",
7354 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7358 movLeft2Result (left, offl, result, offr, 0);
7359 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7361 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7362 assert(strcmp(*lsb,"a"));
7367 _storeAxResults(char *lsb,
7371 _startLazyDPSEvaluation();
7372 if (AOP_NEEDSACC(result))
7374 /* We have to explicitly update the result LSB.
7376 emitcode("xch","a,%s", lsb);
7377 aopPut(AOP(result), "a", offr);
7378 emitcode("mov","a,%s", lsb);
7380 if (getDataSize (result) > 1)
7382 aopPut (AOP (result), "a", offr + MSB16);
7384 _endLazyDPSEvaluation();
7387 /*-----------------------------------------------------------------*/
7388 /* shiftL2Left2Result - shift left two bytes from left to result */
7389 /*-----------------------------------------------------------------*/
7391 shiftL2Left2Result (operand * left, int offl,
7392 operand * result, int offr, int shCount)
7396 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7398 AccAXLsh (lsb, shCount);
7400 _storeAxResults(lsb, result, offr);
7404 #ifdef BETTER_LITERAL_SHIFT
7405 /*-----------------------------------------------------------------*/
7406 /* shiftR2Left2Result - shift right two bytes from left to result */
7407 /*-----------------------------------------------------------------*/
7409 shiftR2Left2Result (operand * left, int offl,
7410 operand * result, int offr,
7411 int shCount, int sign)
7415 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7417 /* a:x >> shCount (x = lsb(result)) */
7420 AccAXRshS(lsb, shCount);
7424 AccAXRsh(lsb, shCount);
7427 _storeAxResults(lsb, result, offr);
7433 /*-----------------------------------------------------------------*/
7434 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7435 /*-----------------------------------------------------------------*/
7437 shiftLLeftOrResult (operand * left, int offl,
7438 operand * result, int offr, int shCount)
7440 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7441 /* shift left accumulator */
7443 /* or with result */
7444 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7445 /* back to result */
7446 aopPut (AOP (result), "a", offr);
7452 /*-----------------------------------------------------------------*/
7453 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7454 /*-----------------------------------------------------------------*/
7456 shiftRLeftOrResult (operand * left, int offl,
7457 operand * result, int offr, int shCount)
7459 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7460 /* shift right accumulator */
7462 /* or with result */
7463 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7464 /* back to result */
7465 aopPut (AOP (result), "a", offr);
7469 #ifdef BETTER_LITERAL_SHIFT
7470 /*-----------------------------------------------------------------*/
7471 /* genlshOne - left shift a one byte quantity by known count */
7472 /*-----------------------------------------------------------------*/
7474 genlshOne (operand * result, operand * left, int shCount)
7476 D (emitcode (";", "genlshOne "););
7477 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7481 #ifdef BETTER_LITERAL_SHIFT
7482 /*-----------------------------------------------------------------*/
7483 /* genlshTwo - left shift two bytes by known amount != 0 */
7484 /*-----------------------------------------------------------------*/
7486 genlshTwo (operand * result, operand * left, int shCount)
7490 D (emitcode (";", "genlshTwo "););
7492 size = getDataSize (result);
7494 /* if shCount >= 8 */
7499 _startLazyDPSEvaluation();
7505 _endLazyDPSEvaluation();
7506 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7507 aopPut (AOP (result), zero, LSB);
7511 movLeft2Result (left, LSB, result, MSB16, 0);
7512 aopPut (AOP (result), zero, LSB);
7513 _endLazyDPSEvaluation();
7518 aopPut (AOP (result), zero, LSB);
7519 _endLazyDPSEvaluation();
7523 /* 1 <= shCount <= 7 */
7528 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7532 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7540 /*-----------------------------------------------------------------*/
7541 /* shiftLLong - shift left one long from left to result */
7542 /* offl = LSB or MSB16 */
7543 /*-----------------------------------------------------------------*/
7545 shiftLLong (operand * left, operand * result, int offr)
7548 int size = AOP_SIZE (result);
7550 if (size >= LSB + offr)
7552 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7554 emitcode ("add", "a,acc");
7555 if (sameRegs (AOP (left), AOP (result)) &&
7556 size >= MSB16 + offr && offr != LSB)
7557 emitcode ("xch", "a,%s",
7558 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7560 aopPut (AOP (result), "a", LSB + offr);
7563 if (size >= MSB16 + offr)
7565 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7567 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7570 emitcode ("rlc", "a");
7571 if (sameRegs (AOP (left), AOP (result)) &&
7572 size >= MSB24 + offr && offr != LSB)
7573 emitcode ("xch", "a,%s",
7574 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7576 aopPut (AOP (result), "a", MSB16 + offr);
7579 if (size >= MSB24 + offr)
7581 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7583 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7586 emitcode ("rlc", "a");
7587 if (sameRegs (AOP (left), AOP (result)) &&
7588 size >= MSB32 + offr && offr != LSB)
7589 emitcode ("xch", "a,%s",
7590 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7592 aopPut (AOP (result), "a", MSB24 + offr);
7595 if (size > MSB32 + offr)
7597 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7599 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7602 emitcode ("rlc", "a");
7603 aopPut (AOP (result), "a", MSB32 + offr);
7606 aopPut (AOP (result), zero, LSB);
7612 /*-----------------------------------------------------------------*/
7613 /* genlshFour - shift four byte by a known amount != 0 */
7614 /*-----------------------------------------------------------------*/
7616 genlshFour (operand * result, operand * left, int shCount)
7620 D (emitcode (";", "genlshFour ");
7623 size = AOP_SIZE (result);
7625 /* if shifting more that 3 bytes */
7630 /* lowest order of left goes to the highest
7631 order of the destination */
7632 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7634 movLeft2Result (left, LSB, result, MSB32, 0);
7635 aopPut (AOP (result), zero, LSB);
7636 aopPut (AOP (result), zero, MSB16);
7637 aopPut (AOP (result), zero, MSB24);
7641 /* more than two bytes */
7642 else if (shCount >= 16)
7644 /* lower order two bytes goes to higher order two bytes */
7646 /* if some more remaining */
7648 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7651 movLeft2Result (left, MSB16, result, MSB32, 0);
7652 movLeft2Result (left, LSB, result, MSB24, 0);
7654 aopPut (AOP (result), zero, MSB16);
7655 aopPut (AOP (result), zero, LSB);
7659 /* if more than 1 byte */
7660 else if (shCount >= 8)
7662 /* lower order three bytes goes to higher order three bytes */
7667 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7669 movLeft2Result (left, LSB, result, MSB16, 0);
7675 movLeft2Result (left, MSB24, result, MSB32, 0);
7676 movLeft2Result (left, MSB16, result, MSB24, 0);
7677 movLeft2Result (left, LSB, result, MSB16, 0);
7678 aopPut (AOP (result), zero, LSB);
7680 else if (shCount == 1)
7681 shiftLLong (left, result, MSB16);
7684 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7685 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7686 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7687 aopPut (AOP (result), zero, LSB);
7692 /* 1 <= shCount <= 7 */
7693 else if (shCount <= 2)
7695 shiftLLong (left, result, LSB);
7697 shiftLLong (result, result, LSB);
7699 /* 3 <= shCount <= 7, optimize */
7702 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7703 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7704 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7709 #ifdef BETTER_LITERAL_SHIFT
7710 /*-----------------------------------------------------------------*/
7711 /* genLeftShiftLiteral - left shifting by known count */
7712 /*-----------------------------------------------------------------*/
7714 genLeftShiftLiteral (operand * left,
7719 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7722 size = getSize (operandType (result));
7724 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7726 /* We only handle certain easy cases so far. */
7728 && (shCount < (size * 8))
7732 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7736 freeAsmop (right, NULL, ic, TRUE);
7738 aopOp(left, ic, FALSE, FALSE);
7739 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7742 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7744 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7745 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7747 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7750 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7752 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7753 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7755 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7761 emitcode ("; shift left ", "result %d, left %d", size,
7765 /* I suppose that the left size >= result size */
7768 _startLazyDPSEvaluation();
7771 movLeft2Result (left, size, result, size, 0);
7773 _endLazyDPSEvaluation();
7775 else if (shCount >= (size * 8))
7777 _startLazyDPSEvaluation();
7780 aopPut (AOP (result), zero, size);
7782 _endLazyDPSEvaluation();
7789 genlshOne (result, left, shCount);
7793 genlshTwo (result, left, shCount);
7797 genlshFour (result, left, shCount);
7801 fprintf(stderr, "*** ack! mystery literal shift!\n");
7805 freeAsmop (left, NULL, ic, TRUE);
7806 freeAsmop (result, NULL, ic, TRUE);
7811 /*-----------------------------------------------------------------*/
7812 /* genLeftShift - generates code for left shifting */
7813 /*-----------------------------------------------------------------*/
7815 genLeftShift (iCode * ic)
7817 operand *left, *right, *result;
7820 symbol *tlbl, *tlbl1;
7822 D (emitcode (";", "genLeftShift "););
7824 right = IC_RIGHT (ic);
7825 left = IC_LEFT (ic);
7826 result = IC_RESULT (ic);
7828 aopOp (right, ic, FALSE, FALSE);
7831 #ifdef BETTER_LITERAL_SHIFT
7832 /* if the shift count is known then do it
7833 as efficiently as possible */
7834 if (AOP_TYPE (right) == AOP_LIT)
7836 if (genLeftShiftLiteral (left, right, result, ic))
7843 /* shift count is unknown then we have to form
7844 a loop get the loop count in B : Note: we take
7845 only the lower order byte since shifting
7846 more that 32 bits make no sense anyway, ( the
7847 largest size of an object can be only 32 bits ) */
7849 if (AOP_TYPE (right) == AOP_LIT)
7851 /* Really should be handled by genLeftShiftLiteral,
7852 * but since I'm too lazy to fix that today, at least we can make
7853 * some small improvement.
7855 emitcode("mov", "b,#0x%02x",
7856 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7860 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7861 emitcode ("inc", "b");
7863 freeAsmop (right, NULL, ic, TRUE);
7864 aopOp (left, ic, FALSE, FALSE);
7865 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7867 /* now move the left to the result if they are not the
7869 if (!sameRegs (AOP (left), AOP (result)) &&
7870 AOP_SIZE (result) > 1)
7873 size = AOP_SIZE (result);
7875 _startLazyDPSEvaluation ();
7878 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7879 if (*l == '@' && (IS_AOP_PREG (result)))
7882 emitcode ("mov", "a,%s", l);
7883 aopPut (AOP (result), "a", offset);
7886 aopPut (AOP (result), l, offset);
7889 _endLazyDPSEvaluation ();
7892 tlbl = newiTempLabel (NULL);
7893 size = AOP_SIZE (result);
7895 tlbl1 = newiTempLabel (NULL);
7897 /* if it is only one byte then */
7900 symbol *tlbl1 = newiTempLabel (NULL);
7902 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7904 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7905 emitcode ("", "%05d$:", tlbl->key + 100);
7906 emitcode ("add", "a,acc");
7907 emitcode ("", "%05d$:", tlbl1->key + 100);
7908 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7909 aopPut (AOP (result), "a", 0);
7913 reAdjustPreg (AOP (result));
7915 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7916 emitcode ("", "%05d$:", tlbl->key + 100);
7917 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7919 emitcode ("add", "a,acc");
7920 aopPut (AOP (result), "a", offset++);
7921 _startLazyDPSEvaluation ();
7924 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7926 emitcode ("rlc", "a");
7927 aopPut (AOP (result), "a", offset++);
7929 _endLazyDPSEvaluation ();
7930 reAdjustPreg (AOP (result));
7932 emitcode ("", "%05d$:", tlbl1->key + 100);
7933 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7935 freeAsmop (left, NULL, ic, TRUE);
7936 freeAsmop (result, NULL, ic, TRUE);
7939 #ifdef BETTER_LITERAL_SHIFT
7940 /*-----------------------------------------------------------------*/
7941 /* genrshOne - right shift a one byte quantity by known count */
7942 /*-----------------------------------------------------------------*/
7944 genrshOne (operand * result, operand * left,
7945 int shCount, int sign)
7947 D (emitcode (";", "genrshOne"););
7948 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7952 #ifdef BETTER_LITERAL_SHIFT
7953 /*-----------------------------------------------------------------*/
7954 /* genrshTwo - right shift two bytes by known amount != 0 */
7955 /*-----------------------------------------------------------------*/
7957 genrshTwo (operand * result, operand * left,
7958 int shCount, int sign)
7960 D (emitcode (";", "genrshTwo"););
7962 /* if shCount >= 8 */
7966 _startLazyDPSEvaluation();
7969 shiftR1Left2Result (left, MSB16, result, LSB,
7974 movLeft2Result (left, MSB16, result, LSB, sign);
7976 addSign (result, MSB16, sign);
7977 _endLazyDPSEvaluation();
7980 /* 1 <= shCount <= 7 */
7983 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7990 /*-----------------------------------------------------------------*/
7991 /* shiftRLong - shift right one long from left to result */
7992 /* offl = LSB or MSB16 */
7993 /*-----------------------------------------------------------------*/
7995 shiftRLong (operand * left, int offl,
7996 operand * result, int sign)
7998 int isSameRegs=sameRegs(AOP(left),AOP(result));
8000 if (isSameRegs && offl>1) {
8001 // we are in big trouble, but this shouldn't happen
8002 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8005 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
8010 emitcode ("rlc", "a");
8011 emitcode ("subb", "a,acc");
8012 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
8014 aopPut (AOP(result), zero, MSB32);
8019 emitcode ("clr", "c");
8021 emitcode ("mov", "c,acc.7");
8024 emitcode ("rrc", "a");
8026 if (isSameRegs && offl==MSB16) {
8027 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
8029 aopPut (AOP (result), "a", MSB32);
8030 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
8033 emitcode ("rrc", "a");
8034 if (isSameRegs && offl==1) {
8035 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
8037 aopPut (AOP (result), "a", MSB24);
8038 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
8040 emitcode ("rrc", "a");
8041 aopPut (AOP (result), "a", MSB16 - offl);
8045 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
8046 emitcode ("rrc", "a");
8047 aopPut (AOP (result), "a", LSB);
8054 /*-----------------------------------------------------------------*/
8055 /* genrshFour - shift four byte by a known amount != 0 */
8056 /*-----------------------------------------------------------------*/
8058 genrshFour (operand * result, operand * left,
8059 int shCount, int sign)
8061 D (emitcode (";", "genrshFour");
8064 /* if shifting more that 3 bytes */
8069 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8071 movLeft2Result (left, MSB32, result, LSB, sign);
8072 addSign (result, MSB16, sign);
8074 else if (shCount >= 16)
8078 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8081 movLeft2Result (left, MSB24, result, LSB, 0);
8082 movLeft2Result (left, MSB32, result, MSB16, sign);
8084 addSign (result, MSB24, sign);
8086 else if (shCount >= 8)
8090 shiftRLong (left, MSB16, result, sign);
8091 else if (shCount == 0)
8093 movLeft2Result (left, MSB16, result, LSB, 0);
8094 movLeft2Result (left, MSB24, result, MSB16, 0);
8095 movLeft2Result (left, MSB32, result, MSB24, sign);
8096 addSign (result, MSB32, sign);
8100 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8101 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8102 /* the last shift is signed */
8103 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8104 addSign (result, MSB32, sign);
8108 { /* 1 <= shCount <= 7 */
8111 shiftRLong (left, LSB, result, sign);
8113 shiftRLong (result, LSB, result, sign);
8117 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8118 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8119 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8125 #ifdef BETTER_LITERAL_SHIFT
8126 /*-----------------------------------------------------------------*/
8127 /* genRightShiftLiteral - right shifting by known count */
8128 /*-----------------------------------------------------------------*/
8130 genRightShiftLiteral (operand * left,
8136 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8139 size = getSize (operandType (result));
8141 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8143 /* We only handle certain easy cases so far. */
8145 && (shCount < (size * 8))
8149 D(emitcode (";", "genRightShiftLiteral wimping out"););
8153 freeAsmop (right, NULL, ic, TRUE);
8155 aopOp (left, ic, FALSE, FALSE);
8156 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8159 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8163 /* test the LEFT size !!! */
8165 /* I suppose that the left size >= result size */
8168 size = getDataSize (result);
8169 _startLazyDPSEvaluation();
8172 movLeft2Result (left, size, result, size, 0);
8174 _endLazyDPSEvaluation();
8176 else if (shCount >= (size * 8))
8180 /* get sign in acc.7 */
8181 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8183 addSign (result, LSB, sign);
8190 genrshOne (result, left, shCount, sign);
8194 genrshTwo (result, left, shCount, sign);
8198 genrshFour (result, left, shCount, sign);
8205 freeAsmop (left, NULL, ic, TRUE);
8206 freeAsmop (result, NULL, ic, TRUE);
8212 /*-----------------------------------------------------------------*/
8213 /* genSignedRightShift - right shift of signed number */
8214 /*-----------------------------------------------------------------*/
8216 genSignedRightShift (iCode * ic)
8218 operand *right, *left, *result;
8221 symbol *tlbl, *tlbl1;
8223 D (emitcode (";", "genSignedRightShift "););
8225 /* we do it the hard way put the shift count in b
8226 and loop thru preserving the sign */
8228 right = IC_RIGHT (ic);
8229 left = IC_LEFT (ic);
8230 result = IC_RESULT (ic);
8232 aopOp (right, ic, FALSE, FALSE);
8234 #ifdef BETTER_LITERAL_SHIFT
8235 if (AOP_TYPE (right) == AOP_LIT)
8237 if (genRightShiftLiteral (left, right, result, ic, 1))
8243 /* shift count is unknown then we have to form
8244 a loop get the loop count in B : Note: we take
8245 only the lower order byte since shifting
8246 more that 32 bits make no sense anyway, ( the
8247 largest size of an object can be only 32 bits ) */
8249 if (AOP_TYPE (right) == AOP_LIT)
8251 /* Really should be handled by genRightShiftLiteral,
8252 * but since I'm too lazy to fix that today, at least we can make
8253 * some small improvement.
8255 emitcode("mov", "b,#0x%02x",
8256 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8260 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8261 emitcode ("inc", "b");
8263 freeAsmop (right, NULL, ic, TRUE);
8264 aopOp (left, ic, FALSE, FALSE);
8265 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8267 /* now move the left to the result if they are not the
8269 if (!sameRegs (AOP (left), AOP (result)) &&
8270 AOP_SIZE (result) > 1)
8273 size = AOP_SIZE (result);
8275 _startLazyDPSEvaluation ();
8278 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8279 if (*l == '@' && IS_AOP_PREG (result))
8282 emitcode ("mov", "a,%s", l);
8283 aopPut (AOP (result), "a", offset);
8286 aopPut (AOP (result), l, offset);
8289 _endLazyDPSEvaluation ();
8292 /* mov the highest order bit to OVR */
8293 tlbl = newiTempLabel (NULL);
8294 tlbl1 = newiTempLabel (NULL);
8296 size = AOP_SIZE (result);
8298 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8299 emitcode ("rlc", "a");
8300 emitcode ("mov", "ov,c");
8301 /* if it is only one byte then */
8304 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8306 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8307 emitcode ("", "%05d$:", tlbl->key + 100);
8308 emitcode ("mov", "c,ov");
8309 emitcode ("rrc", "a");
8310 emitcode ("", "%05d$:", tlbl1->key + 100);
8311 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8312 aopPut (AOP (result), "a", 0);
8316 reAdjustPreg (AOP (result));
8317 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8318 emitcode ("", "%05d$:", tlbl->key + 100);
8319 emitcode ("mov", "c,ov");
8320 _startLazyDPSEvaluation ();
8323 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8325 emitcode ("rrc", "a");
8326 aopPut (AOP (result), "a", offset--);
8328 _endLazyDPSEvaluation ();
8329 reAdjustPreg (AOP (result));
8330 emitcode ("", "%05d$:", tlbl1->key + 100);
8331 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8334 freeAsmop (left, NULL, ic, TRUE);
8335 freeAsmop (result, NULL, ic, TRUE);
8338 /*-----------------------------------------------------------------*/
8339 /* genRightShift - generate code for right shifting */
8340 /*-----------------------------------------------------------------*/
8342 genRightShift (iCode * ic)
8344 operand *right, *left, *result;
8348 symbol *tlbl, *tlbl1;
8350 D (emitcode (";", "genRightShift "););
8352 /* if signed then we do it the hard way preserve the
8353 sign bit moving it inwards */
8354 retype = getSpec (operandType (IC_RESULT (ic)));
8356 if (!SPEC_USIGN (retype))
8358 genSignedRightShift (ic);
8362 /* signed & unsigned types are treated the same : i.e. the
8363 signed is NOT propagated inwards : quoting from the
8364 ANSI - standard : "for E1 >> E2, is equivalent to division
8365 by 2**E2 if unsigned or if it has a non-negative value,
8366 otherwise the result is implementation defined ", MY definition
8367 is that the sign does not get propagated */
8369 right = IC_RIGHT (ic);
8370 left = IC_LEFT (ic);
8371 result = IC_RESULT (ic);
8373 aopOp (right, ic, FALSE, FALSE);
8375 #ifdef BETTER_LITERAL_SHIFT
8376 /* if the shift count is known then do it
8377 as efficiently as possible */
8378 if (AOP_TYPE (right) == AOP_LIT)
8380 if (genRightShiftLiteral (left, right, result, ic, 0))
8387 /* shift count is unknown then we have to form
8388 a loop get the loop count in B : Note: we take
8389 only the lower order byte since shifting
8390 more that 32 bits make no sense anyway, ( the
8391 largest size of an object can be only 32 bits ) */
8393 if (AOP_TYPE (right) == AOP_LIT)
8395 /* Really should be handled by genRightShiftLiteral,
8396 * but since I'm too lazy to fix that today, at least we can make
8397 * some small improvement.
8399 emitcode("mov", "b,#0x%02x",
8400 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8404 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8405 emitcode ("inc", "b");
8407 freeAsmop (right, NULL, ic, TRUE);
8408 aopOp (left, ic, FALSE, FALSE);
8409 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8411 /* now move the left to the result if they are not the
8413 if (!sameRegs (AOP (left), AOP (result)) &&
8414 AOP_SIZE (result) > 1)
8417 size = AOP_SIZE (result);
8419 _startLazyDPSEvaluation ();
8422 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8423 if (*l == '@' && IS_AOP_PREG (result))
8426 emitcode ("mov", "a,%s", l);
8427 aopPut (AOP (result), "a", offset);
8430 aopPut (AOP (result), l, offset);
8433 _endLazyDPSEvaluation ();
8436 tlbl = newiTempLabel (NULL);
8437 tlbl1 = newiTempLabel (NULL);
8438 size = AOP_SIZE (result);
8441 /* if it is only one byte then */
8444 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8446 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8447 emitcode ("", "%05d$:", tlbl->key + 100);
8449 emitcode ("rrc", "a");
8450 emitcode ("", "%05d$:", tlbl1->key + 100);
8451 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8452 aopPut (AOP (result), "a", 0);
8456 reAdjustPreg (AOP (result));
8457 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8458 emitcode ("", "%05d$:", tlbl->key + 100);
8460 _startLazyDPSEvaluation ();
8463 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8465 emitcode ("rrc", "a");
8466 aopPut (AOP (result), "a", offset--);
8468 _endLazyDPSEvaluation ();
8469 reAdjustPreg (AOP (result));
8471 emitcode ("", "%05d$:", tlbl1->key + 100);
8472 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8475 freeAsmop (left, NULL, ic, TRUE);
8476 freeAsmop (result, NULL, ic, TRUE);
8479 /*-----------------------------------------------------------------*/
8480 /* genUnpackBits - generates code for unpacking bits */
8481 /*-----------------------------------------------------------------*/
8483 genUnpackBits (operand * result, char *rname, int ptype)
8490 D (emitcode (";", "genUnpackBits ");
8493 etype = getSpec (operandType (result));
8495 /* read the first byte */
8501 emitcode ("mov", "a,@%s", rname);
8505 emitcode ("movx", "a,@%s", rname);
8509 emitcode ("movx", "a,@dptr");
8513 emitcode ("clr", "a");
8514 emitcode ("movc", "a,@a+dptr");
8518 emitcode ("lcall", "__gptrget");
8522 /* if we have bitdisplacement then it fits */
8523 /* into this byte completely or if length is */
8524 /* less than a byte */
8525 if ((shCnt = SPEC_BSTR (etype)) ||
8526 (SPEC_BLEN (etype) <= 8))
8529 /* shift right acc */
8532 emitcode ("anl", "a,#0x%02x",
8533 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8534 aopPut (AOP (result), "a", offset);
8538 /* bit field did not fit in a byte */
8539 rlen = SPEC_BLEN (etype) - 8;
8540 aopPut (AOP (result), "a", offset++);
8549 emitcode ("inc", "%s", rname);
8550 emitcode ("mov", "a,@%s", rname);
8554 emitcode ("inc", "%s", rname);
8555 emitcode ("movx", "a,@%s", rname);
8559 emitcode ("inc", "dptr");
8560 emitcode ("movx", "a,@dptr");
8564 emitcode ("clr", "a");
8565 emitcode ("inc", "dptr");
8566 emitcode ("movc", "a,@a+dptr");
8570 emitcode ("inc", "dptr");
8571 emitcode ("lcall", "__gptrget");
8576 /* if we are done */
8580 aopPut (AOP (result), "a", offset++);
8586 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
8587 aopPut (AOP (result), "a", offset);
8594 /*-----------------------------------------------------------------*/
8595 /* genDataPointerGet - generates code when ptr offset is known */
8596 /*-----------------------------------------------------------------*/
8598 genDataPointerGet (operand * left,
8604 int size, offset = 0;
8605 aopOp (result, ic, TRUE, FALSE);
8607 /* get the string representation of the name */
8608 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8609 size = AOP_SIZE (result);
8610 _startLazyDPSEvaluation ();
8614 sprintf (buffer, "(%s + %d)", l + 1, offset);
8616 sprintf (buffer, "%s", l + 1);
8617 aopPut (AOP (result), buffer, offset++);
8619 _endLazyDPSEvaluation ();
8621 freeAsmop (left, NULL, ic, TRUE);
8622 freeAsmop (result, NULL, ic, TRUE);
8625 /*-----------------------------------------------------------------*/
8626 /* genNearPointerGet - emitcode for near pointer fetch */
8627 /*-----------------------------------------------------------------*/
8629 genNearPointerGet (operand * left,
8637 sym_link *rtype, *retype, *letype;
8638 sym_link *ltype = operandType (left);
8641 rtype = operandType (result);
8642 retype = getSpec (rtype);
8643 letype = getSpec (ltype);
8645 aopOp (left, ic, FALSE, FALSE);
8647 /* if left is rematerialisable and
8648 result is not bit variable type and
8649 the left is pointer to data space i.e
8650 lower 128 bytes of space */
8651 if (AOP_TYPE (left) == AOP_IMMD &&
8652 !IS_BITVAR (retype) &&
8653 !IS_BITVAR (letype) &&
8654 DCL_TYPE (ltype) == POINTER)
8656 genDataPointerGet (left, result, ic);
8660 /* if the value is already in a pointer register
8661 then don't need anything more */
8662 if (!AOP_INPREG (AOP (left)))
8664 /* otherwise get a free pointer register */
8666 preg = getFreePtr (ic, &aop, FALSE);
8667 emitcode ("mov", "%s,%s",
8669 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8673 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8675 freeAsmop (left, NULL, ic, TRUE);
8676 aopOp (result, ic, FALSE, FALSE);
8678 /* if bitfield then unpack the bits */
8679 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8680 genUnpackBits (result, rname, POINTER);
8683 /* we have can just get the values */
8684 int size = AOP_SIZE (result);
8689 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8692 emitcode ("mov", "a,@%s", rname);
8693 aopPut (AOP (result), "a", offset);
8697 sprintf (buffer, "@%s", rname);
8698 aopPut (AOP (result), buffer, offset);
8702 emitcode ("inc", "%s", rname);
8706 /* now some housekeeping stuff */
8709 /* we had to allocate for this iCode */
8710 if (pi) { /* post increment present */
8711 aopPut(AOP ( left ),rname,0);
8713 freeAsmop (NULL, aop, ic, TRUE);
8717 /* we did not allocate which means left
8718 already in a pointer register, then
8719 if size > 0 && this could be used again
8720 we have to point it back to where it
8722 if (AOP_SIZE (result) > 1 &&
8723 !OP_SYMBOL (left)->remat &&
8724 (OP_SYMBOL (left)->liveTo > ic->seq ||
8728 int size = AOP_SIZE (result) - 1;
8730 emitcode ("dec", "%s", rname);
8735 freeAsmop (result, NULL, ic, TRUE);
8736 if (pi) pi->generated = 1;
8739 /*-----------------------------------------------------------------*/
8740 /* genPagedPointerGet - emitcode for paged pointer fetch */
8741 /*-----------------------------------------------------------------*/
8743 genPagedPointerGet (operand * left,
8751 sym_link *rtype, *retype, *letype;
8753 rtype = operandType (result);
8754 retype = getSpec (rtype);
8755 letype = getSpec (operandType (left));
8756 aopOp (left, ic, FALSE, FALSE);
8758 /* if the value is already in a pointer register
8759 then don't need anything more */
8760 if (!AOP_INPREG (AOP (left)))
8762 /* otherwise get a free pointer register */
8764 preg = getFreePtr (ic, &aop, FALSE);
8765 emitcode ("mov", "%s,%s",
8767 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8771 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8773 freeAsmop (left, NULL, ic, TRUE);
8774 aopOp (result, ic, FALSE, FALSE);
8776 /* if bitfield then unpack the bits */
8777 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8778 genUnpackBits (result, rname, PPOINTER);
8781 /* we have can just get the values */
8782 int size = AOP_SIZE (result);
8788 emitcode ("movx", "a,@%s", rname);
8789 aopPut (AOP (result), "a", offset);
8794 emitcode ("inc", "%s", rname);
8798 /* now some housekeeping stuff */
8801 /* we had to allocate for this iCode */
8802 if (pi) aopPut ( AOP (left), rname, 0);
8803 freeAsmop (NULL, aop, ic, TRUE);
8807 /* we did not allocate which means left
8808 already in a pointer register, then
8809 if size > 0 && this could be used again
8810 we have to point it back to where it
8812 if (AOP_SIZE (result) > 1 &&
8813 !OP_SYMBOL (left)->remat &&
8814 (OP_SYMBOL (left)->liveTo > ic->seq ||
8818 int size = AOP_SIZE (result) - 1;
8820 emitcode ("dec", "%s", rname);
8825 freeAsmop (result, NULL, ic, TRUE);
8826 if (pi) pi->generated = 1;
8829 /*-----------------------------------------------------------------*/
8830 /* genFarPointerGet - gget value from far space */
8831 /*-----------------------------------------------------------------*/
8833 genFarPointerGet (operand * left,
8834 operand * result, iCode * ic, iCode *pi)
8837 sym_link *retype = getSpec (operandType (result));
8838 sym_link *letype = getSpec (operandType (left));
8839 D (emitcode (";", "genFarPointerGet");
8842 aopOp (left, ic, FALSE, FALSE);
8844 /* if the operand is already in dptr
8845 then we do nothing else we move the value to dptr */
8846 if (AOP_TYPE (left) != AOP_STR)
8848 /* if this is remateriazable */
8849 if (AOP_TYPE (left) == AOP_IMMD)
8851 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8855 /* we need to get it byte by byte */
8856 _startLazyDPSEvaluation ();
8857 if (AOP_TYPE (left) != AOP_DPTR)
8859 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8860 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8861 if (options.model == MODEL_FLAT24)
8862 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8866 /* We need to generate a load to DPTR indirect through DPTR. */
8867 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8869 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8870 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8871 if (options.model == MODEL_FLAT24)
8872 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8873 emitcode ("pop", "dph");
8874 emitcode ("pop", "dpl");
8876 _endLazyDPSEvaluation ();
8879 /* so dptr know contains the address */
8880 aopOp (result, ic, FALSE, TRUE);
8882 /* if bit then unpack */
8883 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8884 genUnpackBits (result, "dptr", FPOINTER);
8887 size = AOP_SIZE (result);
8890 _startLazyDPSEvaluation ();
8897 emitcode ("movx", "a,@dptr");
8898 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
8899 emitcode ("inc", "dptr");
8901 aopPut (AOP (result), "a", offset++);
8903 _endLazyDPSEvaluation ();
8905 if (pi && AOP_TYPE (left) != AOP_IMMD) {
8906 aopPut ( AOP (left), "dpl", 0);
8907 aopPut ( AOP (left), "dph", 1);
8908 if (options.model == MODEL_FLAT24)
8909 aopPut ( AOP (left), "dpx", 2);
8911 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
8912 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
8914 size = AOP_SIZE (result) - 1;
8915 while (size--) emitcode ("lcall","__decdptr");
8918 freeAsmop (left, NULL, ic, TRUE);
8919 freeAsmop (result, NULL, ic, TRUE);
8922 /*-----------------------------------------------------------------*/
8923 /* emitcodePointerGet - gget value from code space */
8924 /*-----------------------------------------------------------------*/
8926 emitcodePointerGet (operand * left,
8927 operand * result, iCode * ic, iCode *pi)
8930 sym_link *retype = getSpec (operandType (result));
8932 aopOp (left, ic, FALSE, FALSE);
8934 /* if the operand is already in dptr
8935 then we do nothing else we move the value to dptr */
8936 if (AOP_TYPE (left) != AOP_STR)
8938 /* if this is remateriazable */
8939 if (AOP_TYPE (left) == AOP_IMMD)
8941 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8944 { /* we need to get it byte by byte */
8945 _startLazyDPSEvaluation ();
8946 if (AOP_TYPE (left) != AOP_DPTR)
8948 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8949 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8950 if (options.model == MODEL_FLAT24)
8951 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8955 /* We need to generate a load to DPTR indirect through DPTR. */
8956 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8958 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8959 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8960 if (options.model == MODEL_FLAT24)
8961 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8962 emitcode ("pop", "dph");
8963 emitcode ("pop", "dpl");
8965 _endLazyDPSEvaluation ();
8968 /* so dptr know contains the address */
8969 aopOp (result, ic, FALSE, TRUE);
8971 /* if bit then unpack */
8972 if (IS_BITVAR (retype))
8973 genUnpackBits (result, "dptr", CPOINTER);
8976 size = AOP_SIZE (result);
8979 _startLazyDPSEvaluation ();
8985 emitcode ("clr", "a");
8986 emitcode ("movc", "a,@a+dptr");
8987 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
8988 emitcode ("inc", "dptr");
8989 aopPut (AOP (result), "a", offset++);
8991 _endLazyDPSEvaluation ();
8993 if (pi && AOP_TYPE (left) != AOP_IMMD) {
8994 aopPut ( AOP (left), "dpl", 0);
8995 aopPut ( AOP (left), "dph", 1);
8996 if (options.model == MODEL_FLAT24)
8997 aopPut ( AOP (left), "dpx", 2);
8999 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9000 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9002 size = AOP_SIZE (result) - 1;
9003 while (size--) emitcode ("lcall","__decdptr");
9006 freeAsmop (left, NULL, ic, TRUE);
9007 freeAsmop (result, NULL, ic, TRUE);
9010 /*-----------------------------------------------------------------*/
9011 /* genGenPointerGet - gget value from generic pointer space */
9012 /*-----------------------------------------------------------------*/
9014 genGenPointerGet (operand * left,
9015 operand * result, iCode * ic, iCode * pi)
9018 sym_link *retype = getSpec (operandType (result));
9019 sym_link *letype = getSpec (operandType (left));
9021 D (emitcode (";", "genGenPointerGet "); );
9023 aopOp (left, ic, FALSE, (OP_SYMBOL(left)->ruonly ? FALSE : TRUE));
9025 /* if the operand is already in dptr
9026 then we do nothing else we move the value to dptr */
9027 if (AOP_TYPE (left) != AOP_STR)
9029 /* if this is remateriazable */
9030 if (AOP_TYPE (left) == AOP_IMMD)
9032 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9033 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9034 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
9036 emitcode ("mov", "b,#%d", pointerCode (retype));
9039 { /* we need to get it byte by byte */
9040 _startLazyDPSEvaluation ();
9041 if (AOP(left)->type==AOP_DPTR2) {
9043 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
9046 emitcode ("mov", "dpl,%s", l);
9047 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
9050 emitcode ("mov", "dph,%s", l);
9051 if (options.model == MODEL_FLAT24) {
9052 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
9055 emitcode ("mov", "dpx,%s", l);
9056 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9058 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9061 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
9062 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
9063 if (options.model == MODEL_FLAT24) {
9064 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9065 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9067 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9070 _endLazyDPSEvaluation ();
9073 /* so dptr know contains the address */
9074 aopOp (result, ic, FALSE, TRUE);
9076 /* if bit then unpack */
9077 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9078 genUnpackBits (result, "dptr", GPOINTER);
9081 size = AOP_SIZE (result);
9086 emitcode ("lcall", "__gptrget");
9087 aopPut (AOP (result), "a", offset++);
9088 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9089 emitcode ("inc", "dptr");
9093 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9094 aopPut ( AOP (left), "dpl", 0);
9095 aopPut ( AOP (left), "dph", 1);
9096 if (options.model == MODEL_FLAT24) {
9097 aopPut ( AOP (left), "dpx", 2);
9098 aopPut ( AOP (left), "b", 3);
9099 } else aopPut ( AOP (left), "b", 2);
9101 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9102 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9104 size = AOP_SIZE (result) - 1;
9105 while (size--) emitcode ("lcall","__decdptr");
9108 freeAsmop (left, NULL, ic, TRUE);
9109 freeAsmop (result, NULL, ic, TRUE);
9112 /*-----------------------------------------------------------------*/
9113 /* genPointerGet - generate code for pointer get */
9114 /*-----------------------------------------------------------------*/
9116 genPointerGet (iCode * ic, iCode *pi)
9118 operand *left, *result;
9119 sym_link *type, *etype;
9122 D (emitcode (";", "genPointerGet ");
9125 left = IC_LEFT (ic);
9126 result = IC_RESULT (ic);
9128 /* depending on the type of pointer we need to
9129 move it to the correct pointer register */
9130 type = operandType (left);
9131 etype = getSpec (type);
9132 /* if left is of type of pointer then it is simple */
9133 if (IS_PTR (type) && !IS_FUNC (type->next))
9134 p_type = DCL_TYPE (type);
9137 /* we have to go by the storage class */
9138 p_type = PTR_TYPE (SPEC_OCLS (etype));
9140 /* special case when cast remat */
9141 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9142 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9143 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9144 type = type = operandType (left);
9145 p_type = DCL_TYPE (type);
9147 /* now that we have the pointer type we assign
9148 the pointer values */
9154 genNearPointerGet (left, result, ic, pi);
9158 genPagedPointerGet (left, result, ic, pi);
9162 genFarPointerGet (left, result, ic, pi);
9166 emitcodePointerGet (left, result, ic, pi);
9170 genGenPointerGet (left, result, ic, pi);
9176 /*-----------------------------------------------------------------*/
9177 /* genPackBits - generates code for packed bit storage */
9178 /*-----------------------------------------------------------------*/
9180 genPackBits (sym_link * etype,
9182 char *rname, int p_type)
9190 blen = SPEC_BLEN (etype);
9191 bstr = SPEC_BSTR (etype);
9193 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9196 /* if the bit lenth is less than or */
9197 /* it exactly fits a byte then */
9198 if (SPEC_BLEN (etype) <= 8)
9200 shCount = SPEC_BSTR (etype);
9202 /* shift left acc */
9205 if (SPEC_BLEN (etype) < 8)
9206 { /* if smaller than a byte */
9212 emitcode ("mov", "b,a");
9213 emitcode ("mov", "a,@%s", rname);
9217 emitcode ("mov", "b,a");
9218 emitcode ("movx", "a,@dptr");
9222 emitcode ("push", "b");
9223 emitcode ("push", "acc");
9224 emitcode ("lcall", "__gptrget");
9225 emitcode ("pop", "b");
9229 emitcode ("anl", "a,#0x%02x", (unsigned char)
9230 ((unsigned char) (0xFF << (blen + bstr)) |
9231 (unsigned char) (0xFF >> (8 - bstr))));
9232 emitcode ("orl", "a,b");
9233 if (p_type == GPOINTER)
9234 emitcode ("pop", "b");
9241 emitcode ("mov", "@%s,a", rname);
9245 emitcode ("movx", "@dptr,a");
9249 emitcode ("lcall", "__gptrput");
9254 if (SPEC_BLEN (etype) <= 8)
9257 emitcode ("inc", "%s", rname);
9258 rLen = SPEC_BLEN (etype);
9260 /* now generate for lengths greater than one byte */
9264 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9276 emitcode ("mov", "@%s,a", rname);
9279 emitcode ("mov", "@%s,%s", rname, l);
9284 emitcode ("movx", "@dptr,a");
9289 emitcode ("lcall", "__gptrput");
9292 emitcode ("inc", "%s", rname);
9297 /* last last was not complete */
9300 /* save the byte & read byte */
9304 emitcode ("mov", "b,a");
9305 emitcode ("mov", "a,@%s", rname);
9309 emitcode ("mov", "b,a");
9310 emitcode ("movx", "a,@dptr");
9314 emitcode ("push", "b");
9315 emitcode ("push", "acc");
9316 emitcode ("lcall", "__gptrget");
9317 emitcode ("pop", "b");
9321 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
9322 emitcode ("orl", "a,b");
9325 if (p_type == GPOINTER)
9326 emitcode ("pop", "b");
9332 emitcode ("mov", "@%s,a", rname);
9336 emitcode ("movx", "@dptr,a");
9340 emitcode ("lcall", "__gptrput");
9344 /*-----------------------------------------------------------------*/
9345 /* genDataPointerSet - remat pointer to data space */
9346 /*-----------------------------------------------------------------*/
9348 genDataPointerSet (operand * right,
9352 int size, offset = 0;
9353 char *l, buffer[256];
9355 aopOp (right, ic, FALSE, FALSE);
9357 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9358 size = AOP_SIZE (right);
9362 sprintf (buffer, "(%s + %d)", l + 1, offset);
9364 sprintf (buffer, "%s", l + 1);
9365 emitcode ("mov", "%s,%s", buffer,
9366 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9369 freeAsmop (right, NULL, ic, TRUE);
9370 freeAsmop (result, NULL, ic, TRUE);
9373 /*-----------------------------------------------------------------*/
9374 /* genNearPointerSet - emitcode for near pointer put */
9375 /*-----------------------------------------------------------------*/
9377 genNearPointerSet (operand * right,
9385 sym_link *retype, *letype;
9386 sym_link *ptype = operandType (result);
9388 retype = getSpec (operandType (right));
9389 letype = getSpec (ptype);
9391 aopOp (result, ic, FALSE, FALSE);
9393 /* if the result is rematerializable &
9394 in data space & not a bit variable */
9395 if (AOP_TYPE (result) == AOP_IMMD &&
9396 DCL_TYPE (ptype) == POINTER &&
9397 !IS_BITVAR (retype) &&
9398 !IS_BITVAR (letype))
9400 genDataPointerSet (right, result, ic);
9404 /* if the value is already in a pointer register
9405 then don't need anything more */
9406 if (!AOP_INPREG (AOP (result)))
9408 /* otherwise get a free pointer register */
9410 preg = getFreePtr (ic, &aop, FALSE);
9411 emitcode ("mov", "%s,%s",
9413 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9417 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9419 aopOp (right, ic, FALSE, FALSE);
9421 /* if bitfield then unpack the bits */
9422 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9423 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9426 /* we have can just get the values */
9427 int size = AOP_SIZE (right);
9432 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9436 emitcode ("mov", "@%s,a", rname);
9439 emitcode ("mov", "@%s,%s", rname, l);
9441 emitcode ("inc", "%s", rname);
9446 /* now some housekeeping stuff */
9449 /* we had to allocate for this iCode */
9450 if (pi) aopPut (AOP (result),rname,0);
9451 freeAsmop (NULL, aop, ic, TRUE);
9455 /* we did not allocate which means left
9456 already in a pointer register, then
9457 if size > 0 && this could be used again
9458 we have to point it back to where it
9460 if (AOP_SIZE (right) > 1 &&
9461 !OP_SYMBOL (result)->remat &&
9462 (OP_SYMBOL (result)->liveTo > ic->seq ||
9466 int size = AOP_SIZE (right) - 1;
9468 emitcode ("dec", "%s", rname);
9473 if (pi) pi->generated = 1;
9474 freeAsmop (result, NULL, ic, TRUE);
9475 freeAsmop (right, NULL, ic, TRUE);
9480 /*-----------------------------------------------------------------*/
9481 /* genPagedPointerSet - emitcode for Paged pointer put */
9482 /*-----------------------------------------------------------------*/
9484 genPagedPointerSet (operand * right,
9492 sym_link *retype, *letype;
9494 retype = getSpec (operandType (right));
9495 letype = getSpec (operandType (result));
9497 aopOp (result, ic, FALSE, FALSE);
9499 /* if the value is already in a pointer register
9500 then don't need anything more */
9501 if (!AOP_INPREG (AOP (result)))
9503 /* otherwise get a free pointer register */
9505 preg = getFreePtr (ic, &aop, FALSE);
9506 emitcode ("mov", "%s,%s",
9508 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9512 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9514 aopOp (right, ic, FALSE, FALSE);
9516 /* if bitfield then unpack the bits */
9517 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9518 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9521 /* we have can just get the values */
9522 int size = AOP_SIZE (right);
9527 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9530 emitcode ("movx", "@%s,a", rname);
9533 emitcode ("inc", "%s", rname);
9539 /* now some housekeeping stuff */
9542 if (pi) aopPut (AOP (result),rname,0);
9543 /* we had to allocate for this iCode */
9544 freeAsmop (NULL, aop, ic, TRUE);
9548 /* we did not allocate which means left
9549 already in a pointer register, then
9550 if size > 0 && this could be used again
9551 we have to point it back to where it
9553 if (AOP_SIZE (right) > 1 &&
9554 !OP_SYMBOL (result)->remat &&
9555 (OP_SYMBOL (result)->liveTo > ic->seq ||
9559 int size = AOP_SIZE (right) - 1;
9561 emitcode ("dec", "%s", rname);
9566 if (pi) pi->generated = 1;
9567 freeAsmop (result, NULL, ic, TRUE);
9568 freeAsmop (right, NULL, ic, TRUE);
9573 /*-----------------------------------------------------------------*/
9574 /* genFarPointerSet - set value from far space */
9575 /*-----------------------------------------------------------------*/
9577 genFarPointerSet (operand * right,
9578 operand * result, iCode * ic, iCode *pi)
9581 sym_link *retype = getSpec (operandType (right));
9582 sym_link *letype = getSpec (operandType (result));
9584 aopOp (result, ic, FALSE, FALSE);
9586 /* if the operand is already in dptr
9587 then we do nothing else we move the value to dptr */
9588 if (AOP_TYPE (result) != AOP_STR)
9590 /* if this is remateriazable */
9591 if (AOP_TYPE (result) == AOP_IMMD)
9592 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9595 /* we need to get it byte by byte */
9596 _startLazyDPSEvaluation ();
9597 if (AOP_TYPE (result) != AOP_DPTR)
9599 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9600 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9601 if (options.model == MODEL_FLAT24)
9602 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9606 /* We need to generate a load to DPTR indirect through DPTR. */
9607 D (emitcode (";", "genFarPointerSet -- indirection special case.");
9609 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9610 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9611 if (options.model == MODEL_FLAT24)
9612 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9613 emitcode ("pop", "dph");
9614 emitcode ("pop", "dpl");
9616 _endLazyDPSEvaluation ();
9619 /* so dptr know contains the address */
9620 aopOp (right, ic, FALSE, TRUE);
9622 /* if bit then unpack */
9623 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9624 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9627 size = AOP_SIZE (right);
9630 _startLazyDPSEvaluation ();
9633 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9639 emitcode ("movx", "@dptr,a");
9640 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
9641 emitcode ("inc", "dptr");
9643 _endLazyDPSEvaluation ();
9646 if (pi && AOP_TYPE (result) != AOP_IMMD) {
9647 aopPut (AOP(result),"dpl",0);
9648 aopPut (AOP(result),"dph",1);
9649 if (options.model == MODEL_FLAT24)
9650 aopPut (AOP(result),"dpx",2);
9652 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9653 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9655 size = AOP_SIZE (right) - 1;
9656 while (size--) emitcode ("lcall","__decdptr");
9658 freeAsmop (result, NULL, ic, TRUE);
9659 freeAsmop (right, NULL, ic, TRUE);
9662 /*-----------------------------------------------------------------*/
9663 /* genGenPointerSet - set value from generic pointer space */
9664 /*-----------------------------------------------------------------*/
9666 genGenPointerSet (operand * right,
9667 operand * result, iCode * ic, iCode *pi)
9670 sym_link *retype = getSpec (operandType (right));
9671 sym_link *letype = getSpec (operandType (result));
9673 aopOp (result, ic, FALSE, OP_SYMBOL(result)->ruonly ? FALSE : TRUE);
9675 /* if the operand is already in dptr
9676 then we do nothing else we move the value to dptr */
9677 if (AOP_TYPE (result) != AOP_STR)
9679 _startLazyDPSEvaluation ();
9680 /* if this is remateriazable */
9681 if (AOP_TYPE (result) == AOP_IMMD)
9683 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9684 if (AOP(result)->aopu.aop_immd.from_cast_remat)
9685 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
9687 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9690 { /* we need to get it byte by byte */
9691 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9692 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9693 if (options.model == MODEL_FLAT24) {
9694 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9695 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9697 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9700 _endLazyDPSEvaluation ();
9702 /* so dptr know contains the address */
9703 aopOp (right, ic, FALSE, TRUE);
9705 /* if bit then unpack */
9706 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9707 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9710 size = AOP_SIZE (right);
9713 _startLazyDPSEvaluation ();
9716 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9722 emitcode ("lcall", "__gptrput");
9723 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
9724 emitcode ("inc", "dptr");
9726 _endLazyDPSEvaluation ();
9729 if (pi && AOP_TYPE (result) != AOP_IMMD) {
9730 aopPut (AOP(result),"dpl",0);
9731 aopPut (AOP(result),"dph",1);
9732 if (options.model == MODEL_FLAT24) {
9733 aopPut (AOP(result),"dpx",2);
9734 aopPut (AOP(result),"b",3);
9736 aopPut (AOP(result),"b",2);
9739 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9740 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9742 size = AOP_SIZE (right) - 1;
9743 while (size--) emitcode ("lcall","__decdptr");
9745 freeAsmop (result, NULL, ic, TRUE);
9746 freeAsmop (right, NULL, ic, TRUE);
9749 /*-----------------------------------------------------------------*/
9750 /* genPointerSet - stores the value into a pointer location */
9751 /*-----------------------------------------------------------------*/
9753 genPointerSet (iCode * ic, iCode *pi)
9755 operand *right, *result;
9756 sym_link *type, *etype;
9759 D (emitcode (";", "genPointerSet ");
9762 right = IC_RIGHT (ic);
9763 result = IC_RESULT (ic);
9765 /* depending on the type of pointer we need to
9766 move it to the correct pointer register */
9767 type = operandType (result);
9768 etype = getSpec (type);
9769 /* if left is of type of pointer then it is simple */
9770 if (IS_PTR (type) && !IS_FUNC (type->next))
9772 p_type = DCL_TYPE (type);
9776 /* we have to go by the storage class */
9777 p_type = PTR_TYPE (SPEC_OCLS (etype));
9779 /* special case when cast remat */
9780 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9781 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9782 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9783 type = type = operandType (result);
9784 p_type = DCL_TYPE (type);
9787 /* now that we have the pointer type we assign
9788 the pointer values */
9794 genNearPointerSet (right, result, ic, pi);
9798 genPagedPointerSet (right, result, ic, pi);
9802 genFarPointerSet (right, result, ic, pi);
9806 genGenPointerSet (right, result, ic, pi);
9812 /*-----------------------------------------------------------------*/
9813 /* genIfx - generate code for Ifx statement */
9814 /*-----------------------------------------------------------------*/
9816 genIfx (iCode * ic, iCode * popIc)
9818 operand *cond = IC_COND (ic);
9821 D (emitcode (";", "genIfx "););
9823 aopOp (cond, ic, FALSE, FALSE);
9825 /* get the value into acc */
9826 if (AOP_TYPE (cond) != AOP_CRY)
9830 /* the result is now in the accumulator */
9831 freeAsmop (cond, NULL, ic, TRUE);
9833 /* if there was something to be popped then do it */
9837 /* if the condition is a bit variable */
9838 if (isbit && IS_ITEMP (cond) &&
9840 genIfxJump (ic, SPIL_LOC (cond)->rname);
9841 else if (isbit && !IS_ITEMP (cond))
9842 genIfxJump (ic, OP_SYMBOL (cond)->rname);
9844 genIfxJump (ic, "a");
9849 /*-----------------------------------------------------------------*/
9850 /* genAddrOf - generates code for address of */
9851 /*-----------------------------------------------------------------*/
9853 genAddrOf (iCode * ic)
9855 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9858 D (emitcode (";", "genAddrOf ");
9861 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9863 /* if the operand is on the stack then we
9864 need to get the stack offset of this
9868 /* if 10 bit stack */
9869 if (options.stack10bit) {
9870 /* if it has an offset then we need to compute it */
9872 emitcode ("mov", "a,_bpx");
9873 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9874 emitcode ("mov", "b,a");
9875 emitcode ("mov", "a,_bpx+1");
9876 emitcode ("addc","a,#0x%02x", (((short) sym->stack) >> 8) & 0xff);
9877 aopPut (AOP (IC_RESULT (ic)), "b", 0);
9878 aopPut (AOP (IC_RESULT (ic)), "a", 1);
9879 aopPut (AOP (IC_RESULT (ic)), "#0x40", 2);
9881 /* we can just move _bp */
9882 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
9883 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
9884 aopPut (AOP (IC_RESULT (ic)), "#0x40", 2);
9887 /* if it has an offset then we need to compute it */
9889 emitcode ("mov", "a,_bp");
9890 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9891 aopPut (AOP (IC_RESULT (ic)), "a", 0);
9893 /* we can just move _bp */
9894 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9896 /* fill the result with zero */
9897 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9900 if (options.stack10bit && size < (FPTRSIZE - 1)) {
9902 "*** warning: pointer to stack var truncated.\n");
9907 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9913 /* object not on stack then we need the name */
9914 size = AOP_SIZE (IC_RESULT (ic));
9919 char s[SDCC_NAME_MAX];
9921 sprintf (s, "#(%s >> %d)",
9925 sprintf (s, "#%s", sym->rname);
9926 aopPut (AOP (IC_RESULT (ic)), s, offset++);
9930 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9934 /*-----------------------------------------------------------------*/
9935 /* genArrayInit - generates code for address of */
9936 /*-----------------------------------------------------------------*/
9938 genArrayInit (iCode * ic)
9942 int elementSize = 0, eIndex;
9943 unsigned val, lastVal;
9945 operand *left=IC_LEFT(ic);
9947 D (emitcode (";", "genArrayInit "););
9949 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
9951 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
9953 // Load immediate value into DPTR.
9954 emitcode("mov", "dptr, %s",
9955 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
9957 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
9960 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9961 "Unexpected operand to genArrayInit.\n");
9964 // a regression because of SDCCcse.c:1.52
9965 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9966 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9967 if (options.model == MODEL_FLAT24)
9968 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9972 type = operandType(IC_LEFT(ic));
9974 if (type && type->next)
9976 elementSize = getSize(type->next);
9980 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9981 "can't determine element size in genArrayInit.\n");
9985 iLoop = IC_ARRAYILIST(ic);
9990 bool firstpass = TRUE;
9992 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
9993 iLoop->count, (int)iLoop->literalValue, elementSize);
9999 symbol *tlbl = NULL;
10001 count = ix > 256 ? 256 : ix;
10005 tlbl = newiTempLabel (NULL);
10006 if (firstpass || (count & 0xff))
10008 emitcode("mov", "b, #0x%x", count & 0xff);
10011 emitcode ("", "%05d$:", tlbl->key + 100);
10016 for (eIndex = 0; eIndex < elementSize; eIndex++)
10018 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10019 if (val != lastVal)
10021 emitcode("mov", "a, #0x%x", val);
10025 emitcode("movx", "@dptr, a");
10026 emitcode("inc", "dptr");
10031 emitcode("djnz", "b, %05d$", tlbl->key + 100);
10037 iLoop = iLoop->next;
10040 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10043 /*-----------------------------------------------------------------*/
10044 /* genFarFarAssign - assignment when both are in far space */
10045 /*-----------------------------------------------------------------*/
10047 genFarFarAssign (operand * result, operand * right, iCode * ic)
10049 int size = AOP_SIZE (right);
10051 symbol *rSym = NULL;
10055 /* quick & easy case. */
10056 D(emitcode(";","genFarFarAssign (1 byte case)"););
10057 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
10058 freeAsmop (right, NULL, ic, FALSE);
10059 /* now assign DPTR to result */
10061 aopOp(result, ic, FALSE, FALSE);
10063 aopPut(AOP(result), "a", 0);
10064 freeAsmop(result, NULL, ic, FALSE);
10068 /* See if we've got an underlying symbol to abuse. */
10069 if (IS_SYMOP(result) && OP_SYMBOL(result))
10071 if (IS_TRUE_SYMOP(result))
10073 rSym = OP_SYMBOL(result);
10075 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10077 rSym = OP_SYMBOL(result)->usl.spillLoc;
10081 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10083 /* We can use the '390 auto-toggle feature to good effect here. */
10085 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10086 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
10087 emitcode ("mov", "dptr,#%s", rSym->rname);
10088 /* DP2 = result, DP1 = right, DP1 is current. */
10091 emitcode("movx", "a,@dptr");
10092 emitcode("movx", "@dptr,a");
10095 emitcode("inc", "dptr");
10096 emitcode("inc", "dptr");
10099 emitcode("mov", "dps, #0");
10100 freeAsmop (right, NULL, ic, FALSE);
10102 some alternative code for processors without auto-toggle
10103 no time to test now, so later well put in...kpb
10104 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10105 emitcode("mov", "dps, #0x01"); /* Select DPTR2. */
10106 emitcode ("mov", "dptr,#%s", rSym->rname);
10107 /* DP2 = result, DP1 = right, DP1 is current. */
10111 emitcode("movx", "a,@dptr");
10113 emitcode("inc", "dptr");
10114 emitcode("inc", "dps");
10115 emitcode("movx", "@dptr,a");
10117 emitcode("inc", "dptr");
10118 emitcode("inc", "dps");
10120 emitcode("mov", "dps, #0");
10121 freeAsmop (right, NULL, ic, FALSE);
10126 D (emitcode (";", "genFarFarAssign"););
10127 aopOp (result, ic, TRUE, TRUE);
10129 _startLazyDPSEvaluation ();
10133 aopPut (AOP (result),
10134 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10137 _endLazyDPSEvaluation ();
10138 freeAsmop (result, NULL, ic, FALSE);
10139 freeAsmop (right, NULL, ic, FALSE);
10143 /*-----------------------------------------------------------------*/
10144 /* genAssign - generate code for assignment */
10145 /*-----------------------------------------------------------------*/
10147 genAssign (iCode * ic)
10149 operand *result, *right;
10151 unsigned long lit = 0L;
10153 D (emitcode (";", "genAssign ");
10156 result = IC_RESULT (ic);
10157 right = IC_RIGHT (ic);
10159 /* if they are the same */
10160 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10163 aopOp (right, ic, FALSE, FALSE);
10165 emitcode (";", "genAssign: resultIsFar = %s",
10166 isOperandInFarSpace (result) ?
10169 /* special case both in far space */
10170 if ((AOP_TYPE (right) == AOP_DPTR ||
10171 AOP_TYPE (right) == AOP_DPTR2) &&
10172 /* IS_TRUE_SYMOP(result) && */
10173 isOperandInFarSpace (result))
10175 genFarFarAssign (result, right, ic);
10179 aopOp (result, ic, TRUE, FALSE);
10181 /* if they are the same registers */
10182 if (sameRegs (AOP (right), AOP (result)))
10185 /* if the result is a bit */
10186 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10188 /* if the right size is a literal then
10189 we know what the value is */
10190 if (AOP_TYPE (right) == AOP_LIT)
10192 if (((int) operandLitValue (right)))
10193 aopPut (AOP (result), one, 0);
10195 aopPut (AOP (result), zero, 0);
10199 /* the right is also a bit variable */
10200 if (AOP_TYPE (right) == AOP_CRY)
10202 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10203 aopPut (AOP (result), "c", 0);
10207 /* we need to or */
10209 aopPut (AOP (result), "a", 0);
10213 /* bit variables done */
10215 size = AOP_SIZE (result);
10217 if (AOP_TYPE (right) == AOP_LIT)
10218 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10221 (AOP_TYPE (result) != AOP_REG) &&
10222 (AOP_TYPE (right) == AOP_LIT) &&
10223 !IS_FLOAT (operandType (right)))
10225 _startLazyDPSEvaluation ();
10226 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10228 aopPut (AOP (result),
10229 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10234 /* And now fill the rest with zeros. */
10237 emitcode ("clr", "a");
10241 aopPut (AOP (result), "a", offset++);
10243 _endLazyDPSEvaluation ();
10247 _startLazyDPSEvaluation ();
10250 aopPut (AOP (result),
10251 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10255 _endLazyDPSEvaluation ();
10259 freeAsmop (right, NULL, ic, FALSE);
10260 freeAsmop (result, NULL, ic, TRUE);
10263 /*-----------------------------------------------------------------*/
10264 /* genJumpTab - generates code for jump table */
10265 /*-----------------------------------------------------------------*/
10267 genJumpTab (iCode * ic)
10272 D (emitcode (";", "genJumpTab ");
10275 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10276 /* get the condition into accumulator */
10277 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10279 /* multiply by four! */
10280 emitcode ("add", "a,acc");
10281 emitcode ("add", "a,acc");
10282 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10284 jtab = newiTempLabel (NULL);
10285 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10286 emitcode ("jmp", "@a+dptr");
10287 emitcode ("", "%05d$:", jtab->key + 100);
10288 /* now generate the jump labels */
10289 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10290 jtab = setNextItem (IC_JTLABELS (ic)))
10291 emitcode ("ljmp", "%05d$", jtab->key + 100);
10295 /*-----------------------------------------------------------------*/
10296 /* genCast - gen code for casting */
10297 /*-----------------------------------------------------------------*/
10299 genCast (iCode * ic)
10301 operand *result = IC_RESULT (ic);
10302 sym_link *ctype = operandType (IC_LEFT (ic));
10303 sym_link *rtype = operandType (IC_RIGHT (ic));
10304 operand *right = IC_RIGHT (ic);
10307 D (emitcode (";", "genCast ");
10310 /* if they are equivalent then do nothing */
10311 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10314 aopOp (right, ic, FALSE, FALSE);
10315 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10317 /* if the result is a bit */
10318 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10319 if (IS_BITVAR(OP_SYMBOL(result)->type))
10321 /* if the right size is a literal then
10322 we know what the value is */
10323 if (AOP_TYPE (right) == AOP_LIT)
10325 if (((int) operandLitValue (right)))
10326 aopPut (AOP (result), one, 0);
10328 aopPut (AOP (result), zero, 0);
10333 /* the right is also a bit variable */
10334 if (AOP_TYPE (right) == AOP_CRY)
10336 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10337 aopPut (AOP (result), "c", 0);
10341 /* we need to or */
10343 aopPut (AOP (result), "a", 0);
10347 /* if they are the same size : or less */
10348 if (AOP_SIZE (result) <= AOP_SIZE (right))
10351 /* if they are in the same place */
10352 if (sameRegs (AOP (right), AOP (result)))
10355 /* if they in different places then copy */
10356 size = AOP_SIZE (result);
10358 _startLazyDPSEvaluation ();
10361 aopPut (AOP (result),
10362 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10366 _endLazyDPSEvaluation ();
10371 /* if the result is of type pointer */
10372 if (IS_PTR (ctype))
10376 sym_link *type = operandType (right);
10378 /* pointer to generic pointer */
10379 if (IS_GENPTR (ctype))
10385 p_type = DCL_TYPE (type);
10389 #if OLD_CAST_BEHAVIOR
10390 /* KV: we are converting a non-pointer type to
10391 * a generic pointer. This (ifdef'd out) code
10392 * says that the resulting generic pointer
10393 * should have the same class as the storage
10394 * location of the non-pointer variable.
10396 * For example, converting an int (which happens
10397 * to be stored in DATA space) to a pointer results
10398 * in a DATA generic pointer; if the original int
10399 * in XDATA space, so will be the resulting pointer.
10401 * I don't like that behavior, and thus this change:
10402 * all such conversions will be forced to XDATA and
10403 * throw a warning. If you want some non-XDATA
10404 * type, or you want to suppress the warning, you
10405 * must go through an intermediate cast, like so:
10407 * char _generic *gp = (char _xdata *)(intVar);
10409 sym_link *etype = getSpec (type);
10411 /* we have to go by the storage class */
10412 if (SPEC_OCLS (etype) != generic)
10414 p_type = PTR_TYPE (SPEC_OCLS (etype));
10419 /* Converting unknown class (i.e. register variable)
10420 * to generic pointer. This is not good, but
10421 * we'll make a guess (and throw a warning).
10424 werror (W_INT_TO_GEN_PTR_CAST);
10428 /* the first two bytes are known */
10429 size = GPTRSIZE - 1;
10431 _startLazyDPSEvaluation ();
10434 aopPut (AOP (result),
10435 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10439 _endLazyDPSEvaluation ();
10441 /* the last byte depending on type */
10459 /* this should never happen */
10460 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10461 "got unknown pointer type");
10464 aopPut (AOP (result), l, GPTRSIZE - 1);
10468 /* just copy the pointers */
10469 size = AOP_SIZE (result);
10471 _startLazyDPSEvaluation ();
10474 aopPut (AOP (result),
10475 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10479 _endLazyDPSEvaluation ();
10483 /* so we now know that the size of destination is greater
10484 than the size of the source */
10485 /* we move to result for the size of source */
10486 size = AOP_SIZE (right);
10488 _startLazyDPSEvaluation ();
10491 aopPut (AOP (result),
10492 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10496 _endLazyDPSEvaluation ();
10498 /* now depending on the sign of the source && destination */
10499 size = AOP_SIZE (result) - AOP_SIZE (right);
10500 /* if unsigned or not an integral type */
10501 /* also, if the source is a bit, we don't need to sign extend, because
10502 * it can't possibly have set the sign bit.
10504 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10508 aopPut (AOP (result), zero, offset++);
10513 /* we need to extend the sign :{ */
10514 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10515 FALSE, FALSE, TRUE);
10517 emitcode ("rlc", "a");
10518 emitcode ("subb", "a,acc");
10520 aopPut (AOP (result), "a", offset++);
10523 /* we are done hurray !!!! */
10526 freeAsmop (right, NULL, ic, TRUE);
10527 freeAsmop (result, NULL, ic, TRUE);
10531 /*-----------------------------------------------------------------*/
10532 /* genDjnz - generate decrement & jump if not zero instrucion */
10533 /*-----------------------------------------------------------------*/
10535 genDjnz (iCode * ic, iCode * ifx)
10537 symbol *lbl, *lbl1;
10541 /* if the if condition has a false label
10542 then we cannot save */
10543 if (IC_FALSE (ifx))
10546 /* if the minus is not of the form
10548 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10549 !IS_OP_LITERAL (IC_RIGHT (ic)))
10552 if (operandLitValue (IC_RIGHT (ic)) != 1)
10555 /* if the size of this greater than one then no
10557 if (getSize (operandType (IC_RESULT (ic))) > 1)
10560 /* otherwise we can save BIG */
10561 D(emitcode(";", "genDjnz"););
10563 lbl = newiTempLabel (NULL);
10564 lbl1 = newiTempLabel (NULL);
10566 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10568 if (AOP_NEEDSACC(IC_RESULT(ic)))
10570 /* If the result is accessed indirectly via
10571 * the accumulator, we must explicitly write
10572 * it back after the decrement.
10574 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10576 if (strcmp(rByte, "a"))
10578 /* Something is hopelessly wrong */
10579 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10580 __FILE__, __LINE__);
10581 /* We can just give up; the generated code will be inefficient,
10582 * but what the hey.
10584 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10587 emitcode ("dec", "%s", rByte);
10588 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10589 emitcode ("jnz", "%05d$", lbl->key + 100);
10591 else if (IS_AOP_PREG (IC_RESULT (ic)))
10593 emitcode ("dec", "%s",
10594 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10595 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10596 emitcode ("jnz", "%05d$", lbl->key + 100);
10600 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10603 emitcode ("sjmp", "%05d$", lbl1->key + 100);
10604 emitcode ("", "%05d$:", lbl->key + 100);
10605 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10606 emitcode ("", "%05d$:", lbl1->key + 100);
10608 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10609 ifx->generated = 1;
10613 /*-----------------------------------------------------------------*/
10614 /* genReceive - generate code for a receive iCode */
10615 /*-----------------------------------------------------------------*/
10617 genReceive (iCode * ic)
10620 D (emitcode (";", "genReceive ");
10623 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10624 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10625 IS_TRUE_SYMOP (IC_RESULT (ic))))
10627 int size = getSize (operandType (IC_RESULT (ic)));
10628 int offset = fReturnSizeDS390 - size;
10631 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10632 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10635 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10636 size = AOP_SIZE (IC_RESULT (ic));
10640 emitcode ("pop", "acc");
10641 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10648 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10650 assignResultValue (IC_RESULT (ic));
10653 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10656 /*-----------------------------------------------------------------*/
10657 /* gen390Code - generate code for Dallas 390 based controllers */
10658 /*-----------------------------------------------------------------*/
10660 gen390Code (iCode * lic)
10665 lineHead = lineCurr = NULL;
10667 if (options.model == MODEL_FLAT24) {
10668 fReturnSizeDS390 = 5;
10669 fReturn = fReturn24;
10671 fReturnSizeDS390 = 4;
10672 fReturn = fReturn16;
10673 options.stack10bit=0;
10677 /* print the allocation information */
10679 printAllocInfo (currFunc, codeOutFile);
10681 /* if debug information required */
10682 if (options.debug && currFunc)
10684 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
10686 if (IS_STATIC (currFunc->etype))
10687 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
10689 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
10692 /* stack pointer name */
10693 if (options.useXstack)
10699 for (ic = lic; ic; ic = ic->next)
10702 if (cln != ic->lineno)
10707 emitcode ("", "C$%s$%d$%d$%d ==.",
10708 FileBaseName (ic->filename), ic->lineno,
10709 ic->level, ic->block);
10712 emitcode (";", "%s %d", ic->filename, ic->lineno);
10715 /* if the result is marked as
10716 spilt and rematerializable or code for
10717 this has already been generated then
10719 if (resultRemat (ic) || ic->generated)
10722 /* depending on the operation */
10742 /* IPOP happens only when trying to restore a
10743 spilt live range, if there is an ifx statement
10744 following this pop then the if statement might
10745 be using some of the registers being popped which
10746 would destory the contents of the register so
10747 we need to check for this condition and handle it */
10749 ic->next->op == IFX &&
10750 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10751 genIfx (ic->next, ic);
10769 genEndFunction (ic);
10789 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10806 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10810 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10817 /* note these two are xlated by algebraic equivalence
10818 during parsing SDCC.y */
10819 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10820 "got '>=' or '<=' shouldn't have come here");
10824 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10836 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10840 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10844 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10868 genRightShift (ic);
10871 case GET_VALUE_AT_ADDRESS:
10872 genPointerGet (ic,hasInc(IC_LEFT(ic),ic));
10876 if (POINTER_SET (ic))
10877 genPointerSet (ic,hasInc(IC_RESULT(ic),ic));
10903 addSet (&_G.sendSet, ic);
10916 /* now we are ready to call the
10917 peep hole optimizer */
10918 if (!options.nopeep)
10919 peepHole (&lineHead);
10921 /* now do the actual printing */
10922 printLine (lineHead, codeOutFile);