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,_bpx+1");
471 emitcode ("subb","a,#0x%02x",(-((sym->stack < 0) ?
472 ((short) (sym->stack - _G.nRegsSaved)) :
473 ((short) sym->stack)) >> 8) & 0xff);
475 if (options.model == MODEL_FLAT24)
476 emitcode ("mov", "dpx1,#0x%02x", (options.stack_loc >> 16) & 0xff);
478 emitcode ("mov", "dph1,a");
479 emitcode ("mov", "dpl1,b");
481 if (options.model == MODEL_FLAT24)
482 emitcode ("mov", "dpx,#0x%02x", (options.stack_loc >> 16) & 0xff);
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_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))) return ;
1805 /* special case if DPTR alive across a function call then must save it
1806 even though callee saves */
1807 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
1809 rsave = newBitVect(ic->rMask->size);
1810 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
1811 if (bitVectBitValue(ic->rMask,i))
1812 rsave = bitVectSetBit(rsave,i);
1815 /* find the registers in use at this time
1816 and push them away to safety */
1817 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1821 if (options.useXstack)
1823 if (bitVectBitValue (rsave, R0_IDX))
1824 emitcode ("mov", "b,r0");
1825 emitcode ("mov", "r0,%s", spname);
1826 for (i = 0; i < ds390_nRegs; i++)
1828 if (bitVectBitValue (rsave, i))
1831 emitcode ("mov", "a,b");
1833 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1834 emitcode ("movx", "@r0,a");
1835 emitcode ("inc", "r0");
1838 emitcode ("mov", "%s,r0", spname);
1839 if (bitVectBitValue (rsave, R0_IDX))
1840 emitcode ("mov", "r0,b");
1843 for (i = 0; i < ds390_nRegs; i++)
1845 if (bitVectBitValue (rsave, i))
1846 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1849 detype = getSpec (operandType (IC_LEFT (ic)));
1852 /*-----------------------------------------------------------------*/
1853 /* unsaveRegisters - pop the pushed registers */
1854 /*-----------------------------------------------------------------*/
1856 unsaveRegisters (iCode * ic)
1861 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
1863 rsave = newBitVect(ic->rMask->size);
1864 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
1865 if (bitVectBitValue(ic->rMask,i))
1866 rsave = bitVectSetBit(rsave,i);
1869 /* find the registers in use at this time
1870 and push them away to safety */
1871 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1874 if (options.useXstack)
1876 emitcode ("mov", "r0,%s", spname);
1877 for (i = ds390_nRegs; i >= 0; i--)
1879 if (bitVectBitValue (rsave, i))
1881 emitcode ("dec", "r0");
1882 emitcode ("movx", "a,@r0");
1884 emitcode ("mov", "b,a");
1886 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1890 emitcode ("mov", "%s,r0", spname);
1891 if (bitVectBitValue (rsave, R0_IDX))
1892 emitcode ("mov", "r0,b");
1895 for (i = ds390_nRegs; i >= 0; i--)
1897 if (bitVectBitValue (rsave, i))
1898 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1904 /*-----------------------------------------------------------------*/
1906 /*-----------------------------------------------------------------*/
1908 pushSide (operand * oper, int size)
1911 _startLazyDPSEvaluation ();
1914 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1915 if (AOP_TYPE (oper) != AOP_REG &&
1916 AOP_TYPE (oper) != AOP_DIR &&
1919 emitcode ("mov", "a,%s", l);
1920 emitcode ("push", "acc");
1923 emitcode ("push", "%s", l);
1925 _endLazyDPSEvaluation ();
1928 /*-----------------------------------------------------------------*/
1929 /* assignResultValue - */
1930 /*-----------------------------------------------------------------*/
1932 assignResultValue (operand * oper)
1935 int size = AOP_SIZE (oper);
1937 _startLazyDPSEvaluation ();
1940 aopPut (AOP (oper), fReturn[offset], offset);
1943 _endLazyDPSEvaluation ();
1947 /*-----------------------------------------------------------------*/
1948 /* genXpush - pushes onto the external stack */
1949 /*-----------------------------------------------------------------*/
1951 genXpush (iCode * ic)
1953 asmop *aop = newAsmop (0);
1955 int size, offset = 0;
1957 D (emitcode (";", "genXpush ");
1960 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1961 r = getFreePtr (ic, &aop, FALSE);
1964 emitcode ("mov", "%s,_spx", r->name);
1966 size = AOP_SIZE (IC_LEFT (ic));
1967 _startLazyDPSEvaluation ();
1971 char *l = aopGet (AOP (IC_LEFT (ic)),
1972 offset++, FALSE, FALSE, TRUE);
1974 emitcode ("movx", "@%s,a", r->name);
1975 emitcode ("inc", "%s", r->name);
1978 _endLazyDPSEvaluation ();
1981 emitcode ("mov", "_spx,%s", r->name);
1983 freeAsmop (NULL, aop, ic, TRUE);
1984 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1987 /*-----------------------------------------------------------------*/
1988 /* genIpush - genrate code for pushing this gets a little complex */
1989 /*-----------------------------------------------------------------*/
1991 genIpush (iCode * ic)
1993 int size, offset = 0;
1996 D (emitcode (";", "genIpush ");
1999 /* if this is not a parm push : ie. it is spill push
2000 and spill push is always done on the local stack */
2004 /* and the item is spilt then do nothing */
2005 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2008 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2009 size = AOP_SIZE (IC_LEFT (ic));
2010 /* push it on the stack */
2011 _startLazyDPSEvaluation ();
2014 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
2020 emitcode ("push", "%s", l);
2022 _endLazyDPSEvaluation ();
2026 /* this is a paramter push: in this case we call
2027 the routine to find the call and save those
2028 registers that need to be saved */
2031 /* if use external stack then call the external
2032 stack pushing routine */
2033 if (options.useXstack)
2039 /* then do the push */
2040 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2042 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2043 size = AOP_SIZE (IC_LEFT (ic));
2045 _startLazyDPSEvaluation ();
2048 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2049 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2050 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2053 emitcode ("mov", "a,%s", l);
2054 emitcode ("push", "acc");
2057 emitcode ("push", "%s", l);
2059 _endLazyDPSEvaluation ();
2061 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2064 /*-----------------------------------------------------------------*/
2065 /* genIpop - recover the registers: can happen only for spilling */
2066 /*-----------------------------------------------------------------*/
2068 genIpop (iCode * ic)
2072 D (emitcode (";", "genIpop ");
2076 /* if the temp was not pushed then */
2077 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2080 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2081 size = AOP_SIZE (IC_LEFT (ic));
2082 offset = (size - 1);
2083 _startLazyDPSEvaluation ();
2086 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2087 FALSE, TRUE, TRUE));
2089 _endLazyDPSEvaluation ();
2091 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2094 /*-----------------------------------------------------------------*/
2095 /* unsaveRBank - restores the resgister bank from stack */
2096 /*-----------------------------------------------------------------*/
2098 unsaveRBank (int bank, iCode * ic, bool popPsw)
2104 if (options.useXstack)
2108 /* Assume r0 is available for use. */
2109 r = ds390_regWithIdx (R0_IDX);;
2114 r = getFreePtr (ic, &aop, FALSE);
2116 emitcode ("mov", "%s,_spx", r->name);
2121 if (options.useXstack)
2123 emitcode ("movx", "a,@%s", r->name);
2124 emitcode ("mov", "psw,a");
2125 emitcode ("dec", "%s", r->name);
2129 emitcode ("pop", "psw");
2133 for (i = (ds390_nRegs - 1); i >= 0; i--)
2135 if (options.useXstack)
2137 emitcode ("movx", "a,@%s", r->name);
2138 emitcode ("mov", "(%s+%d),a",
2139 regs390[i].base, 8 * bank + regs390[i].offset);
2140 emitcode ("dec", "%s", r->name);
2144 emitcode ("pop", "(%s+%d)",
2145 regs390[i].base, 8 * bank + regs390[i].offset);
2148 if (options.useXstack)
2150 emitcode ("mov", "_spx,%s", r->name);
2155 freeAsmop (NULL, aop, ic, TRUE);
2159 /*-----------------------------------------------------------------*/
2160 /* saveRBank - saves an entire register bank on the stack */
2161 /*-----------------------------------------------------------------*/
2163 saveRBank (int bank, iCode * ic, bool pushPsw)
2169 if (options.useXstack)
2173 /* Assume r0 is available for use. */
2174 r = ds390_regWithIdx (R0_IDX);;
2179 r = getFreePtr (ic, &aop, FALSE);
2181 emitcode ("mov", "%s,_spx", r->name);
2184 for (i = 0; i < ds390_nRegs; i++)
2186 if (options.useXstack)
2188 emitcode ("inc", "%s", r->name);
2189 emitcode ("mov", "a,(%s+%d)",
2190 regs390[i].base, 8 * bank + regs390[i].offset);
2191 emitcode ("movx", "@%s,a", r->name);
2194 emitcode ("push", "(%s+%d)",
2195 regs390[i].base, 8 * bank + regs390[i].offset);
2200 if (options.useXstack)
2202 emitcode ("mov", "a,psw");
2203 emitcode ("movx", "@%s,a", r->name);
2204 emitcode ("inc", "%s", r->name);
2205 emitcode ("mov", "_spx,%s", r->name);
2209 emitcode ("push", "psw");
2212 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2217 freeAsmop (NULL, aop, ic, TRUE);
2226 /*-----------------------------------------------------------------*/
2227 /* genCall - generates a call statement */
2228 /*-----------------------------------------------------------------*/
2230 genCall (iCode * ic)
2233 bool restoreBank = FALSE;
2234 bool swapBanks = FALSE;
2236 D (emitcode (";", "genCall "););
2238 /* if we are calling a not _naked function that is not using
2239 the same register bank then we need to save the
2240 destination registers on the stack */
2241 dtype = operandType (IC_LEFT (ic));
2242 if (dtype && !IFFUNC_ISNAKED(dtype) &&
2243 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2244 IFFUNC_ISISR (currFunc->type))
2248 /* This is unexpected; the bank should have been saved in
2251 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2257 /* if caller saves & we have not saved then */
2261 /* if send set is not empty the assign */
2262 /* We've saved all the registers we care about;
2263 * therefore, we may clobber any register not used
2264 * in the calling convention (i.e. anything not in
2271 for (sic = setFirstItem (_G.sendSet); sic;
2272 sic = setNextItem (_G.sendSet))
2274 int size, offset = 0;
2277 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2278 size = AOP_SIZE (IC_LEFT (sic));
2280 _startLazyDPSEvaluation ();
2283 char *l = aopGet (AOP(IC_LEFT(sic)), offset,
2284 FALSE, FALSE, TRUE);
2285 if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size)
2287 emitcode("mov", "%s,%s", regs390[offset].name, l);
2289 else if (strcmp (l, fReturn[offset]))
2291 emitcode ("mov", "%s,%s",
2297 _endLazyDPSEvaluation ();
2298 if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR)
2300 size = AOP_SIZE (IC_LEFT (sic));
2308 emitcode("mov", "%s,%s",
2309 fReturn[size], regs390[size].name);
2313 // we know that dpl(hxb) is the result, so
2314 _startLazyDPSEvaluation ();
2315 size=getSize(operandType(IC_LEFT(sic)));
2317 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2319 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2323 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2324 FALSE, FALSE, TRUE);
2325 if (strcmp (l, fReturn[offset]))
2327 emitcode ("mov", "%s,%s",
2333 _endLazyDPSEvaluation ();
2335 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2342 emitcode ("mov", "psw,#0x%02x",
2343 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2347 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2348 OP_SYMBOL (IC_LEFT (ic))->rname :
2349 OP_SYMBOL (IC_LEFT (ic))->name));
2353 emitcode ("mov", "psw,#0x%02x",
2354 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2357 /* if we need assign a result value */
2358 if ((IS_ITEMP (IC_RESULT (ic)) &&
2359 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2360 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2361 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2362 IS_TRUE_SYMOP (IC_RESULT (ic)))
2364 if (isOperandInFarSpace (IC_RESULT (ic))
2365 && getSize (operandType (IC_RESULT (ic))) <= 2)
2367 int size = getSize (operandType (IC_RESULT (ic)));
2369 /* Special case for 1 or 2 byte return in far space. */
2373 emitcode ("mov", "b,%s", fReturn[1]);
2376 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2377 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2381 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2383 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2388 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2391 assignResultValue (IC_RESULT (ic));
2393 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2397 /* adjust the stack for parameters if
2399 if (ic->parmBytes) {
2400 if (options.stack10bit) {
2401 emitcode ("clr","c");
2402 emitcode ("mov","a,sp");
2403 emitcode ("subb","a,#0x%02x",ic->parmBytes & 0xff);
2404 emitcode ("mov","sp,a");
2405 emitcode ("mov","a,esp");
2406 emitcode ("subb","a,#0x%02x",(ic->parmBytes >> 8) & 0xff);
2407 emitcode ("mov","esp,a");
2410 if (ic->parmBytes > 3) {
2411 emitcode ("mov", "a,%s", spname);
2412 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2413 emitcode ("mov", "%s,a", spname);
2415 for (i = 0; i < ic->parmBytes; i++)
2416 emitcode ("dec", "%s", spname);
2420 /* if we hade saved some registers then unsave them */
2422 unsaveRegisters (ic);
2424 /* if register bank was saved then pop them */
2426 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2429 /*-----------------------------------------------------------------*/
2430 /* genPcall - generates a call by pointer statement */
2431 /*-----------------------------------------------------------------*/
2433 genPcall (iCode * ic)
2436 symbol *rlbl = newiTempLabel (NULL);
2437 bool restoreBank=FALSE;
2439 D (emitcode (";", "genPcall ");
2443 /* if caller saves & we have not saved then */
2447 /* if we are calling a function that is not using
2448 the same register bank then we need to save the
2449 destination registers on the stack */
2450 dtype = operandType (IC_LEFT (ic));
2451 if (dtype && !IFFUNC_ISNAKED(dtype) &&
2452 IFFUNC_ISISR (currFunc->type) &&
2453 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2454 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2458 /* push the return address on to the stack */
2459 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2460 emitcode ("push", "acc");
2461 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2462 emitcode ("push", "acc");
2464 if (options.model == MODEL_FLAT24)
2466 emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2467 emitcode ("push", "acc");
2470 /* now push the calling address */
2471 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2473 pushSide (IC_LEFT (ic), FPTRSIZE);
2475 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2477 /* if send set is not empty the assign */
2482 for (sic = setFirstItem (_G.sendSet); sic;
2483 sic = setNextItem (_G.sendSet))
2485 int size, offset = 0;
2487 // we know that dpl(hxb) is the result, so
2488 _startLazyDPSEvaluation ();
2489 size=getSize(operandType(IC_LEFT(sic)));
2491 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2493 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2497 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2498 FALSE, FALSE, TRUE);
2499 if (strcmp (l, fReturn[offset]))
2501 emitcode ("mov", "%s,%s",
2507 _endLazyDPSEvaluation ();
2508 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2513 emitcode ("ret", "");
2514 emitcode ("", "%05d$:", (rlbl->key + 100));
2517 /* if we need assign a result value */
2518 if ((IS_ITEMP (IC_RESULT (ic)) &&
2519 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2520 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2521 IS_TRUE_SYMOP (IC_RESULT (ic)))
2525 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2528 assignResultValue (IC_RESULT (ic));
2530 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2533 /* adjust the stack for parameters if
2538 if (ic->parmBytes > 3)
2540 emitcode ("mov", "a,%s", spname);
2541 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2542 emitcode ("mov", "%s,a", spname);
2545 for (i = 0; i < ic->parmBytes; i++)
2546 emitcode ("dec", "%s", spname);
2550 /* if register bank was saved then unsave them */
2552 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2554 /* if we hade saved some registers then
2557 unsaveRegisters (ic);
2561 /*-----------------------------------------------------------------*/
2562 /* resultRemat - result is rematerializable */
2563 /*-----------------------------------------------------------------*/
2565 resultRemat (iCode * ic)
2567 if (SKIP_IC (ic) || ic->op == IFX)
2570 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2572 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2573 if (sym->remat && !POINTER_SET (ic))
2580 #if defined(__BORLANDC__) || defined(_MSC_VER)
2581 #define STRCASECMP stricmp
2583 #define STRCASECMP strcasecmp
2586 /*-----------------------------------------------------------------*/
2587 /* inExcludeList - return 1 if the string is in exclude Reg list */
2588 /*-----------------------------------------------------------------*/
2590 inExcludeList (char *s)
2594 if (options.excludeRegs[i] &&
2595 STRCASECMP (options.excludeRegs[i], "none") == 0)
2598 for (i = 0; options.excludeRegs[i]; i++)
2600 if (options.excludeRegs[i] &&
2601 STRCASECMP (s, options.excludeRegs[i]) == 0)
2607 /*-----------------------------------------------------------------*/
2608 /* genFunction - generated code for function entry */
2609 /*-----------------------------------------------------------------*/
2611 genFunction (iCode * ic)
2615 bool switchedPSW = FALSE;
2617 D (emitcode (";", "genFunction "););
2620 /* create the function header */
2621 emitcode (";", "-----------------------------------------");
2622 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2623 emitcode (";", "-----------------------------------------");
2625 emitcode ("", "%s:", sym->rname);
2626 ftype = operandType (IC_LEFT (ic));
2628 if (IFFUNC_ISNAKED(ftype))
2630 emitcode(";", "naked function: no prologue.");
2634 /* if critical function then turn interrupts off */
2635 if (IFFUNC_ISCRITICAL (ftype))
2636 emitcode ("clr", "ea");
2638 /* here we need to generate the equates for the
2639 register bank if required */
2640 if (FUNC_REGBANK (ftype) != rbank)
2644 rbank = FUNC_REGBANK (ftype);
2645 for (i = 0; i < ds390_nRegs; i++)
2647 if (regs390[i].print) {
2648 if (strcmp (regs390[i].base, "0") == 0)
2649 emitcode ("", "%s = 0x%02x",
2651 8 * rbank + regs390[i].offset);
2653 emitcode ("", "%s = %s + 0x%02x",
2656 8 * rbank + regs390[i].offset);
2661 /* if this is an interrupt service routine then
2662 save acc, b, dpl, dph */
2663 if (IFFUNC_ISISR (sym->type))
2666 if (!inExcludeList ("acc"))
2667 emitcode ("push", "acc");
2668 if (!inExcludeList ("b"))
2669 emitcode ("push", "b");
2670 if (!inExcludeList ("dpl"))
2671 emitcode ("push", "dpl");
2672 if (!inExcludeList ("dph"))
2673 emitcode ("push", "dph");
2674 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2676 emitcode ("push", "dpx");
2677 /* Make sure we're using standard DPTR */
2678 emitcode ("push", "dps");
2679 emitcode ("mov", "dps, #0x00");
2680 if (options.stack10bit)
2682 /* This ISR could conceivably use DPTR2. Better save it. */
2683 emitcode ("push", "dpl1");
2684 emitcode ("push", "dph1");
2685 emitcode ("push", "dpx1");
2686 emitcode ("push", DP2_RESULT_REG);
2689 /* if this isr has no bank i.e. is going to
2690 run with bank 0 , then we need to save more
2692 if (!FUNC_REGBANK (sym->type))
2695 /* if this function does not call any other
2696 function then we can be economical and
2697 save only those registers that are used */
2698 if (!IFFUNC_HASFCALL(sym->type))
2702 /* if any registers used */
2705 /* save the registers used */
2706 for (i = 0; i < sym->regsUsed->size; i++)
2708 if (bitVectBitValue (sym->regsUsed, i) ||
2709 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2710 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2717 /* this function has a function call cannot
2718 determines register usage so we will have to push the
2720 saveRBank (0, ic, FALSE);
2725 /* This ISR uses a non-zero bank.
2727 * We assume that the bank is available for our
2730 * However, if this ISR calls a function which uses some
2731 * other bank, we must save that bank entirely.
2733 unsigned long banksToSave = 0;
2735 if (IFFUNC_HASFCALL(sym->type))
2738 #define MAX_REGISTER_BANKS 4
2743 for (i = ic; i; i = i->next)
2745 if (i->op == ENDFUNCTION)
2747 /* we got to the end OK. */
2755 dtype = operandType (IC_LEFT(i));
2757 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2759 /* Mark this bank for saving. */
2760 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2762 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2766 banksToSave |= (1 << FUNC_REGBANK(dtype));
2769 /* And note that we don't need to do it in
2777 /* This is a mess; we have no idea what
2778 * register bank the called function might
2781 * The only thing I can think of to do is
2782 * throw a warning and hope.
2784 werror(W_FUNCPTR_IN_USING_ISR);
2788 if (banksToSave && options.useXstack)
2790 /* Since we aren't passing it an ic,
2791 * saveRBank will assume r0 is available to abuse.
2793 * So switch to our (trashable) bank now, so
2794 * the caller's R0 isn't trashed.
2796 emitcode ("push", "psw");
2797 emitcode ("mov", "psw,#0x%02x",
2798 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2802 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2804 if (banksToSave & (1 << ix))
2806 saveRBank(ix, NULL, FALSE);
2810 // jwk: this needs a closer look
2811 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2816 /* if callee-save to be used for this function
2817 then save the registers being used in this function */
2818 if (IFFUNC_CALLEESAVES(sym->type))
2822 /* if any registers used */
2825 /* save the registers used */
2826 for (i = 0; i < sym->regsUsed->size; i++)
2828 if (bitVectBitValue (sym->regsUsed, i) ||
2829 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2831 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2839 /* set the register bank to the desired value */
2840 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2843 emitcode ("push", "psw");
2844 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2847 if (IFFUNC_ISREENT (sym->type) || options.stackAuto) {
2848 if (options.stack10bit) {
2849 emitcode ("push","_bpx");
2850 emitcode ("push","_bpx+1");
2851 emitcode ("mov","_bpx,%s",spname);
2852 emitcode ("mov","_bpx+1,esp");
2853 emitcode ("anl","_bpx+1,#3");
2855 if (options.useXstack) {
2856 emitcode ("mov", "r0,%s", spname);
2857 emitcode ("mov", "a,_bp");
2858 emitcode ("movx", "@r0,a");
2859 emitcode ("inc", "%s", spname);
2861 /* set up the stack */
2862 emitcode ("push", "_bp"); /* save the callers stack */
2864 emitcode ("mov", "_bp,%s", spname);
2868 /* adjust the stack for the function */
2871 if (options.stack10bit) {
2872 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
2873 assert (sym->recvSize <= 4);
2874 emitcode ("mov","a,sp");
2875 emitcode ("add","a,#0x%02x", ((short) sym->stack & 0xff));
2876 emitcode ("mov","sp,a");
2877 emitcode ("mov","a,esp");
2878 emitcode ("addc","a,#0x%02x", (((short) sym->stack) >> 8) & 0xff);
2879 emitcode ("mov","esp,a");
2882 werror (W_STACK_OVERFLOW, sym->name);
2884 if (i > 3 && sym->recvSize < 4) {
2886 emitcode ("mov", "a,sp");
2887 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2888 emitcode ("mov", "sp,a");
2892 emitcode ("inc", "sp");
2899 emitcode ("mov", "a,_spx");
2900 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2901 emitcode ("mov", "_spx,a");
2906 /*-----------------------------------------------------------------*/
2907 /* genEndFunction - generates epilogue for functions */
2908 /*-----------------------------------------------------------------*/
2910 genEndFunction (iCode * ic)
2912 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2914 D (emitcode (";", "genEndFunction "););
2916 if (IFFUNC_ISNAKED(sym->type))
2918 emitcode(";", "naked function: no epilogue.");
2922 if (IFFUNC_ISREENT (sym->type) || options.stackAuto) {
2923 if (options.stack10bit) {
2924 emitcode ("mov", "sp,_bpx", spname);
2925 emitcode ("mov", "esp,_bpx+1", spname);
2927 emitcode ("mov", "%s,_bp", spname);
2931 /* if use external stack but some variables were
2932 added to the local stack then decrement the
2934 if (options.useXstack && sym->stack) {
2935 emitcode ("mov", "a,sp");
2936 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2937 emitcode ("mov", "sp,a");
2941 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto)) {
2942 if (options.useXstack) {
2943 emitcode ("mov", "r0,%s", spname);
2944 emitcode ("movx", "a,@r0");
2945 emitcode ("mov", "_bp,a");
2946 emitcode ("dec", "%s", spname);
2948 if (options.stack10bit) {
2949 emitcode ("pop", "_bpx+1");
2950 emitcode ("pop", "_bpx");
2952 emitcode ("pop", "_bp");
2957 /* restore the register bank */
2958 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2960 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
2961 || !options.useXstack)
2963 /* Special case of ISR using non-zero bank with useXstack
2966 emitcode ("pop", "psw");
2970 if (IFFUNC_ISISR (sym->type))
2973 /* now we need to restore the registers */
2974 /* if this isr has no bank i.e. is going to
2975 run with bank 0 , then we need to save more
2977 if (!FUNC_REGBANK (sym->type))
2979 /* if this function does not call any other
2980 function then we can be economical and
2981 save only those registers that are used */
2982 if (!IFFUNC_HASFCALL(sym->type))
2986 /* if any registers used */
2989 /* save the registers used */
2990 for (i = sym->regsUsed->size; i >= 0; i--)
2992 if (bitVectBitValue (sym->regsUsed, i) ||
2993 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2994 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3001 /* this function has a function call cannot
3002 determines register usage so we will have to pop the
3004 unsaveRBank (0, ic, FALSE);
3009 /* This ISR uses a non-zero bank.
3011 * Restore any register banks saved by genFunction
3014 // jwk: this needs a closer look
3015 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3018 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3020 if (savedBanks & (1 << ix))
3022 unsaveRBank(ix, NULL, FALSE);
3026 if (options.useXstack)
3028 /* Restore bank AFTER calling unsaveRBank,
3029 * since it can trash r0.
3031 emitcode ("pop", "psw");
3035 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3037 if (options.stack10bit)
3039 emitcode ("pop", DP2_RESULT_REG);
3040 emitcode ("pop", "dpx1");
3041 emitcode ("pop", "dph1");
3042 emitcode ("pop", "dpl1");
3044 emitcode ("pop", "dps");
3045 emitcode ("pop", "dpx");
3047 if (!inExcludeList ("dph"))
3048 emitcode ("pop", "dph");
3049 if (!inExcludeList ("dpl"))
3050 emitcode ("pop", "dpl");
3051 if (!inExcludeList ("b"))
3052 emitcode ("pop", "b");
3053 if (!inExcludeList ("acc"))
3054 emitcode ("pop", "acc");
3056 if (IFFUNC_ISCRITICAL (sym->type))
3057 emitcode ("setb", "ea");
3059 /* if debug then send end of function */
3060 if (options.debug && currFunc) {
3062 emitcode ("", "C$%s$%d$%d$%d ==.",
3063 FileBaseName (ic->filename), currFunc->lastLine,
3064 ic->level, ic->block);
3065 if (IS_STATIC (currFunc->etype))
3066 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3068 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3072 emitcode ("reti", "");
3076 if (IFFUNC_ISCRITICAL (sym->type))
3077 emitcode ("setb", "ea");
3079 if (IFFUNC_CALLEESAVES(sym->type))
3083 /* if any registers used */
3086 /* save the registers used */
3087 for (i = sym->regsUsed->size; i >= 0; i--)
3089 if (bitVectBitValue (sym->regsUsed, i) ||
3090 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3091 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3097 /* if debug then send end of function */
3098 if (options.debug && currFunc)
3101 emitcode ("", "C$%s$%d$%d$%d ==.",
3102 FileBaseName (ic->filename), currFunc->lastLine,
3103 ic->level, ic->block);
3104 if (IS_STATIC (currFunc->etype))
3105 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3107 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3111 emitcode ("ret", "");
3116 /*-----------------------------------------------------------------*/
3117 /* genRet - generate code for return statement */
3118 /*-----------------------------------------------------------------*/
3122 int size, offset = 0, pushed = 0;
3124 D (emitcode (";", "genRet ");
3127 /* if we have no return value then
3128 just generate the "ret" */
3132 /* we have something to return then
3133 move the return value into place */
3134 aopOp (IC_LEFT (ic), ic, FALSE,
3135 (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3136 size = AOP_SIZE (IC_LEFT (ic));
3138 _startLazyDPSEvaluation ();
3142 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3144 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3145 FALSE, TRUE, FALSE);
3146 emitcode ("push", "%s", l);
3151 /* Since A is the last element of fReturn,
3152 * is is OK to clobber it in the aopGet.
3154 l = aopGet (AOP (IC_LEFT (ic)), offset,
3155 FALSE, FALSE, TRUE);
3156 if (strcmp (fReturn[offset], l))
3157 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3160 _endLazyDPSEvaluation ();
3167 if (strcmp (fReturn[pushed], "a"))
3168 emitcode ("pop", fReturn[pushed]);
3170 emitcode ("pop", "acc");
3173 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3176 /* generate a jump to the return label
3177 if the next is not the return statement */
3178 if (!(ic->next && ic->next->op == LABEL &&
3179 IC_LABEL (ic->next) == returnLabel))
3181 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3185 /*-----------------------------------------------------------------*/
3186 /* genLabel - generates a label */
3187 /*-----------------------------------------------------------------*/
3189 genLabel (iCode * ic)
3191 /* special case never generate */
3192 if (IC_LABEL (ic) == entryLabel)
3195 D (emitcode (";", "genLabel ");
3198 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3201 /*-----------------------------------------------------------------*/
3202 /* genGoto - generates a ljmp */
3203 /*-----------------------------------------------------------------*/
3205 genGoto (iCode * ic)
3207 D (emitcode (";", "genGoto ");
3209 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3212 /*-----------------------------------------------------------------*/
3213 /* findLabelBackwards: walks back through the iCode chain looking */
3214 /* for the given label. Returns number of iCode instructions */
3215 /* between that label and given ic. */
3216 /* Returns zero if label not found. */
3217 /*-----------------------------------------------------------------*/
3219 findLabelBackwards (iCode * ic, int key)
3228 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3230 /* printf("findLabelBackwards = %d\n", count); */
3238 /*-----------------------------------------------------------------*/
3239 /* genPlusIncr :- does addition with increment if possible */
3240 /*-----------------------------------------------------------------*/
3242 genPlusIncr (iCode * ic)
3244 unsigned int icount;
3245 unsigned int size = getDataSize (IC_RESULT (ic));
3247 /* will try to generate an increment */
3248 /* if the right side is not a literal
3250 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3253 /* if the literal value of the right hand side
3254 is greater than 4 then it is not worth it */
3255 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3258 /* if increment 16 bits in register */
3260 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3261 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3262 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3270 /* If the next instruction is a goto and the goto target
3271 * is <= 5 instructions previous to this, we can generate
3272 * jumps straight to that target.
3274 if (ic->next && ic->next->op == GOTO
3275 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3278 emitcode (";", "tail increment optimized (range %d)", labelRange);
3279 tlbl = IC_LABEL (ic->next);
3284 tlbl = newiTempLabel (NULL);
3287 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3288 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3289 IS_AOP_PREG (IC_RESULT (ic)))
3290 emitcode ("cjne", "%s,#0x00,%05d$"
3291 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3295 emitcode ("clr", "a");
3296 emitcode ("cjne", "a,%s,%05d$"
3297 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3301 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3304 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3305 IS_AOP_PREG (IC_RESULT (ic)))
3306 emitcode ("cjne", "%s,#0x00,%05d$"
3307 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3310 emitcode ("cjne", "a,%s,%05d$"
3311 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3314 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3318 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3319 IS_AOP_PREG (IC_RESULT (ic)))
3320 emitcode ("cjne", "%s,#0x00,%05d$"
3321 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3325 emitcode ("cjne", "a,%s,%05d$"
3326 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3329 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3334 emitcode ("", "%05d$:", tlbl->key + 100);
3339 /* if the sizes are greater than 1 then we cannot */
3340 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3341 AOP_SIZE (IC_LEFT (ic)) > 1)
3344 /* we can if the aops of the left & result match or
3345 if they are in registers and the registers are the
3348 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3349 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3350 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3355 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3356 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3357 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3362 _startLazyDPSEvaluation ();
3365 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3367 _endLazyDPSEvaluation ();
3376 /*-----------------------------------------------------------------*/
3377 /* outBitAcc - output a bit in acc */
3378 /*-----------------------------------------------------------------*/
3380 outBitAcc (operand * result)
3382 symbol *tlbl = newiTempLabel (NULL);
3383 /* if the result is a bit */
3384 if (AOP_TYPE (result) == AOP_CRY)
3386 aopPut (AOP (result), "a", 0);
3390 emitcode ("jz", "%05d$", tlbl->key + 100);
3391 emitcode ("mov", "a,%s", one);
3392 emitcode ("", "%05d$:", tlbl->key + 100);
3397 /*-----------------------------------------------------------------*/
3398 /* genPlusBits - generates code for addition of two bits */
3399 /*-----------------------------------------------------------------*/
3401 genPlusBits (iCode * ic)
3403 D (emitcode (";", "genPlusBits ");
3405 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3407 symbol *lbl = newiTempLabel (NULL);
3408 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3409 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3410 emitcode ("cpl", "c");
3411 emitcode ("", "%05d$:", (lbl->key + 100));
3412 outBitC (IC_RESULT (ic));
3416 emitcode ("clr", "a");
3417 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3418 emitcode ("rlc", "a");
3419 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3420 emitcode ("addc", "a,#0x00");
3421 outAcc (IC_RESULT (ic));
3426 adjustArithmeticResult (iCode * ic)
3428 if (opIsGptr (IC_RESULT (ic)) &&
3429 opIsGptr (IC_LEFT (ic)) &&
3430 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3432 aopPut (AOP (IC_RESULT (ic)),
3433 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3437 if (opIsGptr (IC_RESULT (ic)) &&
3438 opIsGptr (IC_RIGHT (ic)) &&
3439 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3441 aopPut (AOP (IC_RESULT (ic)),
3442 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3446 if (opIsGptr (IC_RESULT (ic)) &&
3447 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3448 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3449 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3450 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3453 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3454 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3458 #if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
3459 // Please don't bring it back without a really good reason.
3460 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3461 // (because all three operands are in far space).
3462 #define AOP_OP_3(ic) \
3463 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3464 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3465 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3466 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3467 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3468 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3470 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3472 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3476 // Macro to aopOp all three operands of an ic. If this cannot be done,
3477 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3478 // will be set TRUE. The caller must then handle the case specially, noting
3479 // that the IC_RESULT operand is not aopOp'd.
3480 #define AOP_OP_3_NOFATAL(ic, rc) \
3481 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3482 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR) || \
3483 (OP_SYMBOL(IC_RESULT(ic))->ruonly)); \
3484 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3485 (isOperandInFarSpace(IC_RESULT(ic)) || OP_SYMBOL(IC_RESULT(ic))->ruonly )) \
3487 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3492 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3493 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3495 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3496 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3498 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3500 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3504 // aopOp the left & right operands of an ic.
3505 #define AOP_OP_2(ic) \
3506 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3507 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3509 // convienience macro.
3510 #define AOP_SET_LOCALS(ic) \
3511 left = IC_LEFT(ic); \
3512 right = IC_RIGHT(ic); \
3513 result = IC_RESULT(ic);
3516 // Given an integer value of pushedSize bytes on the stack,
3517 // adjust it to be resultSize bytes, either by discarding
3518 // the most significant bytes or by zero-padding.
3520 // On exit from this macro, pushedSize will have been adjusted to
3521 // equal resultSize, and ACC may be trashed.
3522 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3523 /* If the pushed data is bigger than the result, \
3524 * simply discard unused bytes. Icky, but works. \
3526 while (pushedSize > resultSize) \
3528 D (emitcode (";", "discarding unused result byte."););\
3529 emitcode ("pop", "acc"); \
3532 if (pushedSize < resultSize) \
3534 emitcode ("clr", "a"); \
3535 /* Conversly, we haven't pushed enough here. \
3536 * just zero-pad, and all is well. \
3538 while (pushedSize < resultSize) \
3540 emitcode("push", "acc"); \
3544 assert(pushedSize == resultSize);
3546 /*-----------------------------------------------------------------*/
3547 /* genPlus - generates code for addition */
3548 /*-----------------------------------------------------------------*/
3550 genPlus (iCode * ic)
3552 int size, offset = 0;
3553 bool pushResult = FALSE;
3556 D (emitcode (";", "genPlus "););
3558 /* special cases :- */
3559 if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) &&
3560 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3561 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3562 size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3564 while (size--) emitcode ("inc","dptr");
3566 emitcode ("mov","a,dpl");
3567 emitcode ("add","a,#0x%02x",size & 0xff);
3568 emitcode ("mov","dpl,a");
3569 emitcode ("mov","a,dph");
3570 emitcode ("addc","a,#0x%02x",(size >> 8) & 0xff);
3571 emitcode ("mov","dph,a");
3572 emitcode ("mov","a,dpx");
3573 emitcode ("addc","a,#0x%02x",(size >> 16) & 0xff);
3574 emitcode ("mov","dpx,a");
3576 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3579 if ( IS_SYMOP(IC_LEFT(ic)) &&
3580 OP_SYMBOL(IC_LEFT(ic))->remat &&
3581 isOperandInFarSpace(IC_RIGHT(ic))) {
3582 operand *op = IC_RIGHT(ic);
3583 IC_RIGHT(ic) = IC_LEFT(ic);
3587 AOP_OP_3_NOFATAL (ic, pushResult);
3590 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3595 /* if literal, literal on the right or
3596 if left requires ACC or right is already
3598 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3599 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3600 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3602 operand *t = IC_RIGHT (ic);
3603 IC_RIGHT (ic) = IC_LEFT (ic);
3605 emitcode (";", "Swapped plus args.");
3608 /* if both left & right are in bit
3610 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3611 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3617 /* if left in bit space & right literal */
3618 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3619 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3621 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3622 /* if result in bit space */
3623 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3625 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3626 emitcode ("cpl", "c");
3627 outBitC (IC_RESULT (ic));
3631 size = getDataSize (IC_RESULT (ic));
3632 _startLazyDPSEvaluation ();
3635 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3636 emitcode ("addc", "a,#00");
3637 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3639 _endLazyDPSEvaluation ();
3644 /* if I can do an increment instead
3645 of add then GOOD for ME */
3646 if (genPlusIncr (ic) == TRUE)
3648 emitcode (";", "did genPlusIncr");
3653 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3655 _startLazyDPSEvaluation ();
3658 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3660 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3662 emitcode ("add", "a,%s",
3663 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3665 emitcode ("addc", "a,%s",
3666 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3670 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3672 /* right is going to use ACC or we would have taken the
3675 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3677 D(emitcode(";", "+ AOP_ACC special case."););
3678 emitcode("xch", "a, %s", DP2_RESULT_REG);
3680 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3683 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3686 emitcode("add", "a, %s", DP2_RESULT_REG);
3690 emitcode ("add", "a,%s",
3691 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3696 emitcode ("addc", "a,%s",
3697 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3702 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3706 emitcode ("push", "acc");
3710 _endLazyDPSEvaluation ();
3714 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3716 size = getDataSize (IC_LEFT (ic));
3717 rSize = getDataSize (IC_RESULT (ic));
3719 ADJUST_PUSHED_RESULT(size, rSize);
3721 _startLazyDPSEvaluation ();
3724 emitcode ("pop", "acc");
3725 aopPut (AOP (IC_RESULT (ic)), "a", size);
3727 _endLazyDPSEvaluation ();
3730 adjustArithmeticResult (ic);
3733 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3734 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3735 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3738 /*-----------------------------------------------------------------*/
3739 /* genMinusDec :- does subtraction with deccrement if possible */
3740 /*-----------------------------------------------------------------*/
3742 genMinusDec (iCode * ic)
3744 unsigned int icount;
3745 unsigned int size = getDataSize (IC_RESULT (ic));
3747 /* will try to generate an increment */
3748 /* if the right side is not a literal
3750 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3753 /* if the literal value of the right hand side
3754 is greater than 4 then it is not worth it */
3755 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3758 /* if decrement 16 bits in register */
3759 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3760 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3761 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3769 /* If the next instruction is a goto and the goto target
3770 * is <= 5 instructions previous to this, we can generate
3771 * jumps straight to that target.
3773 if (ic->next && ic->next->op == GOTO
3774 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3777 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3778 tlbl = IC_LABEL (ic->next);
3783 tlbl = newiTempLabel (NULL);
3787 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3788 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3789 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3790 IS_AOP_PREG (IC_RESULT (ic)))
3791 emitcode ("cjne", "%s,#0xff,%05d$"
3792 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3796 emitcode ("mov", "a,#0xff");
3797 emitcode ("cjne", "a,%s,%05d$"
3798 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3801 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3804 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3805 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3806 IS_AOP_PREG (IC_RESULT (ic)))
3807 emitcode ("cjne", "%s,#0xff,%05d$"
3808 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3812 emitcode ("cjne", "a,%s,%05d$"
3813 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3816 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3820 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3821 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3822 IS_AOP_PREG (IC_RESULT (ic)))
3823 emitcode ("cjne", "%s,#0xff,%05d$"
3824 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3828 emitcode ("cjne", "a,%s,%05d$"
3829 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3832 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3836 emitcode ("", "%05d$:", tlbl->key + 100);
3841 /* if the sizes are greater than 1 then we cannot */
3842 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3843 AOP_SIZE (IC_LEFT (ic)) > 1)
3846 /* we can if the aops of the left & result match or
3847 if they are in registers and the registers are the
3850 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3851 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3852 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3855 _startLazyDPSEvaluation ();
3858 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3860 _endLazyDPSEvaluation ();
3868 /*-----------------------------------------------------------------*/
3869 /* addSign - complete with sign */
3870 /*-----------------------------------------------------------------*/
3872 addSign (operand * result, int offset, int sign)
3874 int size = (getDataSize (result) - offset);
3877 _startLazyDPSEvaluation();
3880 emitcode ("rlc", "a");
3881 emitcode ("subb", "a,acc");
3884 aopPut (AOP (result), "a", offset++);
3891 aopPut (AOP (result), zero, offset++);
3894 _endLazyDPSEvaluation();
3898 /*-----------------------------------------------------------------*/
3899 /* genMinusBits - generates code for subtraction of two bits */
3900 /*-----------------------------------------------------------------*/
3902 genMinusBits (iCode * ic)
3904 symbol *lbl = newiTempLabel (NULL);
3906 D (emitcode (";", "genMinusBits "););
3908 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3910 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3911 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3912 emitcode ("cpl", "c");
3913 emitcode ("", "%05d$:", (lbl->key + 100));
3914 outBitC (IC_RESULT (ic));
3918 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3919 emitcode ("subb", "a,acc");
3920 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3921 emitcode ("inc", "a");
3922 emitcode ("", "%05d$:", (lbl->key + 100));
3923 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3924 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3928 /*-----------------------------------------------------------------*/
3929 /* genMinus - generates code for subtraction */
3930 /*-----------------------------------------------------------------*/
3932 genMinus (iCode * ic)
3934 int size, offset = 0;
3936 unsigned long lit = 0L;
3937 bool pushResult = FALSE;
3939 D (emitcode (";", "genMinus "););
3941 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3942 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3943 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3944 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3950 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3952 /* special cases :- */
3953 /* if both left & right are in bit space */
3954 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3955 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3961 /* if I can do an decrement instead
3962 of subtract then GOOD for ME */
3963 if (genMinusDec (ic) == TRUE)
3968 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3970 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3976 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3981 /* if literal, add a,#-lit, else normal subb */
3982 _startLazyDPSEvaluation ();
3985 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3986 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3987 emitcode ("subb", "a,%s",
3988 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3991 /* first add without previous c */
3993 if (!size && lit==-1) {
3994 emitcode ("dec", "a");
3996 emitcode ("add", "a,#0x%02x",
3997 (unsigned int) (lit & 0x0FFL));
4000 emitcode ("addc", "a,#0x%02x",
4001 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4007 emitcode ("push", "acc");
4011 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4015 _endLazyDPSEvaluation ();
4019 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4021 size = getDataSize (IC_LEFT (ic));
4022 rSize = getDataSize (IC_RESULT (ic));
4024 ADJUST_PUSHED_RESULT(size, rSize);
4026 _startLazyDPSEvaluation ();
4029 emitcode ("pop", "acc");
4030 aopPut (AOP (IC_RESULT (ic)), "a", size);
4032 _endLazyDPSEvaluation ();
4035 adjustArithmeticResult (ic);
4038 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4039 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4040 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4044 /*-----------------------------------------------------------------*/
4045 /* genMultbits :- multiplication of bits */
4046 /*-----------------------------------------------------------------*/
4048 genMultbits (operand * left,
4053 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4054 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4055 aopOp(result, ic, TRUE, FALSE);
4060 /*-----------------------------------------------------------------*/
4061 /* genMultOneByte : 8*8=8/16 bit multiplication */
4062 /*-----------------------------------------------------------------*/
4064 genMultOneByte (operand * left,
4069 sym_link *opetype = operandType (result);
4073 /* (if two literals: the value is computed before) */
4074 /* if one literal, literal on the right */
4075 if (AOP_TYPE (left) == AOP_LIT)
4080 emitcode (";", "swapped left and right");
4083 if (SPEC_USIGN(opetype)
4084 // ignore the sign of left and right, what else can we do?
4085 || (SPEC_USIGN(operandType(left)) &&
4086 SPEC_USIGN(operandType(right)))) {
4087 // just an unsigned 8*8=8/16 multiply
4088 //emitcode (";","unsigned");
4089 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4090 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
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 aopPut (AOP (result), "a", 0);
4106 if (AOP_SIZE(result)==2)
4108 aopPut (AOP (result), "b", 1);
4113 // we have to do a signed multiply
4115 emitcode (";", "signed");
4116 emitcode ("clr", "F0"); // reset sign flag
4117 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4119 lbl=newiTempLabel(NULL);
4120 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
4121 // left side is negative, 8-bit two's complement, this fails for -128
4122 emitcode ("setb", "F0"); // set sign flag
4123 emitcode ("cpl", "a");
4124 emitcode ("inc", "a");
4126 emitcode ("", "%05d$:", lbl->key+100);
4129 if (AOP_TYPE(right)==AOP_LIT) {
4130 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4131 /* AND literal negative */
4132 if ((int) val < 0) {
4133 emitcode ("cpl", "F0"); // complement sign flag
4134 emitcode ("mov", "b,#0x%02x", -val);
4136 emitcode ("mov", "b,#0x%02x", val);
4139 lbl=newiTempLabel(NULL);
4140 emitcode ("mov", "b,a");
4141 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4142 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
4143 // right side is negative, 8-bit two's complement
4144 emitcode ("cpl", "F0"); // complement sign flag
4145 emitcode ("cpl", "a");
4146 emitcode ("inc", "a");
4147 emitcode ("", "%05d$:", lbl->key+100);
4149 emitcode ("mul", "ab");
4152 aopOp(result, ic, TRUE, FALSE);
4154 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4156 // this should never happen
4157 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4158 AOP_SIZE(result), __FILE__, lineno);
4162 lbl=newiTempLabel(NULL);
4163 emitcode ("jnb", "F0,%05d$", lbl->key+100);
4164 // only ONE op was negative, we have to do a 8/16-bit two's complement
4165 emitcode ("cpl", "a"); // lsb
4166 if (AOP_SIZE(result)==1) {
4167 emitcode ("inc", "a");
4169 emitcode ("add", "a,#1");
4170 emitcode ("xch", "a,b");
4171 emitcode ("cpl", "a"); // msb
4172 emitcode ("addc", "a,#0");
4173 emitcode ("xch", "a,b");
4176 emitcode ("", "%05d$:", lbl->key+100);
4177 aopPut (AOP (result), "a", 0);
4179 if (AOP_SIZE(result)==2) {
4180 aopPut (AOP (result), "b", 1);
4184 /*-----------------------------------------------------------------*/
4185 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4186 /*-----------------------------------------------------------------*/
4187 static void genMultTwoByte (operand *left, operand *right,
4188 operand *result, iCode *ic)
4190 sym_link *retype = getSpec(operandType(right));
4191 sym_link *letype = getSpec(operandType(left));
4192 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4195 if (AOP_TYPE (left) == AOP_LIT) {
4200 /* save EA bit in F1 */
4201 lbl = newiTempLabel(NULL);
4202 emitcode ("setb","F1");
4203 emitcode ("jbc","EA,%05d$",lbl->key+100);
4204 emitcode ("clr","F1");
4205 emitcode("","%05d$:",lbl->key+100);
4207 /* load up MB with right */
4209 emitcode("clr","F0");
4210 if (AOP_TYPE(right) == AOP_LIT) {
4211 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4213 emitcode("setb","F0");
4216 emitcode ("mov","mb,#0x%02x",val & 0xff);
4217 emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4219 lbl = newiTempLabel(NULL);
4220 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4221 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4222 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4223 emitcode ("xch", "a,b");
4224 emitcode ("cpl","a");
4225 emitcode ("add", "a,#1");
4226 emitcode ("xch", "a,b");
4227 emitcode ("cpl", "a"); // msb
4228 emitcode ("addc", "a,#0");
4229 emitcode ("setb","F0");
4230 emitcode ("","%05d$:",lbl->key+100);
4231 emitcode ("mov","mb,b");
4232 emitcode ("mov","mb,a");
4235 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4236 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4238 /* load up MA with left */
4240 lbl = newiTempLabel(NULL);
4241 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4242 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4243 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4244 emitcode ("xch", "a,b");
4245 emitcode ("cpl","a");
4246 emitcode ("add", "a,#1");
4247 emitcode ("xch", "a,b");
4248 emitcode ("cpl", "a"); // msb
4249 emitcode ("addc","a,#0");
4250 emitcode ("jbc","F0,%05d$",lbl->key+100);
4251 emitcode ("setb","F0");
4252 emitcode ("","%05d$:",lbl->key+100);
4253 emitcode ("mov","ma,b");
4254 emitcode ("mov","ma,a");
4256 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4257 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4259 /* wait for multiplication to finish */
4260 lbl = newiTempLabel(NULL);
4261 emitcode("","%05d$:", lbl->key+100);
4262 emitcode("mov","a,mcnt1");
4263 emitcode("anl","a,#0x80");
4264 emitcode("jnz","%05d$",lbl->key+100);
4266 freeAsmop (left, NULL, ic, TRUE);
4267 freeAsmop (right, NULL, ic,TRUE);
4268 aopOp(result, ic, TRUE, FALSE);
4270 /* if unsigned then simple */
4272 emitcode ("mov","a,ma");
4273 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4274 emitcode ("mov","a,ma");
4275 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4276 aopPut(AOP(result),"ma",1);
4277 aopPut(AOP(result),"ma",0);
4279 emitcode("push","ma");
4280 emitcode("push","ma");
4281 emitcode("push","ma");
4283 /* negate result if needed */
4284 lbl = newiTempLabel(NULL);
4285 emitcode("jnb","F0,%05d$",lbl->key+100);
4286 emitcode("cpl","a");
4287 emitcode("add","a,#1");
4288 emitcode("","%05d$:", lbl->key+100);
4289 if (AOP_TYPE(result) == AOP_ACC)
4291 D(emitcode(";", "ACC special case."););
4292 /* We know result is the only live aop, and
4293 * it's obviously not a DPTR2, so AP is available.
4295 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4299 aopPut(AOP(result),"a",0);
4302 emitcode("pop","acc");
4303 lbl = newiTempLabel(NULL);
4304 emitcode("jnb","F0,%05d$",lbl->key+100);
4305 emitcode("cpl","a");
4306 emitcode("addc","a,#0");
4307 emitcode("","%05d$:", lbl->key+100);
4308 aopPut(AOP(result),"a",1);
4309 emitcode("pop","acc");
4310 if (AOP_SIZE(result) >= 3) {
4311 lbl = newiTempLabel(NULL);
4312 emitcode("jnb","F0,%05d$",lbl->key+100);
4313 emitcode("cpl","a");
4314 emitcode("addc","a,#0");
4315 emitcode("","%05d$:", lbl->key+100);
4316 aopPut(AOP(result),"a",2);
4318 emitcode("pop","acc");
4319 if (AOP_SIZE(result) >= 4) {
4320 lbl = newiTempLabel(NULL);
4321 emitcode("jnb","F0,%05d$",lbl->key+100);
4322 emitcode("cpl","a");
4323 emitcode("addc","a,#0");
4324 emitcode("","%05d$:", lbl->key+100);
4325 aopPut(AOP(result),"a",3);
4327 if (AOP_TYPE(result) == AOP_ACC)
4329 /* We stashed the result away above. */
4330 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4334 freeAsmop (result, NULL, ic, TRUE);
4336 /* restore EA bit in F1 */
4337 lbl = newiTempLabel(NULL);
4338 emitcode ("jnb","F1,%05d$",lbl->key+100);
4339 emitcode ("setb","EA");
4340 emitcode("","%05d$:",lbl->key+100);
4344 /*-----------------------------------------------------------------*/
4345 /* genMult - generates code for multiplication */
4346 /*-----------------------------------------------------------------*/
4348 genMult (iCode * ic)
4350 operand *left = IC_LEFT (ic);
4351 operand *right = IC_RIGHT (ic);
4352 operand *result = IC_RESULT (ic);
4354 D (emitcode (";", "genMult "););
4356 /* assign the amsops */
4359 /* special cases first */
4361 if (AOP_TYPE (left) == AOP_CRY &&
4362 AOP_TYPE (right) == AOP_CRY)
4364 genMultbits (left, right, result, ic);
4368 /* if both are of size == 1 */
4369 if (AOP_SIZE (left) == 1 &&
4370 AOP_SIZE (right) == 1)
4372 genMultOneByte (left, right, result, ic);
4376 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4377 /* use the ds390 ARITHMETIC accel UNIT */
4378 genMultTwoByte (left, right, result, ic);
4381 /* should have been converted to function call */
4385 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4386 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4387 freeAsmop (result, NULL, ic, TRUE);
4390 /*-----------------------------------------------------------------*/
4391 /* genDivbits :- division of bits */
4392 /*-----------------------------------------------------------------*/
4394 genDivbits (operand * left,
4402 /* the result must be bit */
4403 LOAD_AB_FOR_DIV (left, right, l);
4404 emitcode ("div", "ab");
4405 emitcode ("rrc", "a");
4406 aopOp(result, ic, TRUE, FALSE);
4408 aopPut (AOP (result), "c", 0);
4411 /*-----------------------------------------------------------------*/
4412 /* genDivOneByte : 8 bit division */
4413 /*-----------------------------------------------------------------*/
4415 genDivOneByte (operand * left,
4420 sym_link *opetype = operandType (result);
4426 /* signed or unsigned */
4427 if (SPEC_USIGN (opetype))
4429 /* unsigned is easy */
4430 LOAD_AB_FOR_DIV (left, right, l);
4431 emitcode ("div", "ab");
4434 aopOp(result, ic, TRUE, FALSE);
4435 aopPut (AOP (result), "a", 0);
4438 size = AOP_SIZE (result) - 1;
4442 aopPut (AOP (result), zero, offset++);
4447 /* signed is a little bit more difficult */
4449 /* save the signs of the operands */
4450 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4452 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4453 emitcode ("push", "acc"); /* save it on the stack */
4455 /* now sign adjust for both left & right */
4456 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4458 lbl = newiTempLabel (NULL);
4459 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4460 emitcode ("cpl", "a");
4461 emitcode ("inc", "a");
4462 emitcode ("", "%05d$:", (lbl->key + 100));
4463 emitcode ("mov", "b,a");
4465 /* sign adjust left side */
4466 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4469 lbl = newiTempLabel (NULL);
4470 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4471 emitcode ("cpl", "a");
4472 emitcode ("inc", "a");
4473 emitcode ("", "%05d$:", (lbl->key + 100));
4475 /* now the division */
4476 emitcode ("nop", "; workaround for DS80C390 div bug.");
4477 emitcode ("div", "ab");
4478 /* we are interested in the lower order
4480 emitcode ("mov", "b,a");
4481 lbl = newiTempLabel (NULL);
4482 emitcode ("pop", "acc");
4483 /* if there was an over flow we don't
4484 adjust the sign of the result */
4485 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4486 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4488 emitcode ("clr", "a");
4489 emitcode ("subb", "a,b");
4490 emitcode ("mov", "b,a");
4491 emitcode ("", "%05d$:", (lbl->key + 100));
4493 /* now we are done */
4495 aopOp(result, ic, TRUE, FALSE);
4497 aopPut (AOP (result), "b", 0);
4499 size = AOP_SIZE (result) - 1;
4503 emitcode ("mov", "c,b.7");
4504 emitcode ("subb", "a,acc");
4508 aopPut (AOP (result), "a", offset++);
4514 /*-----------------------------------------------------------------*/
4515 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4516 /*-----------------------------------------------------------------*/
4517 static void genDivTwoByte (operand *left, operand *right,
4518 operand *result, iCode *ic)
4520 sym_link *retype = getSpec(operandType(right));
4521 sym_link *letype = getSpec(operandType(left));
4522 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4525 /* save EA bit in F1 */
4526 lbl = newiTempLabel(NULL);
4527 emitcode ("setb","F1");
4528 emitcode ("jbc","EA,%05d$",lbl->key+100);
4529 emitcode ("clr","F1");
4530 emitcode("","%05d$:",lbl->key+100);
4532 /* load up MA with left */
4534 emitcode("clr","F0");
4535 lbl = newiTempLabel(NULL);
4536 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4537 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4538 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4539 emitcode ("xch", "a,b");
4540 emitcode ("cpl","a");
4541 emitcode ("add", "a,#1");
4542 emitcode ("xch", "a,b");
4543 emitcode ("cpl", "a"); // msb
4544 emitcode ("addc","a,#0");
4545 emitcode ("setb","F0");
4546 emitcode ("","%05d$:",lbl->key+100);
4547 emitcode ("mov","ma,b");
4548 emitcode ("mov","ma,a");
4550 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4551 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4554 /* load up MB with right */
4556 if (AOP_TYPE(right) == AOP_LIT) {
4557 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4559 lbl = newiTempLabel(NULL);
4560 emitcode ("jbc","F0,%05d$",lbl->key+100);
4561 emitcode("setb","F0");
4562 emitcode ("","%05d$:",lbl->key+100);
4565 emitcode ("mov","mb,#0x%02x",val & 0xff);
4566 emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4568 lbl = newiTempLabel(NULL);
4569 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4570 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4571 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4572 emitcode ("xch", "a,b");
4573 emitcode ("cpl","a");
4574 emitcode ("add", "a,#1");
4575 emitcode ("xch", "a,b");
4576 emitcode ("cpl", "a"); // msb
4577 emitcode ("addc", "a,#0");
4578 emitcode ("jbc","F0,%05d$",lbl->key+100);
4579 emitcode ("setb","F0");
4580 emitcode ("","%05d$:",lbl->key+100);
4581 emitcode ("mov","mb,b");
4582 emitcode ("mov","mb,a");
4585 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4586 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4589 /* wait for multiplication to finish */
4590 lbl = newiTempLabel(NULL);
4591 emitcode("","%05d$:", lbl->key+100);
4592 emitcode("mov","a,mcnt1");
4593 emitcode("anl","a,#0x80");
4594 emitcode("jnz","%05d$",lbl->key+100);
4596 freeAsmop (left, NULL, ic, TRUE);
4597 freeAsmop (right, NULL, ic,TRUE);
4598 aopOp(result, ic, TRUE, FALSE);
4600 /* if unsigned then simple */
4602 aopPut(AOP(result),"ma",1);
4603 aopPut(AOP(result),"ma",0);
4605 emitcode("push","ma");
4607 /* negate result if needed */
4608 lbl = newiTempLabel(NULL);
4609 emitcode("jnb","F0,%05d$",lbl->key+100);
4610 emitcode("cpl","a");
4611 emitcode("add","a,#1");
4612 emitcode("","%05d$:", lbl->key+100);
4613 aopPut(AOP(result),"a",0);
4614 emitcode("pop","acc");
4615 lbl = newiTempLabel(NULL);
4616 emitcode("jnb","F0,%05d$",lbl->key+100);
4617 emitcode("cpl","a");
4618 emitcode("addc","a,#0");
4619 emitcode("","%05d$:", lbl->key+100);
4620 aopPut(AOP(result),"a",1);
4622 freeAsmop (result, NULL, ic, TRUE);
4623 /* restore EA bit in F1 */
4624 lbl = newiTempLabel(NULL);
4625 emitcode ("jnb","F1,%05d$",lbl->key+100);
4626 emitcode ("setb","EA");
4627 emitcode("","%05d$:",lbl->key+100);
4631 /*-----------------------------------------------------------------*/
4632 /* genDiv - generates code for division */
4633 /*-----------------------------------------------------------------*/
4637 operand *left = IC_LEFT (ic);
4638 operand *right = IC_RIGHT (ic);
4639 operand *result = IC_RESULT (ic);
4641 D (emitcode (";", "genDiv "););
4643 /* assign the amsops */
4646 /* special cases first */
4648 if (AOP_TYPE (left) == AOP_CRY &&
4649 AOP_TYPE (right) == AOP_CRY)
4651 genDivbits (left, right, result, ic);
4655 /* if both are of size == 1 */
4656 if (AOP_SIZE (left) == 1 &&
4657 AOP_SIZE (right) == 1)
4659 genDivOneByte (left, right, result, ic);
4663 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4664 /* use the ds390 ARITHMETIC accel UNIT */
4665 genDivTwoByte (left, right, result, ic);
4668 /* should have been converted to function call */
4671 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4672 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4673 freeAsmop (result, NULL, ic, TRUE);
4676 /*-----------------------------------------------------------------*/
4677 /* genModbits :- modulus of bits */
4678 /*-----------------------------------------------------------------*/
4680 genModbits (operand * left,
4688 /* the result must be bit */
4689 LOAD_AB_FOR_DIV (left, right, l);
4690 emitcode ("div", "ab");
4691 emitcode ("mov", "a,b");
4692 emitcode ("rrc", "a");
4693 aopOp(result, ic, TRUE, FALSE);
4694 aopPut (AOP (result), "c", 0);
4697 /*-----------------------------------------------------------------*/
4698 /* genModOneByte : 8 bit modulus */
4699 /*-----------------------------------------------------------------*/
4701 genModOneByte (operand * left,
4706 sym_link *opetype = operandType (result);
4710 /* signed or unsigned */
4711 if (SPEC_USIGN (opetype))
4713 /* unsigned is easy */
4714 LOAD_AB_FOR_DIV (left, right, l);
4715 emitcode ("div", "ab");
4716 aopOp(result, ic, TRUE, FALSE);
4717 aopPut (AOP (result), "b", 0);
4721 /* signed is a little bit more difficult */
4723 /* save the signs of the operands */
4724 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4727 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4728 emitcode ("push", "acc"); /* save it on the stack */
4730 /* now sign adjust for both left & right */
4731 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4734 lbl = newiTempLabel (NULL);
4735 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4736 emitcode ("cpl", "a");
4737 emitcode ("inc", "a");
4738 emitcode ("", "%05d$:", (lbl->key + 100));
4739 emitcode ("mov", "b,a");
4741 /* sign adjust left side */
4742 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4745 lbl = newiTempLabel (NULL);
4746 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4747 emitcode ("cpl", "a");
4748 emitcode ("inc", "a");
4749 emitcode ("", "%05d$:", (lbl->key + 100));
4751 /* now the multiplication */
4752 emitcode ("nop", "; workaround for DS80C390 div bug.");
4753 emitcode ("div", "ab");
4754 /* we are interested in the lower order
4756 lbl = newiTempLabel (NULL);
4757 emitcode ("pop", "acc");
4758 /* if there was an over flow we don't
4759 adjust the sign of the result */
4760 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4761 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4763 emitcode ("clr", "a");
4764 emitcode ("subb", "a,b");
4765 emitcode ("mov", "b,a");
4766 emitcode ("", "%05d$:", (lbl->key + 100));
4768 /* now we are done */
4769 aopOp(result, ic, TRUE, FALSE);
4770 aopPut (AOP (result), "b", 0);
4774 /*-----------------------------------------------------------------*/
4775 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
4776 /*-----------------------------------------------------------------*/
4777 static void genModTwoByte (operand *left, operand *right,
4778 operand *result, iCode *ic)
4780 sym_link *retype = getSpec(operandType(right));
4781 sym_link *letype = getSpec(operandType(left));
4782 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4785 /* load up MA with left */
4786 /* save EA bit in F1 */
4787 lbl = newiTempLabel(NULL);
4788 emitcode ("setb","F1");
4789 emitcode ("jbc","EA,%05d$",lbl->key+100);
4790 emitcode ("clr","F1");
4791 emitcode("","%05d$:",lbl->key+100);
4794 lbl = newiTempLabel(NULL);
4795 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4796 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4797 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4798 emitcode ("xch", "a,b");
4799 emitcode ("cpl","a");
4800 emitcode ("add", "a,#1");
4801 emitcode ("xch", "a,b");
4802 emitcode ("cpl", "a"); // msb
4803 emitcode ("addc","a,#0");
4804 emitcode ("","%05d$:",lbl->key+100);
4805 emitcode ("mov","ma,b");
4806 emitcode ("mov","ma,a");
4808 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4809 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4812 /* load up MB with right */
4814 if (AOP_TYPE(right) == AOP_LIT) {
4815 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4819 emitcode ("mov","mb,#0x%02x",val & 0xff);
4820 emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4822 lbl = newiTempLabel(NULL);
4823 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4824 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4825 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4826 emitcode ("xch", "a,b");
4827 emitcode ("cpl","a");
4828 emitcode ("add", "a,#1");
4829 emitcode ("xch", "a,b");
4830 emitcode ("cpl", "a"); // msb
4831 emitcode ("addc", "a,#0");
4832 emitcode ("","%05d$:",lbl->key+100);
4833 emitcode ("mov","mb,b");
4834 emitcode ("mov","mb,a");
4837 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4838 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4841 /* wait for multiplication to finish */
4842 lbl = newiTempLabel(NULL);
4843 emitcode("","%05d$:", lbl->key+100);
4844 emitcode("mov","a,mcnt1");
4845 emitcode("anl","a,#0x80");
4846 emitcode("jnz","%05d$",lbl->key+100);
4848 freeAsmop (left, NULL, ic, TRUE);
4849 freeAsmop (right, NULL, ic,TRUE);
4850 aopOp(result, ic, TRUE, FALSE);
4852 aopPut(AOP(result),"mb",1);
4853 aopPut(AOP(result),"mb",0);
4854 freeAsmop (result, NULL, ic, TRUE);
4856 /* restore EA bit in F1 */
4857 lbl = newiTempLabel(NULL);
4858 emitcode ("jnb","F1,%05d$",lbl->key+100);
4859 emitcode ("setb","EA");
4860 emitcode("","%05d$:",lbl->key+100);
4864 /*-----------------------------------------------------------------*/
4865 /* genMod - generates code for division */
4866 /*-----------------------------------------------------------------*/
4870 operand *left = IC_LEFT (ic);
4871 operand *right = IC_RIGHT (ic);
4872 operand *result = IC_RESULT (ic);
4874 D (emitcode (";", "genMod "); );
4876 /* assign the amsops */
4879 /* special cases first */
4881 if (AOP_TYPE (left) == AOP_CRY &&
4882 AOP_TYPE (right) == AOP_CRY)
4884 genModbits (left, right, result, ic);
4888 /* if both are of size == 1 */
4889 if (AOP_SIZE (left) == 1 &&
4890 AOP_SIZE (right) == 1)
4892 genModOneByte (left, right, result, ic);
4896 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4897 /* use the ds390 ARITHMETIC accel UNIT */
4898 genModTwoByte (left, right, result, ic);
4902 /* should have been converted to function call */
4906 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4907 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4908 freeAsmop (result, NULL, ic, TRUE);
4911 /*-----------------------------------------------------------------*/
4912 /* genIfxJump :- will create a jump depending on the ifx */
4913 /*-----------------------------------------------------------------*/
4915 genIfxJump (iCode * ic, char *jval)
4918 symbol *tlbl = newiTempLabel (NULL);
4921 D (emitcode (";", "genIfxJump ");
4924 /* if true label then we jump if condition
4928 jlbl = IC_TRUE (ic);
4929 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4930 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4934 /* false label is present */
4935 jlbl = IC_FALSE (ic);
4936 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4937 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4939 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4940 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4942 emitcode (inst, "%05d$", tlbl->key + 100);
4943 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4944 emitcode ("", "%05d$:", tlbl->key + 100);
4946 /* mark the icode as generated */
4950 /*-----------------------------------------------------------------*/
4951 /* genCmp :- greater or less than comparison */
4952 /*-----------------------------------------------------------------*/
4954 genCmp (operand * left, operand * right,
4955 iCode * ic, iCode * ifx, int sign)
4957 int size, offset = 0;
4958 unsigned long lit = 0L;
4961 D (emitcode (";", "genCmp");
4964 result = IC_RESULT (ic);
4966 /* if left & right are bit variables */
4967 if (AOP_TYPE (left) == AOP_CRY &&
4968 AOP_TYPE (right) == AOP_CRY)
4970 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4971 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4975 /* subtract right from left if at the
4976 end the carry flag is set then we know that
4977 left is greater than right */
4978 size = max (AOP_SIZE (left), AOP_SIZE (right));
4980 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4981 if ((size == 1) && !sign &&
4982 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4984 symbol *lbl = newiTempLabel (NULL);
4985 emitcode ("cjne", "%s,%s,%05d$",
4986 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4987 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4989 emitcode ("", "%05d$:", lbl->key + 100);
4993 if (AOP_TYPE (right) == AOP_LIT)
4995 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4996 /* optimize if(x < 0) or if(x >= 0) */
5005 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5007 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5008 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5010 aopOp (result, ic, FALSE, FALSE);
5012 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5014 freeAsmop (result, NULL, ic, TRUE);
5015 genIfxJump (ifx, "acc.7");
5020 emitcode ("rlc", "a");
5022 goto release_freedLR;
5030 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5031 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5032 emitcode (";", "genCmp #2");
5033 if (sign && (size == 0))
5035 emitcode (";", "genCmp #3");
5036 emitcode ("xrl", "a,#0x80");
5037 if (AOP_TYPE (right) == AOP_LIT)
5039 unsigned long lit = (unsigned long)
5040 floatFromVal (AOP (right)->aopu.aop_lit);
5041 emitcode (";", "genCmp #3.1");
5042 emitcode ("subb", "a,#0x%02x",
5043 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5047 emitcode (";", "genCmp #3.2");
5048 if (AOP_NEEDSACC (right))
5050 emitcode ("push", "acc");
5052 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
5053 FALSE, FALSE, FALSE));
5054 emitcode ("xrl", "b,#0x80");
5055 if (AOP_NEEDSACC (right))
5057 emitcode ("pop", "acc");
5059 emitcode ("subb", "a,b");
5066 emitcode (";", "genCmp #4");
5067 if (AOP_NEEDSACC (right))
5070 emitcode (";", "genCmp #4.1");
5071 emitcode ("xch", "a, b");
5072 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
5073 emitcode ("xch", "a, b");
5078 emitcode (";", "genCmp #4.2");
5079 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
5082 emitcode ("subb", "a,%s", s);
5089 /* Don't need the left & right operands any more; do need the result. */
5090 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5091 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5093 aopOp (result, ic, FALSE, FALSE);
5097 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5103 /* if the result is used in the next
5104 ifx conditional branch then generate
5105 code a little differently */
5108 genIfxJump (ifx, "c");
5114 /* leave the result in acc */
5116 freeAsmop (result, NULL, ic, TRUE);
5119 /*-----------------------------------------------------------------*/
5120 /* genCmpGt :- greater than comparison */
5121 /*-----------------------------------------------------------------*/
5123 genCmpGt (iCode * ic, iCode * ifx)
5125 operand *left, *right;
5126 sym_link *letype, *retype;
5129 D (emitcode (";", "genCmpGt ");
5132 left = IC_LEFT (ic);
5133 right = IC_RIGHT (ic);
5135 letype = getSpec (operandType (left));
5136 retype = getSpec (operandType (right));
5137 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5139 /* assign the left & right amsops */
5142 genCmp (right, left, ic, ifx, sign);
5145 /*-----------------------------------------------------------------*/
5146 /* genCmpLt - less than comparisons */
5147 /*-----------------------------------------------------------------*/
5149 genCmpLt (iCode * ic, iCode * ifx)
5151 operand *left, *right;
5152 sym_link *letype, *retype;
5155 D (emitcode (";", "genCmpLt "););
5157 left = IC_LEFT (ic);
5158 right = IC_RIGHT (ic);
5160 letype = getSpec (operandType (left));
5161 retype = getSpec (operandType (right));
5162 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5164 /* assign the left & right amsops */
5167 genCmp (left, right, ic, ifx, sign);
5170 /*-----------------------------------------------------------------*/
5171 /* gencjneshort - compare and jump if not equal */
5172 /*-----------------------------------------------------------------*/
5174 gencjneshort (operand * left, operand * right, symbol * lbl)
5176 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5178 unsigned long lit = 0L;
5180 D (emitcode (";", "gencjneshort");
5183 /* if the left side is a literal or
5184 if the right is in a pointer register and left
5186 if ((AOP_TYPE (left) == AOP_LIT) ||
5187 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5194 if (AOP_TYPE (right) == AOP_LIT)
5195 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5197 if (opIsGptr (left) || opIsGptr (right))
5199 /* We are comparing a generic pointer to something.
5200 * Exclude the generic type byte from the comparison.
5203 D (emitcode (";", "cjneshort: generic ptr special case.");
5208 /* if the right side is a literal then anything goes */
5209 if (AOP_TYPE (right) == AOP_LIT &&
5210 AOP_TYPE (left) != AOP_DIR)
5214 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5216 emitcode ("cjne", "a,%s,%05d$",
5217 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5223 /* if the right side is in a register or in direct space or
5224 if the left is a pointer register & right is not */
5225 else if (AOP_TYPE (right) == AOP_REG ||
5226 AOP_TYPE (right) == AOP_DIR ||
5227 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5228 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5232 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5233 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5234 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5235 emitcode ("jnz", "%05d$", lbl->key + 100);
5237 emitcode ("cjne", "a,%s,%05d$",
5238 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5245 /* right is a pointer reg need both a & b */
5248 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5249 if (strcmp (l, "b"))
5250 emitcode ("mov", "b,%s", l);
5251 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5252 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5258 /*-----------------------------------------------------------------*/
5259 /* gencjne - compare and jump if not equal */
5260 /*-----------------------------------------------------------------*/
5262 gencjne (operand * left, operand * right, symbol * lbl)
5264 symbol *tlbl = newiTempLabel (NULL);
5266 D (emitcode (";", "gencjne");
5269 gencjneshort (left, right, lbl);
5271 emitcode ("mov", "a,%s", one);
5272 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5273 emitcode ("", "%05d$:", lbl->key + 100);
5274 emitcode ("clr", "a");
5275 emitcode ("", "%05d$:", tlbl->key + 100);
5278 /*-----------------------------------------------------------------*/
5279 /* genCmpEq - generates code for equal to */
5280 /*-----------------------------------------------------------------*/
5282 genCmpEq (iCode * ic, iCode * ifx)
5284 operand *left, *right, *result;
5286 D (emitcode (";", "genCmpEq ");
5290 AOP_SET_LOCALS (ic);
5292 /* if literal, literal on the right or
5293 if the right is in a pointer register and left
5295 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5296 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5298 operand *t = IC_RIGHT (ic);
5299 IC_RIGHT (ic) = IC_LEFT (ic);
5303 if (ifx && /* !AOP_SIZE(result) */
5304 OP_SYMBOL (result) &&
5305 OP_SYMBOL (result)->regType == REG_CND)
5308 /* if they are both bit variables */
5309 if (AOP_TYPE (left) == AOP_CRY &&
5310 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5312 if (AOP_TYPE (right) == AOP_LIT)
5314 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5317 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5318 emitcode ("cpl", "c");
5322 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5326 emitcode ("clr", "c");
5328 /* AOP_TYPE(right) == AOP_CRY */
5332 symbol *lbl = newiTempLabel (NULL);
5333 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5334 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5335 emitcode ("cpl", "c");
5336 emitcode ("", "%05d$:", (lbl->key + 100));
5338 /* if true label then we jump if condition
5340 tlbl = newiTempLabel (NULL);
5343 emitcode ("jnc", "%05d$", tlbl->key + 100);
5344 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5348 emitcode ("jc", "%05d$", tlbl->key + 100);
5349 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5351 emitcode ("", "%05d$:", tlbl->key + 100);
5355 tlbl = newiTempLabel (NULL);
5356 gencjneshort (left, right, tlbl);
5359 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5360 emitcode ("", "%05d$:", tlbl->key + 100);
5364 symbol *lbl = newiTempLabel (NULL);
5365 emitcode ("sjmp", "%05d$", lbl->key + 100);
5366 emitcode ("", "%05d$:", tlbl->key + 100);
5367 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5368 emitcode ("", "%05d$:", lbl->key + 100);
5371 /* mark the icode as generated */
5374 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5375 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5379 /* if they are both bit variables */
5380 if (AOP_TYPE (left) == AOP_CRY &&
5381 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5383 if (AOP_TYPE (right) == AOP_LIT)
5385 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5388 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5389 emitcode ("cpl", "c");
5393 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5397 emitcode ("clr", "c");
5399 /* AOP_TYPE(right) == AOP_CRY */
5403 symbol *lbl = newiTempLabel (NULL);
5404 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5405 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5406 emitcode ("cpl", "c");
5407 emitcode ("", "%05d$:", (lbl->key + 100));
5410 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5411 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5413 aopOp (result, ic, TRUE, FALSE);
5416 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5423 genIfxJump (ifx, "c");
5426 /* if the result is used in an arithmetic operation
5427 then put the result in place */
5432 gencjne (left, right, newiTempLabel (NULL));
5434 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5435 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5437 aopOp (result, ic, TRUE, FALSE);
5439 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5441 aopPut (AOP (result), "a", 0);
5446 genIfxJump (ifx, "a");
5449 /* if the result is used in an arithmetic operation
5450 then put the result in place */
5451 if (AOP_TYPE (result) != AOP_CRY)
5453 /* leave the result in acc */
5457 freeAsmop (result, NULL, ic, TRUE);
5460 /*-----------------------------------------------------------------*/
5461 /* ifxForOp - returns the icode containing the ifx for operand */
5462 /*-----------------------------------------------------------------*/
5464 ifxForOp (operand * op, iCode * ic)
5466 /* if true symbol then needs to be assigned */
5467 if (IS_TRUE_SYMOP (op))
5470 /* if this has register type condition and
5471 the next instruction is ifx with the same operand
5472 and live to of the operand is upto the ifx only then */
5474 ic->next->op == IFX &&
5475 IC_COND (ic->next)->key == op->key &&
5476 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5481 /*-----------------------------------------------------------------*/
5482 /* hasInc - operand is incremented before any other use */
5483 /*-----------------------------------------------------------------*/
5485 hasInc (operand *op, iCode *ic)
5487 sym_link *type = operandType(op);
5488 sym_link *retype = getSpec (type);
5489 iCode *lic = ic->next;
5492 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5493 if (!IS_SYMOP(op)) return NULL;
5495 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5496 isize = getSize(type->next);
5498 /* if operand of the form op = op + <sizeof *op> */
5499 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5500 isOperandEqual(IC_RESULT(lic),op) &&
5501 isOperandLiteral(IC_RIGHT(lic)) &&
5502 operandLitValue(IC_RIGHT(lic)) == isize) {
5505 /* if the operand used or deffed */
5506 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5509 /* if GOTO or IFX */
5510 if (lic->op == IFX || lic->op == GOTO) break;
5516 /*-----------------------------------------------------------------*/
5517 /* genAndOp - for && operation */
5518 /*-----------------------------------------------------------------*/
5520 genAndOp (iCode * ic)
5522 operand *left, *right, *result;
5525 D (emitcode (";", "genAndOp "););
5527 /* note here that && operations that are in an
5528 if statement are taken away by backPatchLabels
5529 only those used in arthmetic operations remain */
5531 AOP_SET_LOCALS (ic);
5533 /* if both are bit variables */
5534 if (AOP_TYPE (left) == AOP_CRY &&
5535 AOP_TYPE (right) == AOP_CRY)
5537 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5538 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5539 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5540 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5542 aopOp (result,ic,FALSE, FALSE);
5547 tlbl = newiTempLabel (NULL);
5549 emitcode ("jz", "%05d$", tlbl->key + 100);
5551 emitcode ("", "%05d$:", tlbl->key + 100);
5552 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5553 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5555 aopOp (result,ic,FALSE, FALSE);
5558 freeAsmop (result, NULL, ic, TRUE);
5562 /*-----------------------------------------------------------------*/
5563 /* genOrOp - for || operation */
5564 /*-----------------------------------------------------------------*/
5566 genOrOp (iCode * ic)
5568 operand *left, *right, *result;
5571 D (emitcode (";", "genOrOp "););
5573 /* note here that || operations that are in an
5574 if statement are taken away by backPatchLabels
5575 only those used in arthmetic operations remain */
5577 AOP_SET_LOCALS (ic);
5579 /* if both are bit variables */
5580 if (AOP_TYPE (left) == AOP_CRY &&
5581 AOP_TYPE (right) == AOP_CRY)
5583 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5584 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5585 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5586 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5588 aopOp (result,ic,FALSE, FALSE);
5594 tlbl = newiTempLabel (NULL);
5596 emitcode ("jnz", "%05d$", tlbl->key + 100);
5598 emitcode ("", "%05d$:", tlbl->key + 100);
5599 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5600 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5602 aopOp (result,ic,FALSE, FALSE);
5607 freeAsmop (result, NULL, ic, TRUE);
5610 /*-----------------------------------------------------------------*/
5611 /* isLiteralBit - test if lit == 2^n */
5612 /*-----------------------------------------------------------------*/
5614 isLiteralBit (unsigned long lit)
5616 unsigned long pw[32] =
5617 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5618 0x100L, 0x200L, 0x400L, 0x800L,
5619 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5620 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5621 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5622 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5623 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5626 for (idx = 0; idx < 32; idx++)
5632 /*-----------------------------------------------------------------*/
5633 /* continueIfTrue - */
5634 /*-----------------------------------------------------------------*/
5636 continueIfTrue (iCode * ic)
5639 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5643 /*-----------------------------------------------------------------*/
5645 /*-----------------------------------------------------------------*/
5647 jumpIfTrue (iCode * ic)
5650 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5654 /*-----------------------------------------------------------------*/
5655 /* jmpTrueOrFalse - */
5656 /*-----------------------------------------------------------------*/
5658 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5660 // ugly but optimized by peephole
5663 symbol *nlbl = newiTempLabel (NULL);
5664 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5665 emitcode ("", "%05d$:", tlbl->key + 100);
5666 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5667 emitcode ("", "%05d$:", nlbl->key + 100);
5671 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5672 emitcode ("", "%05d$:", tlbl->key + 100);
5677 // Generate code to perform a bit-wise logic operation
5678 // on two operands in far space (assumed to already have been
5679 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5680 // in far space. This requires pushing the result on the stack
5681 // then popping it into the result.
5683 genFarFarLogicOp(iCode *ic, char *logicOp)
5685 int size, resultSize, compSize;
5689 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5690 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5691 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5693 _startLazyDPSEvaluation();
5694 for (size = compSize; (size--); offset++)
5696 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5697 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5698 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5700 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5701 emitcode ("push", "acc");
5703 _endLazyDPSEvaluation();
5705 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5706 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5707 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5709 resultSize = AOP_SIZE(IC_RESULT(ic));
5711 ADJUST_PUSHED_RESULT(compSize, resultSize);
5713 _startLazyDPSEvaluation();
5716 emitcode ("pop", "acc");
5717 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5719 _endLazyDPSEvaluation();
5720 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5724 /*-----------------------------------------------------------------*/
5725 /* genAnd - code for and */
5726 /*-----------------------------------------------------------------*/
5728 genAnd (iCode * ic, iCode * ifx)
5730 operand *left, *right, *result;
5731 int size, offset = 0;
5732 unsigned long lit = 0L;
5737 D (emitcode (";", "genAnd "););
5739 AOP_OP_3_NOFATAL (ic, pushResult);
5740 AOP_SET_LOCALS (ic);
5744 genFarFarLogicOp(ic, "anl");
5749 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5751 AOP_TYPE (left), AOP_TYPE (right));
5752 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5754 AOP_SIZE (left), AOP_SIZE (right));
5757 /* if left is a literal & right is not then exchange them */
5758 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5759 #ifdef LOGIC_OPS_BROKEN
5760 || AOP_NEEDSACC (left)
5764 operand *tmp = right;
5769 /* if result = right then exchange them */
5770 if (sameRegs (AOP (result), AOP (right)))
5772 operand *tmp = right;
5777 /* if right is bit then exchange them */
5778 if (AOP_TYPE (right) == AOP_CRY &&
5779 AOP_TYPE (left) != AOP_CRY)
5781 operand *tmp = right;
5785 if (AOP_TYPE (right) == AOP_LIT)
5786 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5788 size = AOP_SIZE (result);
5791 // result = bit & yy;
5792 if (AOP_TYPE (left) == AOP_CRY)
5794 // c = bit & literal;
5795 if (AOP_TYPE (right) == AOP_LIT)
5799 if (size && sameRegs (AOP (result), AOP (left)))
5802 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5807 if (size && (AOP_TYPE (result) == AOP_CRY))
5809 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5812 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5817 emitcode ("clr", "c");
5822 if (AOP_TYPE (right) == AOP_CRY)
5825 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5826 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5831 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5833 emitcode ("rrc", "a");
5834 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5842 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5843 genIfxJump (ifx, "c");
5847 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5848 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5849 if ((AOP_TYPE (right) == AOP_LIT) &&
5850 (AOP_TYPE (result) == AOP_CRY) &&
5851 (AOP_TYPE (left) != AOP_CRY))
5853 int posbit = isLiteralBit (lit);
5858 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5861 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5867 sprintf (buffer, "acc.%d", posbit & 0x07);
5868 genIfxJump (ifx, buffer);
5875 symbol *tlbl = newiTempLabel (NULL);
5876 int sizel = AOP_SIZE (left);
5878 emitcode ("setb", "c");
5881 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5883 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5885 if ((posbit = isLiteralBit (bytelit)) != 0)
5886 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5889 if (bytelit != 0x0FFL)
5890 emitcode ("anl", "a,%s",
5891 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5892 emitcode ("jnz", "%05d$", tlbl->key + 100);
5897 // bit = left & literal
5900 emitcode ("clr", "c");
5901 emitcode ("", "%05d$:", tlbl->key + 100);
5903 // if(left & literal)
5907 jmpTrueOrFalse (ifx, tlbl);
5915 /* if left is same as result */
5916 if (sameRegs (AOP (result), AOP (left)))
5918 for (; size--; offset++)
5920 if (AOP_TYPE (right) == AOP_LIT)
5922 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5924 else if (bytelit == 0)
5925 aopPut (AOP (result), zero, offset);
5926 else if (IS_AOP_PREG (result))
5928 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5929 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5930 aopPut (AOP (result), "a", offset);
5933 emitcode ("anl", "%s,%s",
5934 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5935 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5939 if (AOP_TYPE (left) == AOP_ACC)
5940 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5943 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5944 if (IS_AOP_PREG (result))
5946 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5947 aopPut (AOP (result), "a", offset);
5951 emitcode ("anl", "%s,a",
5952 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5959 // left & result in different registers
5960 if (AOP_TYPE (result) == AOP_CRY)
5963 // if(size), result in bit
5964 // if(!size && ifx), conditional oper: if(left & right)
5965 symbol *tlbl = newiTempLabel (NULL);
5966 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5968 emitcode ("setb", "c");
5971 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5972 emitcode ("anl", "a,%s",
5973 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5975 if (AOP_TYPE(left)==AOP_ACC) {
5976 emitcode("mov", "b,a");
5977 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5978 emitcode("anl", "a,b");
5980 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5981 emitcode ("anl", "a,%s",
5982 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5985 emitcode ("jnz", "%05d$", tlbl->key + 100);
5991 emitcode ("", "%05d$:", tlbl->key + 100);
5995 jmpTrueOrFalse (ifx, tlbl);
5999 for (; (size--); offset++)
6002 // result = left & right
6003 if (AOP_TYPE (right) == AOP_LIT)
6005 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6007 aopPut (AOP (result),
6008 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6012 else if (bytelit == 0)
6014 aopPut (AOP (result), zero, offset);
6017 D (emitcode (";", "better literal AND."););
6018 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6019 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6020 FALSE, FALSE, FALSE));
6025 // faster than result <- left, anl result,right
6026 // and better if result is SFR
6027 if (AOP_TYPE (left) == AOP_ACC)
6029 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
6030 FALSE, FALSE, FALSE));
6034 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6035 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6037 emitcode("mov", "b,a");
6041 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6042 emitcode ("anl", "a,%s", rOp);
6045 aopPut (AOP (result), "a", offset);
6051 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6052 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6053 freeAsmop (result, NULL, ic, TRUE);
6057 /*-----------------------------------------------------------------*/
6058 /* genOr - code for or */
6059 /*-----------------------------------------------------------------*/
6061 genOr (iCode * ic, iCode * ifx)
6063 operand *left, *right, *result;
6064 int size, offset = 0;
6065 unsigned long lit = 0L;
6068 D (emitcode (";", "genOr "););
6070 AOP_OP_3_NOFATAL (ic, pushResult);
6071 AOP_SET_LOCALS (ic);
6075 genFarFarLogicOp(ic, "orl");
6081 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6083 AOP_TYPE (left), AOP_TYPE (right));
6084 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6086 AOP_SIZE (left), AOP_SIZE (right));
6089 /* if left is a literal & right is not then exchange them */
6090 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6091 #ifdef LOGIC_OPS_BROKEN
6092 || AOP_NEEDSACC (left) // I think this is a net loss now.
6096 operand *tmp = right;
6101 /* if result = right then exchange them */
6102 if (sameRegs (AOP (result), AOP (right)))
6104 operand *tmp = right;
6109 /* if right is bit then exchange them */
6110 if (AOP_TYPE (right) == AOP_CRY &&
6111 AOP_TYPE (left) != AOP_CRY)
6113 operand *tmp = right;
6117 if (AOP_TYPE (right) == AOP_LIT)
6118 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6120 size = AOP_SIZE (result);
6124 if (AOP_TYPE (left) == AOP_CRY)
6126 if (AOP_TYPE (right) == AOP_LIT)
6128 // c = bit & literal;
6131 // lit != 0 => result = 1
6132 if (AOP_TYPE (result) == AOP_CRY)
6135 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6137 continueIfTrue (ifx);
6140 emitcode ("setb", "c");
6144 // lit == 0 => result = left
6145 if (size && sameRegs (AOP (result), AOP (left)))
6147 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6152 if (AOP_TYPE (right) == AOP_CRY)
6155 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6156 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6161 symbol *tlbl = newiTempLabel (NULL);
6162 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6163 emitcode ("setb", "c");
6164 emitcode ("jb", "%s,%05d$",
6165 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6167 emitcode ("jnz", "%05d$", tlbl->key + 100);
6168 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6170 jmpTrueOrFalse (ifx, tlbl);
6176 emitcode ("", "%05d$:", tlbl->key + 100);
6185 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6186 genIfxJump (ifx, "c");
6190 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6191 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6192 if ((AOP_TYPE (right) == AOP_LIT) &&
6193 (AOP_TYPE (result) == AOP_CRY) &&
6194 (AOP_TYPE (left) != AOP_CRY))
6200 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6202 continueIfTrue (ifx);
6207 // lit = 0, result = boolean(left)
6209 emitcode ("setb", "c");
6213 symbol *tlbl = newiTempLabel (NULL);
6214 emitcode ("jnz", "%05d$", tlbl->key + 100);
6216 emitcode ("", "%05d$:", tlbl->key + 100);
6220 genIfxJump (ifx, "a");
6228 /* if left is same as result */
6229 if (sameRegs (AOP (result), AOP (left)))
6231 for (; size--; offset++)
6233 if (AOP_TYPE (right) == AOP_LIT)
6235 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6241 if (IS_AOP_PREG (left))
6243 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6244 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6245 aopPut (AOP (result), "a", offset);
6249 emitcode ("orl", "%s,%s",
6250 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6251 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6257 if (AOP_TYPE (left) == AOP_ACC)
6259 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6263 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6264 if (IS_AOP_PREG (left))
6266 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6267 aopPut (AOP (result), "a", offset);
6271 emitcode ("orl", "%s,a",
6272 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6280 // left & result in different registers
6281 if (AOP_TYPE (result) == AOP_CRY)
6284 // if(size), result in bit
6285 // if(!size && ifx), conditional oper: if(left | right)
6286 symbol *tlbl = newiTempLabel (NULL);
6287 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6289 emitcode ("setb", "c");
6292 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6293 emitcode ("orl", "a,%s",
6294 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6296 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6297 emitcode ("orl", "a,%s",
6298 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6300 emitcode ("jnz", "%05d$", tlbl->key + 100);
6306 emitcode ("", "%05d$:", tlbl->key + 100);
6310 jmpTrueOrFalse (ifx, tlbl);
6314 _startLazyDPSEvaluation();
6315 for (; (size--); offset++)
6318 // result = left & right
6319 if (AOP_TYPE (right) == AOP_LIT)
6321 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6323 aopPut (AOP (result),
6324 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6328 D (emitcode (";", "better literal OR."););
6329 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6330 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6331 FALSE, FALSE, FALSE));
6336 // faster than result <- left, anl result,right
6337 // and better if result is SFR
6338 if (AOP_TYPE (left) == AOP_ACC)
6340 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6341 FALSE, FALSE, FALSE));
6345 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6347 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6349 emitcode("mov", "b,a");
6353 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6354 emitcode ("orl", "a,%s", rOp);
6357 aopPut (AOP (result), "a", offset);
6359 _endLazyDPSEvaluation();
6364 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6365 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6366 freeAsmop (result, NULL, ic, TRUE);
6369 /*-----------------------------------------------------------------*/
6370 /* genXor - code for xclusive or */
6371 /*-----------------------------------------------------------------*/
6373 genXor (iCode * ic, iCode * ifx)
6375 operand *left, *right, *result;
6376 int size, offset = 0;
6377 unsigned long lit = 0L;
6380 D (emitcode (";", "genXor "););
6382 AOP_OP_3_NOFATAL (ic, pushResult);
6383 AOP_SET_LOCALS (ic);
6387 genFarFarLogicOp(ic, "xrl");
6392 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6394 AOP_TYPE (left), AOP_TYPE (right));
6395 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6397 AOP_SIZE (left), AOP_SIZE (right));
6400 /* if left is a literal & right is not ||
6401 if left needs acc & right does not */
6402 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6403 #ifdef LOGIC_OPS_BROKEN
6404 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6408 operand *tmp = right;
6413 /* if result = right then exchange them */
6414 if (sameRegs (AOP (result), AOP (right)))
6416 operand *tmp = right;
6421 /* if right is bit then exchange them */
6422 if (AOP_TYPE (right) == AOP_CRY &&
6423 AOP_TYPE (left) != AOP_CRY)
6425 operand *tmp = right;
6429 if (AOP_TYPE (right) == AOP_LIT)
6430 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6432 size = AOP_SIZE (result);
6436 if (AOP_TYPE (left) == AOP_CRY)
6438 if (AOP_TYPE (right) == AOP_LIT)
6440 // c = bit & literal;
6443 // lit>>1 != 0 => result = 1
6444 if (AOP_TYPE (result) == AOP_CRY)
6447 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6449 continueIfTrue (ifx);
6452 emitcode ("setb", "c");
6459 // lit == 0, result = left
6460 if (size && sameRegs (AOP (result), AOP (left)))
6462 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6466 // lit == 1, result = not(left)
6467 if (size && sameRegs (AOP (result), AOP (left)))
6469 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6474 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6475 emitcode ("cpl", "c");
6484 symbol *tlbl = newiTempLabel (NULL);
6485 if (AOP_TYPE (right) == AOP_CRY)
6488 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6492 int sizer = AOP_SIZE (right);
6494 // if val>>1 != 0, result = 1
6495 emitcode ("setb", "c");
6498 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6500 // test the msb of the lsb
6501 emitcode ("anl", "a,#0xfe");
6502 emitcode ("jnz", "%05d$", tlbl->key + 100);
6506 emitcode ("rrc", "a");
6508 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6509 emitcode ("cpl", "c");
6510 emitcode ("", "%05d$:", (tlbl->key + 100));
6517 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6518 genIfxJump (ifx, "c");
6522 if (sameRegs (AOP (result), AOP (left)))
6524 /* if left is same as result */
6525 for (; size--; offset++)
6527 if (AOP_TYPE (right) == AOP_LIT)
6529 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6531 else if (IS_AOP_PREG (left))
6533 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6534 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6535 aopPut (AOP (result), "a", offset);
6538 emitcode ("xrl", "%s,%s",
6539 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6540 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6544 if (AOP_TYPE (left) == AOP_ACC)
6545 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6548 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6549 if (IS_AOP_PREG (left))
6551 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6552 aopPut (AOP (result), "a", offset);
6555 emitcode ("xrl", "%s,a",
6556 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6563 // left & result in different registers
6564 if (AOP_TYPE (result) == AOP_CRY)
6567 // if(size), result in bit
6568 // if(!size && ifx), conditional oper: if(left ^ right)
6569 symbol *tlbl = newiTempLabel (NULL);
6570 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6573 emitcode ("setb", "c");
6576 if ((AOP_TYPE (right) == AOP_LIT) &&
6577 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6579 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6583 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6584 emitcode ("xrl", "a,%s",
6585 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6587 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6588 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6590 emitcode("mov", "b,a");
6594 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6595 emitcode ("xrl", "a,%s", rOp);
6598 emitcode ("jnz", "%05d$", tlbl->key + 100);
6604 emitcode ("", "%05d$:", tlbl->key + 100);
6608 jmpTrueOrFalse (ifx, tlbl);
6612 for (; (size--); offset++)
6615 // result = left & right
6616 if (AOP_TYPE (right) == AOP_LIT)
6618 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6620 aopPut (AOP (result),
6621 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6625 D (emitcode (";", "better literal XOR."););
6626 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6627 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6628 FALSE, FALSE, FALSE));
6632 // faster than result <- left, anl result,right
6633 // and better if result is SFR
6634 if (AOP_TYPE (left) == AOP_ACC)
6636 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6637 FALSE, FALSE, FALSE));
6641 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6642 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6644 emitcode("mov", "b,a");
6648 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6649 emitcode ("xrl", "a,%s", rOp);
6652 aopPut (AOP (result), "a", offset);
6659 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6660 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6661 freeAsmop (result, NULL, ic, TRUE);
6664 /*-----------------------------------------------------------------*/
6665 /* genInline - write the inline code out */
6666 /*-----------------------------------------------------------------*/
6668 genInline (iCode * ic)
6670 char *buffer, *bp, *bp1;
6672 D (emitcode (";", "genInline ");
6675 _G.inLine += (!options.asmpeep);
6677 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6678 strcpy (buffer, IC_INLINE (ic));
6680 /* emit each line as a code */
6705 /* emitcode("",buffer); */
6706 _G.inLine -= (!options.asmpeep);
6709 /*-----------------------------------------------------------------*/
6710 /* genRRC - rotate right with carry */
6711 /*-----------------------------------------------------------------*/
6715 operand *left, *result;
6716 int size, offset = 0;
6719 D (emitcode (";", "genRRC ");
6722 /* rotate right with carry */
6723 left = IC_LEFT (ic);
6724 result = IC_RESULT (ic);
6725 aopOp (left, ic, FALSE, FALSE);
6726 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6728 /* move it to the result */
6729 size = AOP_SIZE (result);
6733 _startLazyDPSEvaluation ();
6736 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6738 emitcode ("rrc", "a");
6739 if (AOP_SIZE (result) > 1)
6740 aopPut (AOP (result), "a", offset--);
6742 _endLazyDPSEvaluation ();
6744 /* now we need to put the carry into the
6745 highest order byte of the result */
6746 if (AOP_SIZE (result) > 1)
6748 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6751 emitcode ("mov", "acc.7,c");
6752 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6753 freeAsmop (left, NULL, ic, TRUE);
6754 freeAsmop (result, NULL, ic, TRUE);
6757 /*-----------------------------------------------------------------*/
6758 /* genRLC - generate code for rotate left with carry */
6759 /*-----------------------------------------------------------------*/
6763 operand *left, *result;
6764 int size, offset = 0;
6767 D (emitcode (";", "genRLC ");
6770 /* rotate right with carry */
6771 left = IC_LEFT (ic);
6772 result = IC_RESULT (ic);
6773 aopOp (left, ic, FALSE, FALSE);
6774 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6776 /* move it to the result */
6777 size = AOP_SIZE (result);
6781 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6783 emitcode ("add", "a,acc");
6784 if (AOP_SIZE (result) > 1)
6786 aopPut (AOP (result), "a", offset++);
6789 _startLazyDPSEvaluation ();
6792 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6794 emitcode ("rlc", "a");
6795 if (AOP_SIZE (result) > 1)
6796 aopPut (AOP (result), "a", offset++);
6798 _endLazyDPSEvaluation ();
6800 /* now we need to put the carry into the
6801 highest order byte of the result */
6802 if (AOP_SIZE (result) > 1)
6804 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6807 emitcode ("mov", "acc.0,c");
6808 aopPut (AOP (result), "a", 0);
6809 freeAsmop (left, NULL, ic, TRUE);
6810 freeAsmop (result, NULL, ic, TRUE);
6813 /*-----------------------------------------------------------------*/
6814 /* genGetHbit - generates code get highest order bit */
6815 /*-----------------------------------------------------------------*/
6817 genGetHbit (iCode * ic)
6819 operand *left, *result;
6820 left = IC_LEFT (ic);
6821 result = IC_RESULT (ic);
6822 aopOp (left, ic, FALSE, FALSE);
6823 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6825 D (emitcode (";", "genGetHbit ");
6828 /* get the highest order byte into a */
6829 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6830 if (AOP_TYPE (result) == AOP_CRY)
6832 emitcode ("rlc", "a");
6837 emitcode ("rl", "a");
6838 emitcode ("anl", "a,#0x01");
6843 freeAsmop (left, NULL, ic, TRUE);
6844 freeAsmop (result, NULL, ic, TRUE);
6847 /*-----------------------------------------------------------------*/
6848 /* AccRol - rotate left accumulator by known count */
6849 /*-----------------------------------------------------------------*/
6851 AccRol (int shCount)
6853 shCount &= 0x0007; // shCount : 0..7
6860 emitcode ("rl", "a");
6863 emitcode ("rl", "a");
6864 emitcode ("rl", "a");
6867 emitcode ("swap", "a");
6868 emitcode ("rr", "a");
6871 emitcode ("swap", "a");
6874 emitcode ("swap", "a");
6875 emitcode ("rl", "a");
6878 emitcode ("rr", "a");
6879 emitcode ("rr", "a");
6882 emitcode ("rr", "a");
6887 /*-----------------------------------------------------------------*/
6888 /* AccLsh - left shift accumulator by known count */
6889 /*-----------------------------------------------------------------*/
6891 AccLsh (int shCount)
6896 emitcode ("add", "a,acc");
6897 else if (shCount == 2)
6899 emitcode ("add", "a,acc");
6900 emitcode ("add", "a,acc");
6904 /* rotate left accumulator */
6906 /* and kill the lower order bits */
6907 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6912 /*-----------------------------------------------------------------*/
6913 /* AccRsh - right shift accumulator by known count */
6914 /*-----------------------------------------------------------------*/
6916 AccRsh (int shCount)
6923 emitcode ("rrc", "a");
6927 /* rotate right accumulator */
6928 AccRol (8 - shCount);
6929 /* and kill the higher order bits */
6930 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6935 #ifdef BETTER_LITERAL_SHIFT
6936 /*-----------------------------------------------------------------*/
6937 /* AccSRsh - signed right shift accumulator by known count */
6938 /*-----------------------------------------------------------------*/
6940 AccSRsh (int shCount)
6947 emitcode ("mov", "c,acc.7");
6948 emitcode ("rrc", "a");
6950 else if (shCount == 2)
6952 emitcode ("mov", "c,acc.7");
6953 emitcode ("rrc", "a");
6954 emitcode ("mov", "c,acc.7");
6955 emitcode ("rrc", "a");
6959 tlbl = newiTempLabel (NULL);
6960 /* rotate right accumulator */
6961 AccRol (8 - shCount);
6962 /* and kill the higher order bits */
6963 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6964 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6965 emitcode ("orl", "a,#0x%02x",
6966 (unsigned char) ~SRMask[shCount]);
6967 emitcode ("", "%05d$:", tlbl->key + 100);
6973 #ifdef BETTER_LITERAL_SHIFT
6974 /*-----------------------------------------------------------------*/
6975 /* shiftR1Left2Result - shift right one byte from left to result */
6976 /*-----------------------------------------------------------------*/
6978 shiftR1Left2Result (operand * left, int offl,
6979 operand * result, int offr,
6980 int shCount, int sign)
6982 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6983 /* shift right accumulator */
6988 aopPut (AOP (result), "a", offr);
6992 #ifdef BETTER_LITERAL_SHIFT
6993 /*-----------------------------------------------------------------*/
6994 /* shiftL1Left2Result - shift left one byte from left to result */
6995 /*-----------------------------------------------------------------*/
6997 shiftL1Left2Result (operand * left, int offl,
6998 operand * result, int offr, int shCount)
7000 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7001 /* shift left accumulator */
7003 aopPut (AOP (result), "a", offr);
7007 #ifdef BETTER_LITERAL_SHIFT
7008 /*-----------------------------------------------------------------*/
7009 /* movLeft2Result - move byte from left to result */
7010 /*-----------------------------------------------------------------*/
7012 movLeft2Result (operand * left, int offl,
7013 operand * result, int offr, int sign)
7016 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7018 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
7020 if (*l == '@' && (IS_AOP_PREG (result)))
7022 emitcode ("mov", "a,%s", l);
7023 aopPut (AOP (result), "a", offr);
7029 aopPut (AOP (result), l, offr);
7033 /* MSB sign in acc.7 ! */
7034 if (getDataSize (left) == offl + 1)
7036 emitcode ("mov", "a,%s", l);
7037 aopPut (AOP (result), "a", offr);
7045 #ifdef BETTER_LITERAL_SHIFT
7046 /*-----------------------------------------------------------------*/
7047 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7048 /*-----------------------------------------------------------------*/
7052 emitcode ("rrc", "a");
7053 emitcode ("xch", "a,%s", x);
7054 emitcode ("rrc", "a");
7055 emitcode ("xch", "a,%s", x);
7059 #ifdef BETTER_LITERAL_SHIFT
7061 /*-----------------------------------------------------------------*/
7062 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7063 /*-----------------------------------------------------------------*/
7067 emitcode ("xch", "a,%s", x);
7068 emitcode ("rlc", "a");
7069 emitcode ("xch", "a,%s", x);
7070 emitcode ("rlc", "a");
7074 #ifdef BETTER_LITERAL_SHIFT
7075 /*-----------------------------------------------------------------*/
7076 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7077 /*-----------------------------------------------------------------*/
7081 emitcode ("xch", "a,%s", x);
7082 emitcode ("add", "a,acc");
7083 emitcode ("xch", "a,%s", x);
7084 emitcode ("rlc", "a");
7088 #ifdef BETTER_LITERAL_SHIFT
7089 /*-----------------------------------------------------------------*/
7090 /* AccAXLsh - left shift a:x by known count (0..7) */
7091 /*-----------------------------------------------------------------*/
7093 AccAXLsh (char *x, int shCount)
7108 case 5: // AAAAABBB:CCCCCDDD
7110 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7112 emitcode ("anl", "a,#0x%02x",
7113 SLMask[shCount]); // BBB00000:CCCCCDDD
7115 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7117 AccRol (shCount); // DDDCCCCC:BBB00000
7119 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7121 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7123 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7125 emitcode ("anl", "a,#0x%02x",
7126 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7128 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7130 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7133 case 6: // AAAAAABB:CCCCCCDD
7134 emitcode ("anl", "a,#0x%02x",
7135 SRMask[shCount]); // 000000BB:CCCCCCDD
7136 emitcode ("mov", "c,acc.0"); // c = B
7137 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7139 AccAXRrl1 (x); // BCCCCCCD:D000000B
7140 AccAXRrl1 (x); // BBCCCCCC:DD000000
7142 emitcode("rrc","a");
7143 emitcode("xch","a,%s", x);
7144 emitcode("rrc","a");
7145 emitcode("mov","c,acc.0"); //<< get correct bit
7146 emitcode("xch","a,%s", x);
7148 emitcode("rrc","a");
7149 emitcode("xch","a,%s", x);
7150 emitcode("rrc","a");
7151 emitcode("xch","a,%s", x);
7154 case 7: // a:x <<= 7
7156 emitcode ("anl", "a,#0x%02x",
7157 SRMask[shCount]); // 0000000B:CCCCCCCD
7159 emitcode ("mov", "c,acc.0"); // c = B
7161 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7163 AccAXRrl1 (x); // BCCCCCCC:D0000000
7172 #ifdef BETTER_LITERAL_SHIFT
7174 /*-----------------------------------------------------------------*/
7175 /* AccAXRsh - right shift a:x known count (0..7) */
7176 /*-----------------------------------------------------------------*/
7178 AccAXRsh (char *x, int shCount)
7186 AccAXRrl1 (x); // 0->a:x
7191 AccAXRrl1 (x); // 0->a:x
7194 AccAXRrl1 (x); // 0->a:x
7199 case 5: // AAAAABBB:CCCCCDDD = a:x
7201 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7203 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7205 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7207 emitcode ("anl", "a,#0x%02x",
7208 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7210 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7212 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7214 emitcode ("anl", "a,#0x%02x",
7215 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7217 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7219 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7221 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7224 case 6: // AABBBBBB:CCDDDDDD
7226 emitcode ("mov", "c,acc.7");
7227 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7229 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7231 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7233 emitcode ("anl", "a,#0x%02x",
7234 SRMask[shCount]); // 000000AA:BBBBBBCC
7237 case 7: // ABBBBBBB:CDDDDDDD
7239 emitcode ("mov", "c,acc.7"); // c = A
7241 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7243 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7245 emitcode ("anl", "a,#0x%02x",
7246 SRMask[shCount]); // 0000000A:BBBBBBBC
7255 #ifdef BETTER_LITERAL_SHIFT
7256 /*-----------------------------------------------------------------*/
7257 /* AccAXRshS - right shift signed a:x known count (0..7) */
7258 /*-----------------------------------------------------------------*/
7260 AccAXRshS (char *x, int shCount)
7268 emitcode ("mov", "c,acc.7");
7269 AccAXRrl1 (x); // s->a:x
7273 emitcode ("mov", "c,acc.7");
7274 AccAXRrl1 (x); // s->a:x
7276 emitcode ("mov", "c,acc.7");
7277 AccAXRrl1 (x); // s->a:x
7282 case 5: // AAAAABBB:CCCCCDDD = a:x
7284 tlbl = newiTempLabel (NULL);
7285 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7287 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7289 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7291 emitcode ("anl", "a,#0x%02x",
7292 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7294 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7296 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7298 emitcode ("anl", "a,#0x%02x",
7299 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7301 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7303 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7305 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7307 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7308 emitcode ("orl", "a,#0x%02x",
7309 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7311 emitcode ("", "%05d$:", tlbl->key + 100);
7312 break; // SSSSAAAA:BBBCCCCC
7314 case 6: // AABBBBBB:CCDDDDDD
7316 tlbl = newiTempLabel (NULL);
7317 emitcode ("mov", "c,acc.7");
7318 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7320 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7322 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7324 emitcode ("anl", "a,#0x%02x",
7325 SRMask[shCount]); // 000000AA:BBBBBBCC
7327 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7328 emitcode ("orl", "a,#0x%02x",
7329 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7331 emitcode ("", "%05d$:", tlbl->key + 100);
7333 case 7: // ABBBBBBB:CDDDDDDD
7335 tlbl = newiTempLabel (NULL);
7336 emitcode ("mov", "c,acc.7"); // c = A
7338 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7340 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7342 emitcode ("anl", "a,#0x%02x",
7343 SRMask[shCount]); // 0000000A:BBBBBBBC
7345 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7346 emitcode ("orl", "a,#0x%02x",
7347 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7349 emitcode ("", "%05d$:", tlbl->key + 100);
7357 #ifdef BETTER_LITERAL_SHIFT
7359 _loadLeftIntoAx(char **lsb,
7365 // Get the initial value from left into a pair of registers.
7366 // MSB must be in A, LSB can be any register.
7368 // If the result is held in registers, it is an optimization
7369 // if the LSB can be held in the register which will hold the,
7370 // result LSB since this saves us from having to copy it into
7371 // the result following AccAXLsh.
7373 // If the result is addressed indirectly, this is not a gain.
7374 if (AOP_NEEDSACC(result))
7378 _startLazyDPSEvaluation();
7379 if (AOP_TYPE(left) == AOP_DPTR2)
7382 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7383 // get LSB in DP2_RESULT_REG.
7384 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7385 assert(!strcmp(leftByte, DP2_RESULT_REG));
7389 // get LSB into DP2_RESULT_REG
7390 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7391 if (strcmp(leftByte, DP2_RESULT_REG))
7394 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7397 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7398 assert(strcmp(leftByte, DP2_RESULT_REG));
7401 _endLazyDPSEvaluation();
7402 *lsb = DP2_RESULT_REG;
7406 if (sameRegs (AOP (result), AOP (left)) &&
7407 ((offl + MSB16) == offr))
7409 /* don't crash result[offr] */
7410 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7411 emitcode ("xch", "a,%s",
7412 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7416 movLeft2Result (left, offl, result, offr, 0);
7417 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7419 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7420 assert(strcmp(*lsb,"a"));
7425 _storeAxResults(char *lsb,
7429 _startLazyDPSEvaluation();
7430 if (AOP_NEEDSACC(result))
7432 /* We have to explicitly update the result LSB.
7434 emitcode("xch","a,%s", lsb);
7435 aopPut(AOP(result), "a", offr);
7436 emitcode("mov","a,%s", lsb);
7438 if (getDataSize (result) > 1)
7440 aopPut (AOP (result), "a", offr + MSB16);
7442 _endLazyDPSEvaluation();
7445 /*-----------------------------------------------------------------*/
7446 /* shiftL2Left2Result - shift left two bytes from left to result */
7447 /*-----------------------------------------------------------------*/
7449 shiftL2Left2Result (operand * left, int offl,
7450 operand * result, int offr, int shCount)
7454 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7456 AccAXLsh (lsb, shCount);
7458 _storeAxResults(lsb, result, offr);
7462 #ifdef BETTER_LITERAL_SHIFT
7463 /*-----------------------------------------------------------------*/
7464 /* shiftR2Left2Result - shift right two bytes from left to result */
7465 /*-----------------------------------------------------------------*/
7467 shiftR2Left2Result (operand * left, int offl,
7468 operand * result, int offr,
7469 int shCount, int sign)
7473 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7475 /* a:x >> shCount (x = lsb(result)) */
7478 AccAXRshS(lsb, shCount);
7482 AccAXRsh(lsb, shCount);
7485 _storeAxResults(lsb, result, offr);
7491 /*-----------------------------------------------------------------*/
7492 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7493 /*-----------------------------------------------------------------*/
7495 shiftLLeftOrResult (operand * left, int offl,
7496 operand * result, int offr, int shCount)
7498 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7499 /* shift left accumulator */
7501 /* or with result */
7502 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7503 /* back to result */
7504 aopPut (AOP (result), "a", offr);
7510 /*-----------------------------------------------------------------*/
7511 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7512 /*-----------------------------------------------------------------*/
7514 shiftRLeftOrResult (operand * left, int offl,
7515 operand * result, int offr, int shCount)
7517 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7518 /* shift right accumulator */
7520 /* or with result */
7521 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7522 /* back to result */
7523 aopPut (AOP (result), "a", offr);
7527 #ifdef BETTER_LITERAL_SHIFT
7528 /*-----------------------------------------------------------------*/
7529 /* genlshOne - left shift a one byte quantity by known count */
7530 /*-----------------------------------------------------------------*/
7532 genlshOne (operand * result, operand * left, int shCount)
7534 D (emitcode (";", "genlshOne "););
7535 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7539 #ifdef BETTER_LITERAL_SHIFT
7540 /*-----------------------------------------------------------------*/
7541 /* genlshTwo - left shift two bytes by known amount != 0 */
7542 /*-----------------------------------------------------------------*/
7544 genlshTwo (operand * result, operand * left, int shCount)
7548 D (emitcode (";", "genlshTwo "););
7550 size = getDataSize (result);
7552 /* if shCount >= 8 */
7557 _startLazyDPSEvaluation();
7563 _endLazyDPSEvaluation();
7564 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7565 aopPut (AOP (result), zero, LSB);
7569 movLeft2Result (left, LSB, result, MSB16, 0);
7570 aopPut (AOP (result), zero, LSB);
7571 _endLazyDPSEvaluation();
7576 aopPut (AOP (result), zero, LSB);
7577 _endLazyDPSEvaluation();
7581 /* 1 <= shCount <= 7 */
7586 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7590 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7598 /*-----------------------------------------------------------------*/
7599 /* shiftLLong - shift left one long from left to result */
7600 /* offl = LSB or MSB16 */
7601 /*-----------------------------------------------------------------*/
7603 shiftLLong (operand * left, operand * result, int offr)
7606 int size = AOP_SIZE (result);
7608 if (size >= LSB + offr)
7610 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7612 emitcode ("add", "a,acc");
7613 if (sameRegs (AOP (left), AOP (result)) &&
7614 size >= MSB16 + offr && offr != LSB)
7615 emitcode ("xch", "a,%s",
7616 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7618 aopPut (AOP (result), "a", LSB + offr);
7621 if (size >= MSB16 + offr)
7623 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7625 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7628 emitcode ("rlc", "a");
7629 if (sameRegs (AOP (left), AOP (result)) &&
7630 size >= MSB24 + offr && offr != LSB)
7631 emitcode ("xch", "a,%s",
7632 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7634 aopPut (AOP (result), "a", MSB16 + offr);
7637 if (size >= MSB24 + offr)
7639 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7641 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7644 emitcode ("rlc", "a");
7645 if (sameRegs (AOP (left), AOP (result)) &&
7646 size >= MSB32 + offr && offr != LSB)
7647 emitcode ("xch", "a,%s",
7648 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7650 aopPut (AOP (result), "a", MSB24 + offr);
7653 if (size > MSB32 + offr)
7655 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7657 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7660 emitcode ("rlc", "a");
7661 aopPut (AOP (result), "a", MSB32 + offr);
7664 aopPut (AOP (result), zero, LSB);
7670 /*-----------------------------------------------------------------*/
7671 /* genlshFour - shift four byte by a known amount != 0 */
7672 /*-----------------------------------------------------------------*/
7674 genlshFour (operand * result, operand * left, int shCount)
7678 D (emitcode (";", "genlshFour ");
7681 size = AOP_SIZE (result);
7683 /* if shifting more that 3 bytes */
7688 /* lowest order of left goes to the highest
7689 order of the destination */
7690 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7692 movLeft2Result (left, LSB, result, MSB32, 0);
7693 aopPut (AOP (result), zero, LSB);
7694 aopPut (AOP (result), zero, MSB16);
7695 aopPut (AOP (result), zero, MSB24);
7699 /* more than two bytes */
7700 else if (shCount >= 16)
7702 /* lower order two bytes goes to higher order two bytes */
7704 /* if some more remaining */
7706 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7709 movLeft2Result (left, MSB16, result, MSB32, 0);
7710 movLeft2Result (left, LSB, result, MSB24, 0);
7712 aopPut (AOP (result), zero, MSB16);
7713 aopPut (AOP (result), zero, LSB);
7717 /* if more than 1 byte */
7718 else if (shCount >= 8)
7720 /* lower order three bytes goes to higher order three bytes */
7725 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7727 movLeft2Result (left, LSB, result, MSB16, 0);
7733 movLeft2Result (left, MSB24, result, MSB32, 0);
7734 movLeft2Result (left, MSB16, result, MSB24, 0);
7735 movLeft2Result (left, LSB, result, MSB16, 0);
7736 aopPut (AOP (result), zero, LSB);
7738 else if (shCount == 1)
7739 shiftLLong (left, result, MSB16);
7742 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7743 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7744 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7745 aopPut (AOP (result), zero, LSB);
7750 /* 1 <= shCount <= 7 */
7751 else if (shCount <= 2)
7753 shiftLLong (left, result, LSB);
7755 shiftLLong (result, result, LSB);
7757 /* 3 <= shCount <= 7, optimize */
7760 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7761 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7762 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7767 #ifdef BETTER_LITERAL_SHIFT
7768 /*-----------------------------------------------------------------*/
7769 /* genLeftShiftLiteral - left shifting by known count */
7770 /*-----------------------------------------------------------------*/
7772 genLeftShiftLiteral (operand * left,
7777 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7780 size = getSize (operandType (result));
7782 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7784 /* We only handle certain easy cases so far. */
7786 && (shCount < (size * 8))
7790 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7794 freeAsmop (right, NULL, ic, TRUE);
7796 aopOp(left, ic, FALSE, FALSE);
7797 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7800 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7802 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7803 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7805 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7808 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7810 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7811 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7813 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7819 emitcode ("; shift left ", "result %d, left %d", size,
7823 /* I suppose that the left size >= result size */
7826 _startLazyDPSEvaluation();
7829 movLeft2Result (left, size, result, size, 0);
7831 _endLazyDPSEvaluation();
7833 else if (shCount >= (size * 8))
7835 _startLazyDPSEvaluation();
7838 aopPut (AOP (result), zero, size);
7840 _endLazyDPSEvaluation();
7847 genlshOne (result, left, shCount);
7851 genlshTwo (result, left, shCount);
7855 genlshFour (result, left, shCount);
7859 fprintf(stderr, "*** ack! mystery literal shift!\n");
7863 freeAsmop (left, NULL, ic, TRUE);
7864 freeAsmop (result, NULL, ic, TRUE);
7869 /*-----------------------------------------------------------------*/
7870 /* genLeftShift - generates code for left shifting */
7871 /*-----------------------------------------------------------------*/
7873 genLeftShift (iCode * ic)
7875 operand *left, *right, *result;
7878 symbol *tlbl, *tlbl1;
7880 D (emitcode (";", "genLeftShift "););
7882 right = IC_RIGHT (ic);
7883 left = IC_LEFT (ic);
7884 result = IC_RESULT (ic);
7886 aopOp (right, ic, FALSE, FALSE);
7889 #ifdef BETTER_LITERAL_SHIFT
7890 /* if the shift count is known then do it
7891 as efficiently as possible */
7892 if (AOP_TYPE (right) == AOP_LIT)
7894 if (genLeftShiftLiteral (left, right, result, ic))
7901 /* shift count is unknown then we have to form
7902 a loop get the loop count in B : Note: we take
7903 only the lower order byte since shifting
7904 more that 32 bits make no sense anyway, ( the
7905 largest size of an object can be only 32 bits ) */
7907 if (AOP_TYPE (right) == AOP_LIT)
7909 /* Really should be handled by genLeftShiftLiteral,
7910 * but since I'm too lazy to fix that today, at least we can make
7911 * some small improvement.
7913 emitcode("mov", "b,#0x%02x",
7914 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7918 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7919 emitcode ("inc", "b");
7921 freeAsmop (right, NULL, ic, TRUE);
7922 aopOp (left, ic, FALSE, FALSE);
7923 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7925 /* now move the left to the result if they are not the
7927 if (!sameRegs (AOP (left), AOP (result)) &&
7928 AOP_SIZE (result) > 1)
7931 size = AOP_SIZE (result);
7933 _startLazyDPSEvaluation ();
7936 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7937 if (*l == '@' && (IS_AOP_PREG (result)))
7940 emitcode ("mov", "a,%s", l);
7941 aopPut (AOP (result), "a", offset);
7944 aopPut (AOP (result), l, offset);
7947 _endLazyDPSEvaluation ();
7950 tlbl = newiTempLabel (NULL);
7951 size = AOP_SIZE (result);
7953 tlbl1 = newiTempLabel (NULL);
7955 /* if it is only one byte then */
7958 symbol *tlbl1 = newiTempLabel (NULL);
7960 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7962 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7963 emitcode ("", "%05d$:", tlbl->key + 100);
7964 emitcode ("add", "a,acc");
7965 emitcode ("", "%05d$:", tlbl1->key + 100);
7966 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7967 aopPut (AOP (result), "a", 0);
7971 reAdjustPreg (AOP (result));
7973 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7974 emitcode ("", "%05d$:", tlbl->key + 100);
7975 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7977 emitcode ("add", "a,acc");
7978 aopPut (AOP (result), "a", offset++);
7979 _startLazyDPSEvaluation ();
7982 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7984 emitcode ("rlc", "a");
7985 aopPut (AOP (result), "a", offset++);
7987 _endLazyDPSEvaluation ();
7988 reAdjustPreg (AOP (result));
7990 emitcode ("", "%05d$:", tlbl1->key + 100);
7991 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7993 freeAsmop (left, NULL, ic, TRUE);
7994 freeAsmop (result, NULL, ic, TRUE);
7997 #ifdef BETTER_LITERAL_SHIFT
7998 /*-----------------------------------------------------------------*/
7999 /* genrshOne - right shift a one byte quantity by known count */
8000 /*-----------------------------------------------------------------*/
8002 genrshOne (operand * result, operand * left,
8003 int shCount, int sign)
8005 D (emitcode (";", "genrshOne"););
8006 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8010 #ifdef BETTER_LITERAL_SHIFT
8011 /*-----------------------------------------------------------------*/
8012 /* genrshTwo - right shift two bytes by known amount != 0 */
8013 /*-----------------------------------------------------------------*/
8015 genrshTwo (operand * result, operand * left,
8016 int shCount, int sign)
8018 D (emitcode (";", "genrshTwo"););
8020 /* if shCount >= 8 */
8024 _startLazyDPSEvaluation();
8027 shiftR1Left2Result (left, MSB16, result, LSB,
8032 movLeft2Result (left, MSB16, result, LSB, sign);
8034 addSign (result, MSB16, sign);
8035 _endLazyDPSEvaluation();
8038 /* 1 <= shCount <= 7 */
8041 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8048 /*-----------------------------------------------------------------*/
8049 /* shiftRLong - shift right one long from left to result */
8050 /* offl = LSB or MSB16 */
8051 /*-----------------------------------------------------------------*/
8053 shiftRLong (operand * left, int offl,
8054 operand * result, int sign)
8056 int isSameRegs=sameRegs(AOP(left),AOP(result));
8058 if (isSameRegs && offl>1) {
8059 // we are in big trouble, but this shouldn't happen
8060 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8063 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
8068 emitcode ("rlc", "a");
8069 emitcode ("subb", "a,acc");
8070 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
8072 aopPut (AOP(result), zero, MSB32);
8077 emitcode ("clr", "c");
8079 emitcode ("mov", "c,acc.7");
8082 emitcode ("rrc", "a");
8084 if (isSameRegs && offl==MSB16) {
8085 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
8087 aopPut (AOP (result), "a", MSB32);
8088 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
8091 emitcode ("rrc", "a");
8092 if (isSameRegs && offl==1) {
8093 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
8095 aopPut (AOP (result), "a", MSB24);
8096 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
8098 emitcode ("rrc", "a");
8099 aopPut (AOP (result), "a", MSB16 - offl);
8103 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
8104 emitcode ("rrc", "a");
8105 aopPut (AOP (result), "a", LSB);
8112 /*-----------------------------------------------------------------*/
8113 /* genrshFour - shift four byte by a known amount != 0 */
8114 /*-----------------------------------------------------------------*/
8116 genrshFour (operand * result, operand * left,
8117 int shCount, int sign)
8119 D (emitcode (";", "genrshFour");
8122 /* if shifting more that 3 bytes */
8127 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8129 movLeft2Result (left, MSB32, result, LSB, sign);
8130 addSign (result, MSB16, sign);
8132 else if (shCount >= 16)
8136 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8139 movLeft2Result (left, MSB24, result, LSB, 0);
8140 movLeft2Result (left, MSB32, result, MSB16, sign);
8142 addSign (result, MSB24, sign);
8144 else if (shCount >= 8)
8148 shiftRLong (left, MSB16, result, sign);
8149 else if (shCount == 0)
8151 movLeft2Result (left, MSB16, result, LSB, 0);
8152 movLeft2Result (left, MSB24, result, MSB16, 0);
8153 movLeft2Result (left, MSB32, result, MSB24, sign);
8154 addSign (result, MSB32, sign);
8158 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8159 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8160 /* the last shift is signed */
8161 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8162 addSign (result, MSB32, sign);
8166 { /* 1 <= shCount <= 7 */
8169 shiftRLong (left, LSB, result, sign);
8171 shiftRLong (result, LSB, result, sign);
8175 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8176 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8177 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8183 #ifdef BETTER_LITERAL_SHIFT
8184 /*-----------------------------------------------------------------*/
8185 /* genRightShiftLiteral - right shifting by known count */
8186 /*-----------------------------------------------------------------*/
8188 genRightShiftLiteral (operand * left,
8194 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8197 size = getSize (operandType (result));
8199 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8201 /* We only handle certain easy cases so far. */
8203 && (shCount < (size * 8))
8207 D(emitcode (";", "genRightShiftLiteral wimping out"););
8211 freeAsmop (right, NULL, ic, TRUE);
8213 aopOp (left, ic, FALSE, FALSE);
8214 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8217 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8221 /* test the LEFT size !!! */
8223 /* I suppose that the left size >= result size */
8226 size = getDataSize (result);
8227 _startLazyDPSEvaluation();
8230 movLeft2Result (left, size, result, size, 0);
8232 _endLazyDPSEvaluation();
8234 else if (shCount >= (size * 8))
8238 /* get sign in acc.7 */
8239 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8241 addSign (result, LSB, sign);
8248 genrshOne (result, left, shCount, sign);
8252 genrshTwo (result, left, shCount, sign);
8256 genrshFour (result, left, shCount, sign);
8263 freeAsmop (left, NULL, ic, TRUE);
8264 freeAsmop (result, NULL, ic, TRUE);
8270 /*-----------------------------------------------------------------*/
8271 /* genSignedRightShift - right shift of signed number */
8272 /*-----------------------------------------------------------------*/
8274 genSignedRightShift (iCode * ic)
8276 operand *right, *left, *result;
8279 symbol *tlbl, *tlbl1;
8281 D (emitcode (";", "genSignedRightShift "););
8283 /* we do it the hard way put the shift count in b
8284 and loop thru preserving the sign */
8286 right = IC_RIGHT (ic);
8287 left = IC_LEFT (ic);
8288 result = IC_RESULT (ic);
8290 aopOp (right, ic, FALSE, FALSE);
8292 #ifdef BETTER_LITERAL_SHIFT
8293 if (AOP_TYPE (right) == AOP_LIT)
8295 if (genRightShiftLiteral (left, right, result, ic, 1))
8301 /* shift count is unknown then we have to form
8302 a loop get the loop count in B : Note: we take
8303 only the lower order byte since shifting
8304 more that 32 bits make no sense anyway, ( the
8305 largest size of an object can be only 32 bits ) */
8307 if (AOP_TYPE (right) == AOP_LIT)
8309 /* Really should be handled by genRightShiftLiteral,
8310 * but since I'm too lazy to fix that today, at least we can make
8311 * some small improvement.
8313 emitcode("mov", "b,#0x%02x",
8314 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8318 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8319 emitcode ("inc", "b");
8321 freeAsmop (right, NULL, ic, TRUE);
8322 aopOp (left, ic, FALSE, FALSE);
8323 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8325 /* now move the left to the result if they are not the
8327 if (!sameRegs (AOP (left), AOP (result)) &&
8328 AOP_SIZE (result) > 1)
8331 size = AOP_SIZE (result);
8333 _startLazyDPSEvaluation ();
8336 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8337 if (*l == '@' && IS_AOP_PREG (result))
8340 emitcode ("mov", "a,%s", l);
8341 aopPut (AOP (result), "a", offset);
8344 aopPut (AOP (result), l, offset);
8347 _endLazyDPSEvaluation ();
8350 /* mov the highest order bit to OVR */
8351 tlbl = newiTempLabel (NULL);
8352 tlbl1 = newiTempLabel (NULL);
8354 size = AOP_SIZE (result);
8356 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8357 emitcode ("rlc", "a");
8358 emitcode ("mov", "ov,c");
8359 /* if it is only one byte then */
8362 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8364 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8365 emitcode ("", "%05d$:", tlbl->key + 100);
8366 emitcode ("mov", "c,ov");
8367 emitcode ("rrc", "a");
8368 emitcode ("", "%05d$:", tlbl1->key + 100);
8369 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8370 aopPut (AOP (result), "a", 0);
8374 reAdjustPreg (AOP (result));
8375 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8376 emitcode ("", "%05d$:", tlbl->key + 100);
8377 emitcode ("mov", "c,ov");
8378 _startLazyDPSEvaluation ();
8381 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8383 emitcode ("rrc", "a");
8384 aopPut (AOP (result), "a", offset--);
8386 _endLazyDPSEvaluation ();
8387 reAdjustPreg (AOP (result));
8388 emitcode ("", "%05d$:", tlbl1->key + 100);
8389 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8392 freeAsmop (left, NULL, ic, TRUE);
8393 freeAsmop (result, NULL, ic, TRUE);
8396 /*-----------------------------------------------------------------*/
8397 /* genRightShift - generate code for right shifting */
8398 /*-----------------------------------------------------------------*/
8400 genRightShift (iCode * ic)
8402 operand *right, *left, *result;
8406 symbol *tlbl, *tlbl1;
8408 D (emitcode (";", "genRightShift "););
8410 /* if signed then we do it the hard way preserve the
8411 sign bit moving it inwards */
8412 retype = getSpec (operandType (IC_RESULT (ic)));
8414 if (!SPEC_USIGN (retype))
8416 genSignedRightShift (ic);
8420 /* signed & unsigned types are treated the same : i.e. the
8421 signed is NOT propagated inwards : quoting from the
8422 ANSI - standard : "for E1 >> E2, is equivalent to division
8423 by 2**E2 if unsigned or if it has a non-negative value,
8424 otherwise the result is implementation defined ", MY definition
8425 is that the sign does not get propagated */
8427 right = IC_RIGHT (ic);
8428 left = IC_LEFT (ic);
8429 result = IC_RESULT (ic);
8431 aopOp (right, ic, FALSE, FALSE);
8433 #ifdef BETTER_LITERAL_SHIFT
8434 /* if the shift count is known then do it
8435 as efficiently as possible */
8436 if (AOP_TYPE (right) == AOP_LIT)
8438 if (genRightShiftLiteral (left, right, result, ic, 0))
8445 /* shift count is unknown then we have to form
8446 a loop get the loop count in B : Note: we take
8447 only the lower order byte since shifting
8448 more that 32 bits make no sense anyway, ( the
8449 largest size of an object can be only 32 bits ) */
8451 if (AOP_TYPE (right) == AOP_LIT)
8453 /* Really should be handled by genRightShiftLiteral,
8454 * but since I'm too lazy to fix that today, at least we can make
8455 * some small improvement.
8457 emitcode("mov", "b,#0x%02x",
8458 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8462 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8463 emitcode ("inc", "b");
8465 freeAsmop (right, NULL, ic, TRUE);
8466 aopOp (left, ic, FALSE, FALSE);
8467 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8469 /* now move the left to the result if they are not the
8471 if (!sameRegs (AOP (left), AOP (result)) &&
8472 AOP_SIZE (result) > 1)
8475 size = AOP_SIZE (result);
8477 _startLazyDPSEvaluation ();
8480 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8481 if (*l == '@' && IS_AOP_PREG (result))
8484 emitcode ("mov", "a,%s", l);
8485 aopPut (AOP (result), "a", offset);
8488 aopPut (AOP (result), l, offset);
8491 _endLazyDPSEvaluation ();
8494 tlbl = newiTempLabel (NULL);
8495 tlbl1 = newiTempLabel (NULL);
8496 size = AOP_SIZE (result);
8499 /* if it is only one byte then */
8502 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8504 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8505 emitcode ("", "%05d$:", tlbl->key + 100);
8507 emitcode ("rrc", "a");
8508 emitcode ("", "%05d$:", tlbl1->key + 100);
8509 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8510 aopPut (AOP (result), "a", 0);
8514 reAdjustPreg (AOP (result));
8515 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8516 emitcode ("", "%05d$:", tlbl->key + 100);
8518 _startLazyDPSEvaluation ();
8521 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8523 emitcode ("rrc", "a");
8524 aopPut (AOP (result), "a", offset--);
8526 _endLazyDPSEvaluation ();
8527 reAdjustPreg (AOP (result));
8529 emitcode ("", "%05d$:", tlbl1->key + 100);
8530 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8533 freeAsmop (left, NULL, ic, TRUE);
8534 freeAsmop (result, NULL, ic, TRUE);
8537 /*-----------------------------------------------------------------*/
8538 /* genUnpackBits - generates code for unpacking bits */
8539 /*-----------------------------------------------------------------*/
8541 genUnpackBits (operand * result, char *rname, int ptype)
8548 D (emitcode (";", "genUnpackBits ");
8551 etype = getSpec (operandType (result));
8553 /* read the first byte */
8559 emitcode ("mov", "a,@%s", rname);
8563 emitcode ("movx", "a,@%s", rname);
8567 emitcode ("movx", "a,@dptr");
8571 emitcode ("clr", "a");
8572 emitcode ("movc", "a,@a+dptr");
8576 emitcode ("lcall", "__gptrget");
8580 /* if we have bitdisplacement then it fits */
8581 /* into this byte completely or if length is */
8582 /* less than a byte */
8583 if ((shCnt = SPEC_BSTR (etype)) ||
8584 (SPEC_BLEN (etype) <= 8))
8587 /* shift right acc */
8590 emitcode ("anl", "a,#0x%02x",
8591 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8592 aopPut (AOP (result), "a", offset);
8596 /* bit field did not fit in a byte */
8597 rlen = SPEC_BLEN (etype) - 8;
8598 aopPut (AOP (result), "a", offset++);
8607 emitcode ("inc", "%s", rname);
8608 emitcode ("mov", "a,@%s", rname);
8612 emitcode ("inc", "%s", rname);
8613 emitcode ("movx", "a,@%s", rname);
8617 emitcode ("inc", "dptr");
8618 emitcode ("movx", "a,@dptr");
8622 emitcode ("clr", "a");
8623 emitcode ("inc", "dptr");
8624 emitcode ("movc", "a,@a+dptr");
8628 emitcode ("inc", "dptr");
8629 emitcode ("lcall", "__gptrget");
8634 /* if we are done */
8638 aopPut (AOP (result), "a", offset++);
8644 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
8645 aopPut (AOP (result), "a", offset);
8652 /*-----------------------------------------------------------------*/
8653 /* genDataPointerGet - generates code when ptr offset is known */
8654 /*-----------------------------------------------------------------*/
8656 genDataPointerGet (operand * left,
8662 int size, offset = 0;
8663 aopOp (result, ic, TRUE, FALSE);
8665 /* get the string representation of the name */
8666 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8667 size = AOP_SIZE (result);
8668 _startLazyDPSEvaluation ();
8672 sprintf (buffer, "(%s + %d)", l + 1, offset);
8674 sprintf (buffer, "%s", l + 1);
8675 aopPut (AOP (result), buffer, offset++);
8677 _endLazyDPSEvaluation ();
8679 freeAsmop (left, NULL, ic, TRUE);
8680 freeAsmop (result, NULL, ic, TRUE);
8683 /*-----------------------------------------------------------------*/
8684 /* genNearPointerGet - emitcode for near pointer fetch */
8685 /*-----------------------------------------------------------------*/
8687 genNearPointerGet (operand * left,
8695 sym_link *rtype, *retype, *letype;
8696 sym_link *ltype = operandType (left);
8699 rtype = operandType (result);
8700 retype = getSpec (rtype);
8701 letype = getSpec (ltype);
8703 aopOp (left, ic, FALSE, FALSE);
8705 /* if left is rematerialisable and
8706 result is not bit variable type and
8707 the left is pointer to data space i.e
8708 lower 128 bytes of space */
8709 if (AOP_TYPE (left) == AOP_IMMD &&
8710 !IS_BITVAR (retype) &&
8711 !IS_BITVAR (letype) &&
8712 DCL_TYPE (ltype) == POINTER)
8714 genDataPointerGet (left, result, ic);
8718 /* if the value is already in a pointer register
8719 then don't need anything more */
8720 if (!AOP_INPREG (AOP (left)))
8722 /* otherwise get a free pointer register */
8724 preg = getFreePtr (ic, &aop, FALSE);
8725 emitcode ("mov", "%s,%s",
8727 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8731 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8733 freeAsmop (left, NULL, ic, TRUE);
8734 aopOp (result, ic, FALSE, FALSE);
8736 /* if bitfield then unpack the bits */
8737 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8738 genUnpackBits (result, rname, POINTER);
8741 /* we have can just get the values */
8742 int size = AOP_SIZE (result);
8747 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8750 emitcode ("mov", "a,@%s", rname);
8751 aopPut (AOP (result), "a", offset);
8755 sprintf (buffer, "@%s", rname);
8756 aopPut (AOP (result), buffer, offset);
8760 emitcode ("inc", "%s", rname);
8764 /* now some housekeeping stuff */
8767 /* we had to allocate for this iCode */
8768 if (pi) { /* post increment present */
8769 aopPut(AOP ( left ),rname,0);
8771 freeAsmop (NULL, aop, ic, TRUE);
8775 /* we did not allocate which means left
8776 already in a pointer register, then
8777 if size > 0 && this could be used again
8778 we have to point it back to where it
8780 if (AOP_SIZE (result) > 1 &&
8781 !OP_SYMBOL (left)->remat &&
8782 (OP_SYMBOL (left)->liveTo > ic->seq ||
8786 int size = AOP_SIZE (result) - 1;
8788 emitcode ("dec", "%s", rname);
8793 freeAsmop (result, NULL, ic, TRUE);
8794 if (pi) pi->generated = 1;
8797 /*-----------------------------------------------------------------*/
8798 /* genPagedPointerGet - emitcode for paged pointer fetch */
8799 /*-----------------------------------------------------------------*/
8801 genPagedPointerGet (operand * left,
8809 sym_link *rtype, *retype, *letype;
8811 rtype = operandType (result);
8812 retype = getSpec (rtype);
8813 letype = getSpec (operandType (left));
8814 aopOp (left, ic, FALSE, FALSE);
8816 /* if the value is already in a pointer register
8817 then don't need anything more */
8818 if (!AOP_INPREG (AOP (left)))
8820 /* otherwise get a free pointer register */
8822 preg = getFreePtr (ic, &aop, FALSE);
8823 emitcode ("mov", "%s,%s",
8825 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8829 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8831 freeAsmop (left, NULL, ic, TRUE);
8832 aopOp (result, ic, FALSE, FALSE);
8834 /* if bitfield then unpack the bits */
8835 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8836 genUnpackBits (result, rname, PPOINTER);
8839 /* we have can just get the values */
8840 int size = AOP_SIZE (result);
8846 emitcode ("movx", "a,@%s", rname);
8847 aopPut (AOP (result), "a", offset);
8852 emitcode ("inc", "%s", rname);
8856 /* now some housekeeping stuff */
8859 /* we had to allocate for this iCode */
8860 if (pi) aopPut ( AOP (left), rname, 0);
8861 freeAsmop (NULL, aop, ic, TRUE);
8865 /* we did not allocate which means left
8866 already in a pointer register, then
8867 if size > 0 && this could be used again
8868 we have to point it back to where it
8870 if (AOP_SIZE (result) > 1 &&
8871 !OP_SYMBOL (left)->remat &&
8872 (OP_SYMBOL (left)->liveTo > ic->seq ||
8876 int size = AOP_SIZE (result) - 1;
8878 emitcode ("dec", "%s", rname);
8883 freeAsmop (result, NULL, ic, TRUE);
8884 if (pi) pi->generated = 1;
8887 /*-----------------------------------------------------------------*/
8888 /* genFarPointerGet - gget value from far space */
8889 /*-----------------------------------------------------------------*/
8891 genFarPointerGet (operand * left,
8892 operand * result, iCode * ic, iCode *pi)
8894 int size, offset, dopi=1;
8895 sym_link *retype = getSpec (operandType (result));
8896 sym_link *letype = getSpec (operandType (left));
8897 D (emitcode (";", "genFarPointerGet");
8900 aopOp (left, ic, FALSE, FALSE);
8902 /* if the operand is already in dptr
8903 then we do nothing else we move the value to dptr */
8904 if (AOP_TYPE (left) != AOP_STR)
8906 /* if this is remateriazable */
8907 if (AOP_TYPE (left) == AOP_IMMD)
8909 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8913 /* we need to get it byte by byte */
8914 _startLazyDPSEvaluation ();
8915 if (AOP_TYPE (left) != AOP_DPTR)
8917 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8918 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8919 if (options.model == MODEL_FLAT24)
8920 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8924 /* We need to generate a load to DPTR indirect through DPTR. */
8925 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8927 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8928 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8929 if (options.model == MODEL_FLAT24)
8930 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8931 emitcode ("pop", "dph");
8932 emitcode ("pop", "dpl");
8935 _endLazyDPSEvaluation ();
8938 /* so dptr know contains the address */
8939 aopOp (result, ic, FALSE, TRUE);
8941 /* if bit then unpack */
8942 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8943 genUnpackBits (result, "dptr", FPOINTER);
8946 size = AOP_SIZE (result);
8949 _startLazyDPSEvaluation ();
8956 emitcode ("movx", "a,@dptr");
8957 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
8958 emitcode ("inc", "dptr");
8960 aopPut (AOP (result), "a", offset++);
8962 _endLazyDPSEvaluation ();
8964 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
8965 aopPut ( AOP (left), "dpl", 0);
8966 aopPut ( AOP (left), "dph", 1);
8967 if (options.model == MODEL_FLAT24)
8968 aopPut ( AOP (left), "dpx", 2);
8970 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
8971 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
8973 size = AOP_SIZE (result) - 1;
8974 while (size--) emitcode ("lcall","__decdptr");
8977 freeAsmop (left, NULL, ic, TRUE);
8978 freeAsmop (result, NULL, ic, TRUE);
8981 /*-----------------------------------------------------------------*/
8982 /* emitcodePointerGet - gget value from code space */
8983 /*-----------------------------------------------------------------*/
8985 emitcodePointerGet (operand * left,
8986 operand * result, iCode * ic, iCode *pi)
8988 int size, offset, dopi=1;
8989 sym_link *retype = getSpec (operandType (result));
8991 aopOp (left, ic, FALSE, FALSE);
8993 /* if the operand is already in dptr
8994 then we do nothing else we move the value to dptr */
8995 if (AOP_TYPE (left) != AOP_STR)
8997 /* if this is remateriazable */
8998 if (AOP_TYPE (left) == AOP_IMMD)
9000 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9003 { /* we need to get it byte by byte */
9004 _startLazyDPSEvaluation ();
9005 if (AOP_TYPE (left) != AOP_DPTR)
9007 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9008 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9009 if (options.model == MODEL_FLAT24)
9010 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9014 /* We need to generate a load to DPTR indirect through DPTR. */
9015 D (emitcode (";", "gencodePointerGet -- indirection special case.");
9017 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9018 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9019 if (options.model == MODEL_FLAT24)
9020 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9021 emitcode ("pop", "dph");
9022 emitcode ("pop", "dpl");
9025 _endLazyDPSEvaluation ();
9028 /* so dptr know contains the address */
9029 aopOp (result, ic, FALSE, TRUE);
9031 /* if bit then unpack */
9032 if (IS_BITVAR (retype))
9033 genUnpackBits (result, "dptr", CPOINTER);
9036 size = AOP_SIZE (result);
9039 _startLazyDPSEvaluation ();
9045 emitcode ("clr", "a");
9046 emitcode ("movc", "a,@a+dptr");
9047 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9048 emitcode ("inc", "dptr");
9049 aopPut (AOP (result), "a", offset++);
9051 _endLazyDPSEvaluation ();
9053 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9054 aopPut ( AOP (left), "dpl", 0);
9055 aopPut ( AOP (left), "dph", 1);
9056 if (options.model == MODEL_FLAT24)
9057 aopPut ( AOP (left), "dpx", 2);
9059 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9060 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9062 size = AOP_SIZE (result) - 1;
9063 while (size--) emitcode ("lcall","__decdptr");
9066 freeAsmop (left, NULL, ic, TRUE);
9067 freeAsmop (result, NULL, ic, TRUE);
9070 /*-----------------------------------------------------------------*/
9071 /* genGenPointerGet - gget value from generic pointer space */
9072 /*-----------------------------------------------------------------*/
9074 genGenPointerGet (operand * left,
9075 operand * result, iCode * ic, iCode * pi)
9078 sym_link *retype = getSpec (operandType (result));
9079 sym_link *letype = getSpec (operandType (left));
9081 D (emitcode (";", "genGenPointerGet "); );
9083 aopOp (left, ic, FALSE, (OP_SYMBOL(left)->ruonly ? FALSE : TRUE));
9085 /* if the operand is already in dptr
9086 then we do nothing else we move the value to dptr */
9087 if (AOP_TYPE (left) != AOP_STR)
9089 /* if this is remateriazable */
9090 if (AOP_TYPE (left) == AOP_IMMD)
9092 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9093 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9094 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
9096 emitcode ("mov", "b,#%d", pointerCode (retype));
9099 { /* we need to get it byte by byte */
9100 _startLazyDPSEvaluation ();
9101 if (AOP(left)->type==AOP_DPTR2) {
9103 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
9106 emitcode ("mov", "dpl,%s", l);
9107 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
9110 emitcode ("mov", "dph,%s", l);
9111 if (options.model == MODEL_FLAT24) {
9112 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
9115 emitcode ("mov", "dpx,%s", l);
9116 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9118 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9121 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
9122 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
9123 if (options.model == MODEL_FLAT24) {
9124 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9125 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9127 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9130 _endLazyDPSEvaluation ();
9133 /* so dptr know contains the address */
9134 aopOp (result, ic, FALSE, TRUE);
9136 /* if bit then unpack */
9137 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9138 genUnpackBits (result, "dptr", GPOINTER);
9141 size = AOP_SIZE (result);
9146 emitcode ("lcall", "__gptrget");
9147 aopPut (AOP (result), "a", offset++);
9148 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9149 emitcode ("inc", "dptr");
9153 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9154 aopPut ( AOP (left), "dpl", 0);
9155 aopPut ( AOP (left), "dph", 1);
9156 if (options.model == MODEL_FLAT24) {
9157 aopPut ( AOP (left), "dpx", 2);
9158 aopPut ( AOP (left), "b", 3);
9159 } else aopPut ( AOP (left), "b", 2);
9161 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9162 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9164 size = AOP_SIZE (result) - 1;
9165 while (size--) emitcode ("lcall","__decdptr");
9168 freeAsmop (left, NULL, ic, TRUE);
9169 freeAsmop (result, NULL, ic, TRUE);
9172 /*-----------------------------------------------------------------*/
9173 /* genPointerGet - generate code for pointer get */
9174 /*-----------------------------------------------------------------*/
9176 genPointerGet (iCode * ic, iCode *pi)
9178 operand *left, *result;
9179 sym_link *type, *etype;
9182 D (emitcode (";", "genPointerGet ");
9185 left = IC_LEFT (ic);
9186 result = IC_RESULT (ic);
9188 /* depending on the type of pointer we need to
9189 move it to the correct pointer register */
9190 type = operandType (left);
9191 etype = getSpec (type);
9192 /* if left is of type of pointer then it is simple */
9193 if (IS_PTR (type) && !IS_FUNC (type->next))
9194 p_type = DCL_TYPE (type);
9197 /* we have to go by the storage class */
9198 p_type = PTR_TYPE (SPEC_OCLS (etype));
9200 /* special case when cast remat */
9201 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9202 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9203 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9204 type = type = operandType (left);
9205 p_type = DCL_TYPE (type);
9207 /* now that we have the pointer type we assign
9208 the pointer values */
9214 genNearPointerGet (left, result, ic, pi);
9218 genPagedPointerGet (left, result, ic, pi);
9222 genFarPointerGet (left, result, ic, pi);
9226 emitcodePointerGet (left, result, ic, pi);
9230 genGenPointerGet (left, result, ic, pi);
9236 /*-----------------------------------------------------------------*/
9237 /* genPackBits - generates code for packed bit storage */
9238 /*-----------------------------------------------------------------*/
9240 genPackBits (sym_link * etype,
9242 char *rname, int p_type)
9250 blen = SPEC_BLEN (etype);
9251 bstr = SPEC_BSTR (etype);
9253 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9256 /* if the bit lenth is less than or */
9257 /* it exactly fits a byte then */
9258 if (SPEC_BLEN (etype) <= 8)
9260 shCount = SPEC_BSTR (etype);
9262 /* shift left acc */
9265 if (SPEC_BLEN (etype) < 8)
9266 { /* if smaller than a byte */
9272 emitcode ("mov", "b,a");
9273 emitcode ("mov", "a,@%s", rname);
9277 emitcode ("mov", "b,a");
9278 emitcode ("movx", "a,@dptr");
9282 emitcode ("push", "b");
9283 emitcode ("push", "acc");
9284 emitcode ("lcall", "__gptrget");
9285 emitcode ("pop", "b");
9289 emitcode ("anl", "a,#0x%02x", (unsigned char)
9290 ((unsigned char) (0xFF << (blen + bstr)) |
9291 (unsigned char) (0xFF >> (8 - bstr))));
9292 emitcode ("orl", "a,b");
9293 if (p_type == GPOINTER)
9294 emitcode ("pop", "b");
9301 emitcode ("mov", "@%s,a", rname);
9305 emitcode ("movx", "@dptr,a");
9309 emitcode ("lcall", "__gptrput");
9314 if (SPEC_BLEN (etype) <= 8)
9317 emitcode ("inc", "%s", rname);
9318 rLen = SPEC_BLEN (etype);
9320 /* now generate for lengths greater than one byte */
9324 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9336 emitcode ("mov", "@%s,a", rname);
9339 emitcode ("mov", "@%s,%s", rname, l);
9344 emitcode ("movx", "@dptr,a");
9349 emitcode ("lcall", "__gptrput");
9352 emitcode ("inc", "%s", rname);
9357 /* last last was not complete */
9360 /* save the byte & read byte */
9364 emitcode ("mov", "b,a");
9365 emitcode ("mov", "a,@%s", rname);
9369 emitcode ("mov", "b,a");
9370 emitcode ("movx", "a,@dptr");
9374 emitcode ("push", "b");
9375 emitcode ("push", "acc");
9376 emitcode ("lcall", "__gptrget");
9377 emitcode ("pop", "b");
9381 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
9382 emitcode ("orl", "a,b");
9385 if (p_type == GPOINTER)
9386 emitcode ("pop", "b");
9392 emitcode ("mov", "@%s,a", rname);
9396 emitcode ("movx", "@dptr,a");
9400 emitcode ("lcall", "__gptrput");
9404 /*-----------------------------------------------------------------*/
9405 /* genDataPointerSet - remat pointer to data space */
9406 /*-----------------------------------------------------------------*/
9408 genDataPointerSet (operand * right,
9412 int size, offset = 0;
9413 char *l, buffer[256];
9415 aopOp (right, ic, FALSE, FALSE);
9417 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9418 size = AOP_SIZE (right);
9422 sprintf (buffer, "(%s + %d)", l + 1, offset);
9424 sprintf (buffer, "%s", l + 1);
9425 emitcode ("mov", "%s,%s", buffer,
9426 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9429 freeAsmop (right, NULL, ic, TRUE);
9430 freeAsmop (result, NULL, ic, TRUE);
9433 /*-----------------------------------------------------------------*/
9434 /* genNearPointerSet - emitcode for near pointer put */
9435 /*-----------------------------------------------------------------*/
9437 genNearPointerSet (operand * right,
9445 sym_link *retype, *letype;
9446 sym_link *ptype = operandType (result);
9448 retype = getSpec (operandType (right));
9449 letype = getSpec (ptype);
9451 aopOp (result, ic, FALSE, FALSE);
9453 /* if the result is rematerializable &
9454 in data space & not a bit variable */
9455 if (AOP_TYPE (result) == AOP_IMMD &&
9456 DCL_TYPE (ptype) == POINTER &&
9457 !IS_BITVAR (retype) &&
9458 !IS_BITVAR (letype))
9460 genDataPointerSet (right, result, ic);
9464 /* if the value is already in a pointer register
9465 then don't need anything more */
9466 if (!AOP_INPREG (AOP (result)))
9468 /* otherwise get a free pointer register */
9470 preg = getFreePtr (ic, &aop, FALSE);
9471 emitcode ("mov", "%s,%s",
9473 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9477 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9479 aopOp (right, ic, FALSE, FALSE);
9481 /* if bitfield then unpack the bits */
9482 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9483 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9486 /* we have can just get the values */
9487 int size = AOP_SIZE (right);
9492 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9496 emitcode ("mov", "@%s,a", rname);
9499 emitcode ("mov", "@%s,%s", rname, l);
9501 emitcode ("inc", "%s", rname);
9506 /* now some housekeeping stuff */
9509 /* we had to allocate for this iCode */
9510 if (pi) aopPut (AOP (result),rname,0);
9511 freeAsmop (NULL, aop, ic, TRUE);
9515 /* we did not allocate which means left
9516 already in a pointer register, then
9517 if size > 0 && this could be used again
9518 we have to point it back to where it
9520 if (AOP_SIZE (right) > 1 &&
9521 !OP_SYMBOL (result)->remat &&
9522 (OP_SYMBOL (result)->liveTo > ic->seq ||
9526 int size = AOP_SIZE (right) - 1;
9528 emitcode ("dec", "%s", rname);
9533 if (pi) pi->generated = 1;
9534 freeAsmop (result, NULL, ic, TRUE);
9535 freeAsmop (right, NULL, ic, TRUE);
9540 /*-----------------------------------------------------------------*/
9541 /* genPagedPointerSet - emitcode for Paged pointer put */
9542 /*-----------------------------------------------------------------*/
9544 genPagedPointerSet (operand * right,
9552 sym_link *retype, *letype;
9554 retype = getSpec (operandType (right));
9555 letype = getSpec (operandType (result));
9557 aopOp (result, ic, FALSE, FALSE);
9559 /* if the value is already in a pointer register
9560 then don't need anything more */
9561 if (!AOP_INPREG (AOP (result)))
9563 /* otherwise get a free pointer register */
9565 preg = getFreePtr (ic, &aop, FALSE);
9566 emitcode ("mov", "%s,%s",
9568 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9572 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9574 aopOp (right, ic, FALSE, FALSE);
9576 /* if bitfield then unpack the bits */
9577 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9578 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9581 /* we have can just get the values */
9582 int size = AOP_SIZE (right);
9587 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9590 emitcode ("movx", "@%s,a", rname);
9593 emitcode ("inc", "%s", rname);
9599 /* now some housekeeping stuff */
9602 if (pi) aopPut (AOP (result),rname,0);
9603 /* we had to allocate for this iCode */
9604 freeAsmop (NULL, aop, ic, TRUE);
9608 /* we did not allocate which means left
9609 already in a pointer register, then
9610 if size > 0 && this could be used again
9611 we have to point it back to where it
9613 if (AOP_SIZE (right) > 1 &&
9614 !OP_SYMBOL (result)->remat &&
9615 (OP_SYMBOL (result)->liveTo > ic->seq ||
9619 int size = AOP_SIZE (right) - 1;
9621 emitcode ("dec", "%s", rname);
9626 if (pi) pi->generated = 1;
9627 freeAsmop (result, NULL, ic, TRUE);
9628 freeAsmop (right, NULL, ic, TRUE);
9633 /*-----------------------------------------------------------------*/
9634 /* genFarPointerSet - set value from far space */
9635 /*-----------------------------------------------------------------*/
9637 genFarPointerSet (operand * right,
9638 operand * result, iCode * ic, iCode *pi)
9640 int size, offset, dopi=1;
9641 sym_link *retype = getSpec (operandType (right));
9642 sym_link *letype = getSpec (operandType (result));
9644 aopOp (result, ic, FALSE, FALSE);
9646 /* if the operand is already in dptr
9647 then we do nothing else we move the value to dptr */
9648 if (AOP_TYPE (result) != AOP_STR)
9650 /* if this is remateriazable */
9651 if (AOP_TYPE (result) == AOP_IMMD)
9652 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9655 /* we need to get it byte by byte */
9656 _startLazyDPSEvaluation ();
9657 if (AOP_TYPE (result) != AOP_DPTR)
9659 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9660 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9661 if (options.model == MODEL_FLAT24)
9662 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9666 /* We need to generate a load to DPTR indirect through DPTR. */
9667 D (emitcode (";", "genFarPointerSet -- indirection special case.");
9669 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9670 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9671 if (options.model == MODEL_FLAT24)
9672 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9673 emitcode ("pop", "dph");
9674 emitcode ("pop", "dpl");
9677 _endLazyDPSEvaluation ();
9680 /* so dptr know contains the address */
9681 aopOp (right, ic, FALSE, TRUE);
9683 /* if bit then unpack */
9684 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9685 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9688 size = AOP_SIZE (right);
9691 _startLazyDPSEvaluation ();
9694 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9700 emitcode ("movx", "@dptr,a");
9701 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
9702 emitcode ("inc", "dptr");
9704 _endLazyDPSEvaluation ();
9707 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
9708 aopPut (AOP(result),"dpl",0);
9709 aopPut (AOP(result),"dph",1);
9710 if (options.model == MODEL_FLAT24)
9711 aopPut (AOP(result),"dpx",2);
9713 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9714 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9716 size = AOP_SIZE (right) - 1;
9717 while (size--) emitcode ("lcall","__decdptr");
9719 freeAsmop (result, NULL, ic, TRUE);
9720 freeAsmop (right, NULL, ic, TRUE);
9723 /*-----------------------------------------------------------------*/
9724 /* genGenPointerSet - set value from generic pointer space */
9725 /*-----------------------------------------------------------------*/
9727 genGenPointerSet (operand * right,
9728 operand * result, iCode * ic, iCode *pi)
9731 sym_link *retype = getSpec (operandType (right));
9732 sym_link *letype = getSpec (operandType (result));
9734 aopOp (result, ic, FALSE, OP_SYMBOL(result)->ruonly ? FALSE : TRUE);
9736 /* if the operand is already in dptr
9737 then we do nothing else we move the value to dptr */
9738 if (AOP_TYPE (result) != AOP_STR)
9740 _startLazyDPSEvaluation ();
9741 /* if this is remateriazable */
9742 if (AOP_TYPE (result) == AOP_IMMD)
9744 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9745 if (AOP(result)->aopu.aop_immd.from_cast_remat)
9746 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
9748 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9751 { /* we need to get it byte by byte */
9752 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9753 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9754 if (options.model == MODEL_FLAT24) {
9755 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9756 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9758 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9761 _endLazyDPSEvaluation ();
9763 /* so dptr know contains the address */
9764 aopOp (right, ic, FALSE, TRUE);
9766 /* if bit then unpack */
9767 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9768 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9771 size = AOP_SIZE (right);
9774 _startLazyDPSEvaluation ();
9777 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9783 emitcode ("lcall", "__gptrput");
9784 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
9785 emitcode ("inc", "dptr");
9787 _endLazyDPSEvaluation ();
9790 if (pi && AOP_TYPE (result) != AOP_IMMD) {
9791 aopPut (AOP(result),"dpl",0);
9792 aopPut (AOP(result),"dph",1);
9793 if (options.model == MODEL_FLAT24) {
9794 aopPut (AOP(result),"dpx",2);
9795 aopPut (AOP(result),"b",3);
9797 aopPut (AOP(result),"b",2);
9800 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9801 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9803 size = AOP_SIZE (right) - 1;
9804 while (size--) emitcode ("lcall","__decdptr");
9806 freeAsmop (result, NULL, ic, TRUE);
9807 freeAsmop (right, NULL, ic, TRUE);
9810 /*-----------------------------------------------------------------*/
9811 /* genPointerSet - stores the value into a pointer location */
9812 /*-----------------------------------------------------------------*/
9814 genPointerSet (iCode * ic, iCode *pi)
9816 operand *right, *result;
9817 sym_link *type, *etype;
9820 D (emitcode (";", "genPointerSet ");
9823 right = IC_RIGHT (ic);
9824 result = IC_RESULT (ic);
9826 /* depending on the type of pointer we need to
9827 move it to the correct pointer register */
9828 type = operandType (result);
9829 etype = getSpec (type);
9830 /* if left is of type of pointer then it is simple */
9831 if (IS_PTR (type) && !IS_FUNC (type->next))
9833 p_type = DCL_TYPE (type);
9837 /* we have to go by the storage class */
9838 p_type = PTR_TYPE (SPEC_OCLS (etype));
9840 /* special case when cast remat */
9841 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9842 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9843 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9844 type = type = operandType (result);
9845 p_type = DCL_TYPE (type);
9848 /* now that we have the pointer type we assign
9849 the pointer values */
9855 genNearPointerSet (right, result, ic, pi);
9859 genPagedPointerSet (right, result, ic, pi);
9863 genFarPointerSet (right, result, ic, pi);
9867 genGenPointerSet (right, result, ic, pi);
9873 /*-----------------------------------------------------------------*/
9874 /* genIfx - generate code for Ifx statement */
9875 /*-----------------------------------------------------------------*/
9877 genIfx (iCode * ic, iCode * popIc)
9879 operand *cond = IC_COND (ic);
9882 D (emitcode (";", "genIfx "););
9884 aopOp (cond, ic, FALSE, FALSE);
9886 /* get the value into acc */
9887 if (AOP_TYPE (cond) != AOP_CRY)
9891 /* the result is now in the accumulator */
9892 freeAsmop (cond, NULL, ic, TRUE);
9894 /* if there was something to be popped then do it */
9898 /* if the condition is a bit variable */
9899 if (isbit && IS_ITEMP (cond) &&
9901 genIfxJump (ic, SPIL_LOC (cond)->rname);
9902 else if (isbit && !IS_ITEMP (cond))
9903 genIfxJump (ic, OP_SYMBOL (cond)->rname);
9905 genIfxJump (ic, "a");
9910 /*-----------------------------------------------------------------*/
9911 /* genAddrOf - generates code for address of */
9912 /*-----------------------------------------------------------------*/
9914 genAddrOf (iCode * ic)
9916 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9919 D (emitcode (";", "genAddrOf ");
9922 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9924 /* if the operand is on the stack then we
9925 need to get the stack offset of this
9929 /* if 10 bit stack */
9930 if (options.stack10bit) {
9932 sprintf(buff,"#0x%02x",(options.stack_loc >> 16) & 0xff);
9933 /* if it has an offset then we need to compute it */
9934 emitcode ("subb", "a,#0x%02x",
9935 -((sym->stack < 0) ?
9936 ((short) (sym->stack - _G.nRegsSaved)) :
9937 ((short) sym->stack)) & 0xff);
9938 emitcode ("mov","b,a");
9939 emitcode ("mov","a,#0x%02x",(-((sym->stack < 0) ?
9940 ((short) (sym->stack - _G.nRegsSaved)) :
9941 ((short) sym->stack)) >> 8) & 0xff);
9943 emitcode ("mov", "a,_bpx");
9944 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
9945 ((char) (sym->stack - _G.nRegsSaved)) :
9946 ((char) sym->stack )) & 0xff);
9947 emitcode ("mov", "b,a");
9948 emitcode ("mov", "a,_bpx+1");
9949 emitcode ("addc","a,#0x%02x", (((sym->stack < 0) ?
9950 ((short) (sym->stack - _G.nRegsSaved)) :
9951 ((short) sym->stack )) >> 8) & 0xff);
9952 aopPut (AOP (IC_RESULT (ic)), "b", 0);
9953 aopPut (AOP (IC_RESULT (ic)), "a", 1);
9954 aopPut (AOP (IC_RESULT (ic)), buff, 2);
9956 /* we can just move _bp */
9957 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
9958 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
9959 aopPut (AOP (IC_RESULT (ic)), buff, 2);
9962 /* if it has an offset then we need to compute it */
9964 emitcode ("mov", "a,_bp");
9965 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9966 aopPut (AOP (IC_RESULT (ic)), "a", 0);
9968 /* we can just move _bp */
9969 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9971 /* fill the result with zero */
9972 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9975 if (options.stack10bit && size < (FPTRSIZE - 1)) {
9977 "*** warning: pointer to stack var truncated.\n");
9982 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9988 /* object not on stack then we need the name */
9989 size = AOP_SIZE (IC_RESULT (ic));
9994 char s[SDCC_NAME_MAX];
9996 sprintf (s, "#(%s >> %d)",
10000 sprintf (s, "#%s", sym->rname);
10001 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10005 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10009 /*-----------------------------------------------------------------*/
10010 /* genArrayInit - generates code for address of */
10011 /*-----------------------------------------------------------------*/
10013 genArrayInit (iCode * ic)
10015 literalList *iLoop;
10017 int elementSize = 0, eIndex;
10018 unsigned val, lastVal;
10020 operand *left=IC_LEFT(ic);
10022 D (emitcode (";", "genArrayInit "););
10024 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10026 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10028 // Load immediate value into DPTR.
10029 emitcode("mov", "dptr, %s",
10030 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
10032 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10035 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10036 "Unexpected operand to genArrayInit.\n");
10039 // a regression because of SDCCcse.c:1.52
10040 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
10041 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
10042 if (options.model == MODEL_FLAT24)
10043 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
10047 type = operandType(IC_LEFT(ic));
10049 if (type && type->next)
10051 elementSize = getSize(type->next);
10055 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10056 "can't determine element size in genArrayInit.\n");
10060 iLoop = IC_ARRAYILIST(ic);
10065 bool firstpass = TRUE;
10067 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10068 iLoop->count, (int)iLoop->literalValue, elementSize);
10074 symbol *tlbl = NULL;
10076 count = ix > 256 ? 256 : ix;
10080 tlbl = newiTempLabel (NULL);
10081 if (firstpass || (count & 0xff))
10083 emitcode("mov", "b, #0x%x", count & 0xff);
10086 emitcode ("", "%05d$:", tlbl->key + 100);
10091 for (eIndex = 0; eIndex < elementSize; eIndex++)
10093 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10094 if (val != lastVal)
10096 emitcode("mov", "a, #0x%x", val);
10100 emitcode("movx", "@dptr, a");
10101 emitcode("inc", "dptr");
10106 emitcode("djnz", "b, %05d$", tlbl->key + 100);
10112 iLoop = iLoop->next;
10115 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10118 /*-----------------------------------------------------------------*/
10119 /* genFarFarAssign - assignment when both are in far space */
10120 /*-----------------------------------------------------------------*/
10122 genFarFarAssign (operand * result, operand * right, iCode * ic)
10124 int size = AOP_SIZE (right);
10126 symbol *rSym = NULL;
10130 /* quick & easy case. */
10131 D(emitcode(";","genFarFarAssign (1 byte case)"););
10132 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
10133 freeAsmop (right, NULL, ic, FALSE);
10134 /* now assign DPTR to result */
10136 aopOp(result, ic, FALSE, FALSE);
10138 aopPut(AOP(result), "a", 0);
10139 freeAsmop(result, NULL, ic, FALSE);
10143 /* See if we've got an underlying symbol to abuse. */
10144 if (IS_SYMOP(result) && OP_SYMBOL(result))
10146 if (IS_TRUE_SYMOP(result))
10148 rSym = OP_SYMBOL(result);
10150 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10152 rSym = OP_SYMBOL(result)->usl.spillLoc;
10156 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10158 /* We can use the '390 auto-toggle feature to good effect here. */
10160 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10161 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
10162 emitcode ("mov", "dptr,#%s", rSym->rname);
10163 /* DP2 = result, DP1 = right, DP1 is current. */
10166 emitcode("movx", "a,@dptr");
10167 emitcode("movx", "@dptr,a");
10170 emitcode("inc", "dptr");
10171 emitcode("inc", "dptr");
10174 emitcode("mov", "dps, #0");
10175 freeAsmop (right, NULL, ic, FALSE);
10177 some alternative code for processors without auto-toggle
10178 no time to test now, so later well put in...kpb
10179 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10180 emitcode("mov", "dps, #0x01"); /* Select DPTR2. */
10181 emitcode ("mov", "dptr,#%s", rSym->rname);
10182 /* DP2 = result, DP1 = right, DP1 is current. */
10186 emitcode("movx", "a,@dptr");
10188 emitcode("inc", "dptr");
10189 emitcode("inc", "dps");
10190 emitcode("movx", "@dptr,a");
10192 emitcode("inc", "dptr");
10193 emitcode("inc", "dps");
10195 emitcode("mov", "dps, #0");
10196 freeAsmop (right, NULL, ic, FALSE);
10201 D (emitcode (";", "genFarFarAssign"););
10202 aopOp (result, ic, TRUE, TRUE);
10204 _startLazyDPSEvaluation ();
10208 aopPut (AOP (result),
10209 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10212 _endLazyDPSEvaluation ();
10213 freeAsmop (result, NULL, ic, FALSE);
10214 freeAsmop (right, NULL, ic, FALSE);
10218 /*-----------------------------------------------------------------*/
10219 /* genAssign - generate code for assignment */
10220 /*-----------------------------------------------------------------*/
10222 genAssign (iCode * ic)
10224 operand *result, *right;
10226 unsigned long lit = 0L;
10228 D (emitcode (";", "genAssign ");
10231 result = IC_RESULT (ic);
10232 right = IC_RIGHT (ic);
10234 /* if they are the same */
10235 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10238 aopOp (right, ic, FALSE, FALSE);
10240 emitcode (";", "genAssign: resultIsFar = %s",
10241 isOperandInFarSpace (result) ?
10244 /* special case both in far space */
10245 if ((AOP_TYPE (right) == AOP_DPTR ||
10246 AOP_TYPE (right) == AOP_DPTR2) &&
10247 /* IS_TRUE_SYMOP(result) && */
10248 isOperandInFarSpace (result))
10250 genFarFarAssign (result, right, ic);
10254 aopOp (result, ic, TRUE, FALSE);
10256 /* if they are the same registers */
10257 if (sameRegs (AOP (right), AOP (result)))
10260 /* if the result is a bit */
10261 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10263 /* if the right size is a literal then
10264 we know what the value is */
10265 if (AOP_TYPE (right) == AOP_LIT)
10267 if (((int) operandLitValue (right)))
10268 aopPut (AOP (result), one, 0);
10270 aopPut (AOP (result), zero, 0);
10274 /* the right is also a bit variable */
10275 if (AOP_TYPE (right) == AOP_CRY)
10277 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10278 aopPut (AOP (result), "c", 0);
10282 /* we need to or */
10284 aopPut (AOP (result), "a", 0);
10288 /* bit variables done */
10290 size = AOP_SIZE (result);
10292 if (AOP_TYPE (right) == AOP_LIT)
10293 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10296 (AOP_TYPE (result) != AOP_REG) &&
10297 (AOP_TYPE (right) == AOP_LIT) &&
10298 !IS_FLOAT (operandType (right)))
10300 _startLazyDPSEvaluation ();
10301 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10303 aopPut (AOP (result),
10304 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10309 /* And now fill the rest with zeros. */
10312 emitcode ("clr", "a");
10316 aopPut (AOP (result), "a", offset++);
10318 _endLazyDPSEvaluation ();
10322 _startLazyDPSEvaluation ();
10325 aopPut (AOP (result),
10326 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10330 _endLazyDPSEvaluation ();
10334 freeAsmop (right, NULL, ic, FALSE);
10335 freeAsmop (result, NULL, ic, TRUE);
10338 /*-----------------------------------------------------------------*/
10339 /* genJumpTab - generates code for jump table */
10340 /*-----------------------------------------------------------------*/
10342 genJumpTab (iCode * ic)
10347 D (emitcode (";", "genJumpTab ");
10350 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10351 /* get the condition into accumulator */
10352 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10354 /* multiply by four! */
10355 emitcode ("add", "a,acc");
10356 emitcode ("add", "a,acc");
10357 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10359 jtab = newiTempLabel (NULL);
10360 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10361 emitcode ("jmp", "@a+dptr");
10362 emitcode ("", "%05d$:", jtab->key + 100);
10363 /* now generate the jump labels */
10364 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10365 jtab = setNextItem (IC_JTLABELS (ic)))
10366 emitcode ("ljmp", "%05d$", jtab->key + 100);
10370 /*-----------------------------------------------------------------*/
10371 /* genCast - gen code for casting */
10372 /*-----------------------------------------------------------------*/
10374 genCast (iCode * ic)
10376 operand *result = IC_RESULT (ic);
10377 sym_link *ctype = operandType (IC_LEFT (ic));
10378 sym_link *rtype = operandType (IC_RIGHT (ic));
10379 operand *right = IC_RIGHT (ic);
10382 D (emitcode (";", "genCast ");
10385 /* if they are equivalent then do nothing */
10386 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10389 aopOp (right, ic, FALSE, FALSE);
10390 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10392 /* if the result is a bit */
10393 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10394 if (IS_BITVAR(OP_SYMBOL(result)->type))
10396 /* if the right size is a literal then
10397 we know what the value is */
10398 if (AOP_TYPE (right) == AOP_LIT)
10400 if (((int) operandLitValue (right)))
10401 aopPut (AOP (result), one, 0);
10403 aopPut (AOP (result), zero, 0);
10408 /* the right is also a bit variable */
10409 if (AOP_TYPE (right) == AOP_CRY)
10411 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10412 aopPut (AOP (result), "c", 0);
10416 /* we need to or */
10418 aopPut (AOP (result), "a", 0);
10422 /* if they are the same size : or less */
10423 if (AOP_SIZE (result) <= AOP_SIZE (right))
10426 /* if they are in the same place */
10427 if (sameRegs (AOP (right), AOP (result)))
10430 /* if they in different places then copy */
10431 size = AOP_SIZE (result);
10433 _startLazyDPSEvaluation ();
10436 aopPut (AOP (result),
10437 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10441 _endLazyDPSEvaluation ();
10446 /* if the result is of type pointer */
10447 if (IS_PTR (ctype))
10451 sym_link *type = operandType (right);
10453 /* pointer to generic pointer */
10454 if (IS_GENPTR (ctype))
10460 p_type = DCL_TYPE (type);
10464 #if OLD_CAST_BEHAVIOR
10465 /* KV: we are converting a non-pointer type to
10466 * a generic pointer. This (ifdef'd out) code
10467 * says that the resulting generic pointer
10468 * should have the same class as the storage
10469 * location of the non-pointer variable.
10471 * For example, converting an int (which happens
10472 * to be stored in DATA space) to a pointer results
10473 * in a DATA generic pointer; if the original int
10474 * in XDATA space, so will be the resulting pointer.
10476 * I don't like that behavior, and thus this change:
10477 * all such conversions will be forced to XDATA and
10478 * throw a warning. If you want some non-XDATA
10479 * type, or you want to suppress the warning, you
10480 * must go through an intermediate cast, like so:
10482 * char _generic *gp = (char _xdata *)(intVar);
10484 sym_link *etype = getSpec (type);
10486 /* we have to go by the storage class */
10487 if (SPEC_OCLS (etype) != generic)
10489 p_type = PTR_TYPE (SPEC_OCLS (etype));
10494 /* Converting unknown class (i.e. register variable)
10495 * to generic pointer. This is not good, but
10496 * we'll make a guess (and throw a warning).
10499 werror (W_INT_TO_GEN_PTR_CAST);
10503 /* the first two bytes are known */
10504 size = GPTRSIZE - 1;
10506 _startLazyDPSEvaluation ();
10509 aopPut (AOP (result),
10510 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10514 _endLazyDPSEvaluation ();
10516 /* the last byte depending on type */
10534 /* this should never happen */
10535 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10536 "got unknown pointer type");
10539 aopPut (AOP (result), l, GPTRSIZE - 1);
10543 /* just copy the pointers */
10544 size = AOP_SIZE (result);
10546 _startLazyDPSEvaluation ();
10549 aopPut (AOP (result),
10550 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10554 _endLazyDPSEvaluation ();
10558 /* so we now know that the size of destination is greater
10559 than the size of the source */
10560 /* we move to result for the size of source */
10561 size = AOP_SIZE (right);
10563 _startLazyDPSEvaluation ();
10566 aopPut (AOP (result),
10567 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10571 _endLazyDPSEvaluation ();
10573 /* now depending on the sign of the source && destination */
10574 size = AOP_SIZE (result) - AOP_SIZE (right);
10575 /* if unsigned or not an integral type */
10576 /* also, if the source is a bit, we don't need to sign extend, because
10577 * it can't possibly have set the sign bit.
10579 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10583 aopPut (AOP (result), zero, offset++);
10588 /* we need to extend the sign :{ */
10589 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10590 FALSE, FALSE, TRUE);
10592 emitcode ("rlc", "a");
10593 emitcode ("subb", "a,acc");
10595 aopPut (AOP (result), "a", offset++);
10598 /* we are done hurray !!!! */
10601 freeAsmop (right, NULL, ic, TRUE);
10602 freeAsmop (result, NULL, ic, TRUE);
10606 /*-----------------------------------------------------------------*/
10607 /* genDjnz - generate decrement & jump if not zero instrucion */
10608 /*-----------------------------------------------------------------*/
10610 genDjnz (iCode * ic, iCode * ifx)
10612 symbol *lbl, *lbl1;
10616 /* if the if condition has a false label
10617 then we cannot save */
10618 if (IC_FALSE (ifx))
10621 /* if the minus is not of the form
10623 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10624 !IS_OP_LITERAL (IC_RIGHT (ic)))
10627 if (operandLitValue (IC_RIGHT (ic)) != 1)
10630 /* if the size of this greater than one then no
10632 if (getSize (operandType (IC_RESULT (ic))) > 1)
10635 /* otherwise we can save BIG */
10636 D(emitcode(";", "genDjnz"););
10638 lbl = newiTempLabel (NULL);
10639 lbl1 = newiTempLabel (NULL);
10641 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10643 if (AOP_NEEDSACC(IC_RESULT(ic)))
10645 /* If the result is accessed indirectly via
10646 * the accumulator, we must explicitly write
10647 * it back after the decrement.
10649 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10651 if (strcmp(rByte, "a"))
10653 /* Something is hopelessly wrong */
10654 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10655 __FILE__, __LINE__);
10656 /* We can just give up; the generated code will be inefficient,
10657 * but what the hey.
10659 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10662 emitcode ("dec", "%s", rByte);
10663 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10664 emitcode ("jnz", "%05d$", lbl->key + 100);
10666 else if (IS_AOP_PREG (IC_RESULT (ic)))
10668 emitcode ("dec", "%s",
10669 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10670 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10671 emitcode ("jnz", "%05d$", lbl->key + 100);
10675 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10678 emitcode ("sjmp", "%05d$", lbl1->key + 100);
10679 emitcode ("", "%05d$:", lbl->key + 100);
10680 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10681 emitcode ("", "%05d$:", lbl1->key + 100);
10683 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10684 ifx->generated = 1;
10688 /*-----------------------------------------------------------------*/
10689 /* genReceive - generate code for a receive iCode */
10690 /*-----------------------------------------------------------------*/
10692 genReceive (iCode * ic)
10695 D (emitcode (";", "genReceive ");
10698 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10699 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10700 IS_TRUE_SYMOP (IC_RESULT (ic))))
10702 int size = getSize (operandType (IC_RESULT (ic)));
10703 int offset = fReturnSizeDS390 - size;
10706 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10707 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10710 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10711 size = AOP_SIZE (IC_RESULT (ic));
10715 emitcode ("pop", "acc");
10716 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10723 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10725 assignResultValue (IC_RESULT (ic));
10728 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10731 /*-----------------------------------------------------------------*/
10732 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
10733 /*-----------------------------------------------------------------*/
10734 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
10736 operand *from , *to , *count;
10739 /* we know it has to be 3 parameters */
10740 assert (nparms == 3);
10746 aopOp (from, ic->next, FALSE, FALSE);
10748 /* get from into DPTR1 */
10749 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
10750 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
10751 if (options.model == MODEL_FLAT24) {
10752 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
10755 freeAsmop (from, NULL, ic, FALSE);
10756 aopOp (to, ic, FALSE, FALSE);
10757 /* get "to" into DPTR */
10758 /* if the operand is already in dptr
10759 then we do nothing else we move the value to dptr */
10760 if (AOP_TYPE (to) != AOP_STR) {
10761 /* if already in DPTR then we need to push */
10762 if (AOP_TYPE(to) == AOP_DPTR) {
10763 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
10764 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
10765 if (options.model == MODEL_FLAT24)
10766 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10767 emitcode ("pop", "dph");
10768 emitcode ("pop", "dpl");
10770 _startLazyDPSEvaluation ();
10771 /* if this is remateriazable */
10772 if (AOP_TYPE (to) == AOP_IMMD) {
10773 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
10774 } else { /* we need to get it byte by byte */
10775 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
10776 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
10777 if (options.model == MODEL_FLAT24) {
10778 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10781 _endLazyDPSEvaluation ();
10784 freeAsmop (to, NULL, ic, FALSE);
10786 aopOp (count, ic->next->next, FALSE,FALSE);
10787 lbl =newiTempLabel(NULL);
10789 /* now for the actual copy */
10790 if (AOP_TYPE(count) == AOP_LIT &&
10791 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
10792 emitcode (";","OH! JOY auto increment with djnz (very fast)");
10793 emitcode ("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
10794 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
10795 emitcode ("","%05d$:",lbl->key+100);
10797 emitcode ("clr","a");
10798 emitcode ("movc", "a,@a+dptr");
10800 emitcode ("movx", "a,@dptr");
10801 emitcode ("movx", "@dptr,a");
10802 emitcode ("inc", "dptr");
10803 emitcode ("inc", "dptr");
10804 emitcode ("djnz","b,%05d$",lbl->key+100);
10806 symbol *lbl1 = newiTempLabel(NULL);
10808 emitcode (";"," Auto increment but no djnz");
10809 emitcode ("mov","ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
10810 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
10811 emitcode ("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
10812 emitcode ("","%05d$:",lbl->key+100);
10814 emitcode ("clr","a");
10815 emitcode ("movc", "a,@a+dptr");
10817 emitcode ("movx", "a,@dptr");
10818 emitcode ("movx", "@dptr,a");
10819 emitcode ("inc", "dptr");
10820 emitcode ("inc", "dptr");
10821 emitcode ("mov","a,b");
10822 emitcode ("orl","a,ap");
10823 emitcode ("jz","%05d$",lbl1->key+100);
10824 emitcode ("mov","a,ap");
10825 emitcode ("add","a,#0xFF");
10826 emitcode ("mov","ap,a");
10827 emitcode ("mov","a,b");
10828 emitcode ("addc","a,#0xFF");
10829 emitcode ("mov","b,a");
10830 emitcode ("sjmp","%05d$",lbl->key+100);
10831 emitcode ("","%05d$:",lbl1->key+100);
10833 emitcode ("mov", "dps, #0");
10834 freeAsmop (count, NULL, ic, FALSE);
10838 /*-----------------------------------------------------------------*/
10839 /* genBuiltIn - calls the appropriate function to generating code */
10840 /* for a built in function */
10841 /*-----------------------------------------------------------------*/
10842 static void genBuiltIn (iCode *ic)
10844 operand *bi_parms[MAX_BUILTIN_ARGS];
10849 /* get all the arguments for a built in function */
10850 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
10852 /* which function is it */
10853 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
10854 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
10855 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
10856 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
10857 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
10859 werror(E_INTERNAL_ERROR,"unknown builtin function encountered\n");
10865 /*-----------------------------------------------------------------*/
10866 /* gen390Code - generate code for Dallas 390 based controllers */
10867 /*-----------------------------------------------------------------*/
10869 gen390Code (iCode * lic)
10874 lineHead = lineCurr = NULL;
10876 if (options.model == MODEL_FLAT24) {
10877 fReturnSizeDS390 = 5;
10878 fReturn = fReturn24;
10880 fReturnSizeDS390 = 4;
10881 fReturn = fReturn16;
10882 options.stack10bit=0;
10886 /* print the allocation information */
10888 printAllocInfo (currFunc, codeOutFile);
10890 /* if debug information required */
10891 if (options.debug && currFunc)
10893 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
10895 if (IS_STATIC (currFunc->etype))
10896 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
10898 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
10901 /* stack pointer name */
10902 if (options.useXstack)
10908 for (ic = lic; ic; ic = ic->next)
10911 if (cln != ic->lineno)
10916 emitcode ("", "C$%s$%d$%d$%d ==.",
10917 FileBaseName (ic->filename), ic->lineno,
10918 ic->level, ic->block);
10921 emitcode (";", "%s %d", ic->filename, ic->lineno);
10924 /* if the result is marked as
10925 spilt and rematerializable or code for
10926 this has already been generated then
10928 if (resultRemat (ic) || ic->generated)
10931 /* depending on the operation */
10951 /* IPOP happens only when trying to restore a
10952 spilt live range, if there is an ifx statement
10953 following this pop then the if statement might
10954 be using some of the registers being popped which
10955 would destory the contents of the register so
10956 we need to check for this condition and handle it */
10958 ic->next->op == IFX &&
10959 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10960 genIfx (ic->next, ic);
10978 genEndFunction (ic);
10998 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11015 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11019 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11026 /* note these two are xlated by algebraic equivalence
11027 during parsing SDCC.y */
11028 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11029 "got '>=' or '<=' shouldn't have come here");
11033 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11045 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11049 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11053 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11077 genRightShift (ic);
11080 case GET_VALUE_AT_ADDRESS:
11081 genPointerGet (ic,hasInc(IC_LEFT(ic),ic));
11085 if (POINTER_SET (ic))
11086 genPointerSet (ic,hasInc(IC_RESULT(ic),ic));
11112 if (ic->builtinSEND) genBuiltIn(ic);
11113 else addSet (&_G.sendSet, ic);
11126 /* now we are ready to call the
11127 peep hole optimizer */
11128 if (!options.nopeep)
11129 peepHole (&lineHead);
11131 /* now do the actual printing */
11132 printLine (lineHead, codeOutFile);