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 (options.stack_probe)
2635 emitcode ("lcall","__stack_probe");
2636 /* if critical function then turn interrupts off */
2637 if (IFFUNC_ISCRITICAL (ftype))
2638 emitcode ("clr", "ea");
2640 /* here we need to generate the equates for the
2641 register bank if required */
2642 if (FUNC_REGBANK (ftype) != rbank)
2646 rbank = FUNC_REGBANK (ftype);
2647 for (i = 0; i < ds390_nRegs; i++)
2649 if (regs390[i].print) {
2650 if (strcmp (regs390[i].base, "0") == 0)
2651 emitcode ("", "%s = 0x%02x",
2653 8 * rbank + regs390[i].offset);
2655 emitcode ("", "%s = %s + 0x%02x",
2658 8 * rbank + regs390[i].offset);
2663 /* if this is an interrupt service routine then
2664 save acc, b, dpl, dph */
2665 if (IFFUNC_ISISR (sym->type))
2668 if (!inExcludeList ("acc"))
2669 emitcode ("push", "acc");
2670 if (!inExcludeList ("b"))
2671 emitcode ("push", "b");
2672 if (!inExcludeList ("dpl"))
2673 emitcode ("push", "dpl");
2674 if (!inExcludeList ("dph"))
2675 emitcode ("push", "dph");
2676 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2678 emitcode ("push", "dpx");
2679 /* Make sure we're using standard DPTR */
2680 emitcode ("push", "dps");
2681 emitcode ("mov", "dps, #0x00");
2682 if (options.stack10bit)
2684 /* This ISR could conceivably use DPTR2. Better save it. */
2685 emitcode ("push", "dpl1");
2686 emitcode ("push", "dph1");
2687 emitcode ("push", "dpx1");
2688 emitcode ("push", DP2_RESULT_REG);
2691 /* if this isr has no bank i.e. is going to
2692 run with bank 0 , then we need to save more
2694 if (!FUNC_REGBANK (sym->type))
2697 /* if this function does not call any other
2698 function then we can be economical and
2699 save only those registers that are used */
2700 if (!IFFUNC_HASFCALL(sym->type))
2704 /* if any registers used */
2707 /* save the registers used */
2708 for (i = 0; i < sym->regsUsed->size; i++)
2710 if (bitVectBitValue (sym->regsUsed, i) ||
2711 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2712 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2719 /* this function has a function call cannot
2720 determines register usage so we will have to push the
2722 saveRBank (0, ic, FALSE);
2727 /* This ISR uses a non-zero bank.
2729 * We assume that the bank is available for our
2732 * However, if this ISR calls a function which uses some
2733 * other bank, we must save that bank entirely.
2735 unsigned long banksToSave = 0;
2737 if (IFFUNC_HASFCALL(sym->type))
2740 #define MAX_REGISTER_BANKS 4
2745 for (i = ic; i; i = i->next)
2747 if (i->op == ENDFUNCTION)
2749 /* we got to the end OK. */
2757 dtype = operandType (IC_LEFT(i));
2759 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2761 /* Mark this bank for saving. */
2762 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2764 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2768 banksToSave |= (1 << FUNC_REGBANK(dtype));
2771 /* And note that we don't need to do it in
2779 /* This is a mess; we have no idea what
2780 * register bank the called function might
2783 * The only thing I can think of to do is
2784 * throw a warning and hope.
2786 werror(W_FUNCPTR_IN_USING_ISR);
2790 if (banksToSave && options.useXstack)
2792 /* Since we aren't passing it an ic,
2793 * saveRBank will assume r0 is available to abuse.
2795 * So switch to our (trashable) bank now, so
2796 * the caller's R0 isn't trashed.
2798 emitcode ("push", "psw");
2799 emitcode ("mov", "psw,#0x%02x",
2800 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2804 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2806 if (banksToSave & (1 << ix))
2808 saveRBank(ix, NULL, FALSE);
2812 // jwk: this needs a closer look
2813 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2818 /* if callee-save to be used for this function
2819 then save the registers being used in this function */
2820 if (IFFUNC_CALLEESAVES(sym->type))
2824 /* if any registers used */
2827 /* save the registers used */
2828 for (i = 0; i < sym->regsUsed->size; i++)
2830 if (bitVectBitValue (sym->regsUsed, i) ||
2831 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2833 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2841 /* set the register bank to the desired value */
2842 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2845 emitcode ("push", "psw");
2846 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2849 if (IFFUNC_ISREENT (sym->type) || options.stackAuto) {
2850 if (options.stack10bit) {
2851 emitcode ("push","_bpx");
2852 emitcode ("push","_bpx+1");
2853 emitcode ("mov","_bpx,%s",spname);
2854 emitcode ("mov","_bpx+1,esp");
2855 emitcode ("anl","_bpx+1,#3");
2857 if (options.useXstack) {
2858 emitcode ("mov", "r0,%s", spname);
2859 emitcode ("mov", "a,_bp");
2860 emitcode ("movx", "@r0,a");
2861 emitcode ("inc", "%s", spname);
2863 /* set up the stack */
2864 emitcode ("push", "_bp"); /* save the callers stack */
2866 emitcode ("mov", "_bp,%s", spname);
2870 /* adjust the stack for the function */
2873 if (options.stack10bit) {
2874 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
2875 assert (sym->recvSize <= 4);
2876 emitcode ("mov","a,sp");
2877 emitcode ("add","a,#0x%02x", ((short) sym->stack & 0xff));
2878 emitcode ("mov","sp,a");
2879 emitcode ("mov","a,esp");
2880 emitcode ("addc","a,#0x%02x", (((short) sym->stack) >> 8) & 0xff);
2881 emitcode ("mov","esp,a");
2884 werror (W_STACK_OVERFLOW, sym->name);
2886 if (i > 3 && sym->recvSize < 4) {
2888 emitcode ("mov", "a,sp");
2889 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2890 emitcode ("mov", "sp,a");
2894 emitcode ("inc", "sp");
2901 emitcode ("mov", "a,_spx");
2902 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2903 emitcode ("mov", "_spx,a");
2908 /*-----------------------------------------------------------------*/
2909 /* genEndFunction - generates epilogue for functions */
2910 /*-----------------------------------------------------------------*/
2912 genEndFunction (iCode * ic)
2914 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2916 D (emitcode (";", "genEndFunction "););
2918 if (IFFUNC_ISNAKED(sym->type))
2920 emitcode(";", "naked function: no epilogue.");
2924 if (IFFUNC_ISREENT (sym->type) || options.stackAuto) {
2925 if (options.stack10bit) {
2926 emitcode ("mov", "sp,_bpx", spname);
2927 emitcode ("mov", "esp,_bpx+1", spname);
2929 emitcode ("mov", "%s,_bp", spname);
2933 /* if use external stack but some variables were
2934 added to the local stack then decrement the
2936 if (options.useXstack && sym->stack) {
2937 emitcode ("mov", "a,sp");
2938 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2939 emitcode ("mov", "sp,a");
2943 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto)) {
2944 if (options.useXstack) {
2945 emitcode ("mov", "r0,%s", spname);
2946 emitcode ("movx", "a,@r0");
2947 emitcode ("mov", "_bp,a");
2948 emitcode ("dec", "%s", spname);
2950 if (options.stack10bit) {
2951 emitcode ("pop", "_bpx+1");
2952 emitcode ("pop", "_bpx");
2954 emitcode ("pop", "_bp");
2959 /* restore the register bank */
2960 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2962 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
2963 || !options.useXstack)
2965 /* Special case of ISR using non-zero bank with useXstack
2968 emitcode ("pop", "psw");
2972 if (IFFUNC_ISISR (sym->type))
2975 /* now we need to restore the registers */
2976 /* if this isr has no bank i.e. is going to
2977 run with bank 0 , then we need to save more
2979 if (!FUNC_REGBANK (sym->type))
2981 /* if this function does not call any other
2982 function then we can be economical and
2983 save only those registers that are used */
2984 if (!IFFUNC_HASFCALL(sym->type))
2988 /* if any registers used */
2991 /* save the registers used */
2992 for (i = sym->regsUsed->size; i >= 0; i--)
2994 if (bitVectBitValue (sym->regsUsed, i) ||
2995 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2996 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3003 /* this function has a function call cannot
3004 determines register usage so we will have to pop the
3006 unsaveRBank (0, ic, FALSE);
3011 /* This ISR uses a non-zero bank.
3013 * Restore any register banks saved by genFunction
3016 // jwk: this needs a closer look
3017 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3020 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3022 if (savedBanks & (1 << ix))
3024 unsaveRBank(ix, NULL, FALSE);
3028 if (options.useXstack)
3030 /* Restore bank AFTER calling unsaveRBank,
3031 * since it can trash r0.
3033 emitcode ("pop", "psw");
3037 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3039 if (options.stack10bit)
3041 emitcode ("pop", DP2_RESULT_REG);
3042 emitcode ("pop", "dpx1");
3043 emitcode ("pop", "dph1");
3044 emitcode ("pop", "dpl1");
3046 emitcode ("pop", "dps");
3047 emitcode ("pop", "dpx");
3049 if (!inExcludeList ("dph"))
3050 emitcode ("pop", "dph");
3051 if (!inExcludeList ("dpl"))
3052 emitcode ("pop", "dpl");
3053 if (!inExcludeList ("b"))
3054 emitcode ("pop", "b");
3055 if (!inExcludeList ("acc"))
3056 emitcode ("pop", "acc");
3058 if (IFFUNC_ISCRITICAL (sym->type))
3059 emitcode ("setb", "ea");
3061 /* if debug then send end of function */
3062 if (options.debug && currFunc) {
3064 emitcode ("", "C$%s$%d$%d$%d ==.",
3065 FileBaseName (ic->filename), currFunc->lastLine,
3066 ic->level, ic->block);
3067 if (IS_STATIC (currFunc->etype))
3068 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3070 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3074 emitcode ("reti", "");
3078 if (IFFUNC_ISCRITICAL (sym->type))
3079 emitcode ("setb", "ea");
3081 if (IFFUNC_CALLEESAVES(sym->type))
3085 /* if any registers used */
3088 /* save the registers used */
3089 for (i = sym->regsUsed->size; i >= 0; i--)
3091 if (bitVectBitValue (sym->regsUsed, i) ||
3092 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3093 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3099 /* if debug then send end of function */
3100 if (options.debug && currFunc)
3103 emitcode ("", "C$%s$%d$%d$%d ==.",
3104 FileBaseName (ic->filename), currFunc->lastLine,
3105 ic->level, ic->block);
3106 if (IS_STATIC (currFunc->etype))
3107 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3109 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3113 emitcode ("ret", "");
3118 /*-----------------------------------------------------------------*/
3119 /* genRet - generate code for return statement */
3120 /*-----------------------------------------------------------------*/
3124 int size, offset = 0, pushed = 0;
3126 D (emitcode (";", "genRet ");
3129 /* if we have no return value then
3130 just generate the "ret" */
3134 /* we have something to return then
3135 move the return value into place */
3136 aopOp (IC_LEFT (ic), ic, FALSE,
3137 (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3138 size = AOP_SIZE (IC_LEFT (ic));
3140 _startLazyDPSEvaluation ();
3144 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3146 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3147 FALSE, TRUE, FALSE);
3148 emitcode ("push", "%s", l);
3153 /* Since A is the last element of fReturn,
3154 * is is OK to clobber it in the aopGet.
3156 l = aopGet (AOP (IC_LEFT (ic)), offset,
3157 FALSE, FALSE, TRUE);
3158 if (strcmp (fReturn[offset], l))
3159 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3162 _endLazyDPSEvaluation ();
3169 if (strcmp (fReturn[pushed], "a"))
3170 emitcode ("pop", fReturn[pushed]);
3172 emitcode ("pop", "acc");
3175 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3178 /* generate a jump to the return label
3179 if the next is not the return statement */
3180 if (!(ic->next && ic->next->op == LABEL &&
3181 IC_LABEL (ic->next) == returnLabel))
3183 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3187 /*-----------------------------------------------------------------*/
3188 /* genLabel - generates a label */
3189 /*-----------------------------------------------------------------*/
3191 genLabel (iCode * ic)
3193 /* special case never generate */
3194 if (IC_LABEL (ic) == entryLabel)
3197 D (emitcode (";", "genLabel ");
3200 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3203 /*-----------------------------------------------------------------*/
3204 /* genGoto - generates a ljmp */
3205 /*-----------------------------------------------------------------*/
3207 genGoto (iCode * ic)
3209 D (emitcode (";", "genGoto ");
3211 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3214 /*-----------------------------------------------------------------*/
3215 /* findLabelBackwards: walks back through the iCode chain looking */
3216 /* for the given label. Returns number of iCode instructions */
3217 /* between that label and given ic. */
3218 /* Returns zero if label not found. */
3219 /*-----------------------------------------------------------------*/
3221 findLabelBackwards (iCode * ic, int key)
3230 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3232 /* printf("findLabelBackwards = %d\n", count); */
3240 /*-----------------------------------------------------------------*/
3241 /* genPlusIncr :- does addition with increment if possible */
3242 /*-----------------------------------------------------------------*/
3244 genPlusIncr (iCode * ic)
3246 unsigned int icount;
3247 unsigned int size = getDataSize (IC_RESULT (ic));
3249 /* will try to generate an increment */
3250 /* if the right side is not a literal
3252 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3255 /* if the literal value of the right hand side
3256 is greater than 4 then it is not worth it */
3257 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3260 /* if increment 16 bits in register */
3262 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3263 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3264 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3272 /* If the next instruction is a goto and the goto target
3273 * is <= 5 instructions previous to this, we can generate
3274 * jumps straight to that target.
3276 if (ic->next && ic->next->op == GOTO
3277 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3280 emitcode (";", "tail increment optimized (range %d)", labelRange);
3281 tlbl = IC_LABEL (ic->next);
3286 tlbl = newiTempLabel (NULL);
3289 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3290 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3291 IS_AOP_PREG (IC_RESULT (ic)))
3292 emitcode ("cjne", "%s,#0x00,%05d$"
3293 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3297 emitcode ("clr", "a");
3298 emitcode ("cjne", "a,%s,%05d$"
3299 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3303 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3306 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3307 IS_AOP_PREG (IC_RESULT (ic)))
3308 emitcode ("cjne", "%s,#0x00,%05d$"
3309 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3312 emitcode ("cjne", "a,%s,%05d$"
3313 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3316 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3320 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3321 IS_AOP_PREG (IC_RESULT (ic)))
3322 emitcode ("cjne", "%s,#0x00,%05d$"
3323 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3327 emitcode ("cjne", "a,%s,%05d$"
3328 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3331 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3336 emitcode ("", "%05d$:", tlbl->key + 100);
3341 /* if the sizes are greater than 1 then we cannot */
3342 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3343 AOP_SIZE (IC_LEFT (ic)) > 1)
3346 /* we can if the aops of the left & result match or
3347 if they are in registers and the registers are the
3350 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3351 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3352 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3357 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3358 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3359 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3364 _startLazyDPSEvaluation ();
3367 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3369 _endLazyDPSEvaluation ();
3378 /*-----------------------------------------------------------------*/
3379 /* outBitAcc - output a bit in acc */
3380 /*-----------------------------------------------------------------*/
3382 outBitAcc (operand * result)
3384 symbol *tlbl = newiTempLabel (NULL);
3385 /* if the result is a bit */
3386 if (AOP_TYPE (result) == AOP_CRY)
3388 aopPut (AOP (result), "a", 0);
3392 emitcode ("jz", "%05d$", tlbl->key + 100);
3393 emitcode ("mov", "a,%s", one);
3394 emitcode ("", "%05d$:", tlbl->key + 100);
3399 /*-----------------------------------------------------------------*/
3400 /* genPlusBits - generates code for addition of two bits */
3401 /*-----------------------------------------------------------------*/
3403 genPlusBits (iCode * ic)
3405 D (emitcode (";", "genPlusBits ");
3407 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3409 symbol *lbl = newiTempLabel (NULL);
3410 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3411 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3412 emitcode ("cpl", "c");
3413 emitcode ("", "%05d$:", (lbl->key + 100));
3414 outBitC (IC_RESULT (ic));
3418 emitcode ("clr", "a");
3419 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3420 emitcode ("rlc", "a");
3421 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3422 emitcode ("addc", "a,#0x00");
3423 outAcc (IC_RESULT (ic));
3428 adjustArithmeticResult (iCode * ic)
3430 if (opIsGptr (IC_RESULT (ic)) &&
3431 opIsGptr (IC_LEFT (ic)) &&
3432 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3434 aopPut (AOP (IC_RESULT (ic)),
3435 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3439 if (opIsGptr (IC_RESULT (ic)) &&
3440 opIsGptr (IC_RIGHT (ic)) &&
3441 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3443 aopPut (AOP (IC_RESULT (ic)),
3444 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3448 if (opIsGptr (IC_RESULT (ic)) &&
3449 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3450 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3451 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3452 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3455 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3456 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3460 #if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
3461 // Please don't bring it back without a really good reason.
3462 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3463 // (because all three operands are in far space).
3464 #define AOP_OP_3(ic) \
3465 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3466 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3467 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3468 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3469 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3470 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3472 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3474 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3478 // Macro to aopOp all three operands of an ic. If this cannot be done,
3479 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3480 // will be set TRUE. The caller must then handle the case specially, noting
3481 // that the IC_RESULT operand is not aopOp'd.
3482 #define AOP_OP_3_NOFATAL(ic, rc) \
3483 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3484 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR) || \
3485 (OP_SYMBOL(IC_RESULT(ic))->ruonly)); \
3486 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3487 (isOperandInFarSpace(IC_RESULT(ic)) || OP_SYMBOL(IC_RESULT(ic))->ruonly )) \
3489 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3494 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3495 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3497 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3498 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3500 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3502 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3506 // aopOp the left & right operands of an ic.
3507 #define AOP_OP_2(ic) \
3508 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3509 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3511 // convienience macro.
3512 #define AOP_SET_LOCALS(ic) \
3513 left = IC_LEFT(ic); \
3514 right = IC_RIGHT(ic); \
3515 result = IC_RESULT(ic);
3518 // Given an integer value of pushedSize bytes on the stack,
3519 // adjust it to be resultSize bytes, either by discarding
3520 // the most significant bytes or by zero-padding.
3522 // On exit from this macro, pushedSize will have been adjusted to
3523 // equal resultSize, and ACC may be trashed.
3524 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3525 /* If the pushed data is bigger than the result, \
3526 * simply discard unused bytes. Icky, but works. \
3528 while (pushedSize > resultSize) \
3530 D (emitcode (";", "discarding unused result byte."););\
3531 emitcode ("pop", "acc"); \
3534 if (pushedSize < resultSize) \
3536 emitcode ("clr", "a"); \
3537 /* Conversly, we haven't pushed enough here. \
3538 * just zero-pad, and all is well. \
3540 while (pushedSize < resultSize) \
3542 emitcode("push", "acc"); \
3546 assert(pushedSize == resultSize);
3548 /*-----------------------------------------------------------------*/
3549 /* genPlus - generates code for addition */
3550 /*-----------------------------------------------------------------*/
3552 genPlus (iCode * ic)
3554 int size, offset = 0;
3555 bool pushResult = FALSE;
3558 D (emitcode (";", "genPlus "););
3560 /* special cases :- */
3561 if ( IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly &&
3562 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3563 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3564 size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3566 while (size--) emitcode ("inc","dptr");
3568 emitcode ("mov","a,dpl");
3569 emitcode ("add","a,#0x%02x",size & 0xff);
3570 emitcode ("mov","dpl,a");
3571 emitcode ("mov","a,dph");
3572 emitcode ("addc","a,#0x%02x",(size >> 8) & 0xff);
3573 emitcode ("mov","dph,a");
3574 emitcode ("mov","a,dpx");
3575 emitcode ("addc","a,#0x%02x",(size >> 16) & 0xff);
3576 emitcode ("mov","dpx,a");
3578 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3581 if ( IS_SYMOP(IC_LEFT(ic)) &&
3582 OP_SYMBOL(IC_LEFT(ic))->remat &&
3583 isOperandInFarSpace(IC_RIGHT(ic))) {
3584 operand *op = IC_RIGHT(ic);
3585 IC_RIGHT(ic) = IC_LEFT(ic);
3589 AOP_OP_3_NOFATAL (ic, pushResult);
3592 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3597 /* if literal, literal on the right or
3598 if left requires ACC or right is already
3600 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3601 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3602 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3604 operand *t = IC_RIGHT (ic);
3605 IC_RIGHT (ic) = IC_LEFT (ic);
3607 emitcode (";", "Swapped plus args.");
3610 /* if both left & right are in bit
3612 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3613 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3619 /* if left in bit space & right literal */
3620 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3621 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3623 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3624 /* if result in bit space */
3625 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3627 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3628 emitcode ("cpl", "c");
3629 outBitC (IC_RESULT (ic));
3633 size = getDataSize (IC_RESULT (ic));
3634 _startLazyDPSEvaluation ();
3637 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3638 emitcode ("addc", "a,#00");
3639 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3641 _endLazyDPSEvaluation ();
3646 /* if I can do an increment instead
3647 of add then GOOD for ME */
3648 if (genPlusIncr (ic) == TRUE)
3650 emitcode (";", "did genPlusIncr");
3655 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3657 _startLazyDPSEvaluation ();
3660 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3662 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3664 emitcode ("add", "a,%s",
3665 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3667 emitcode ("addc", "a,%s",
3668 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3672 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3674 /* right is going to use ACC or we would have taken the
3677 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3679 D(emitcode(";", "+ AOP_ACC special case."););
3680 emitcode("xch", "a, %s", DP2_RESULT_REG);
3682 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3685 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3688 emitcode("add", "a, %s", DP2_RESULT_REG);
3692 emitcode ("add", "a,%s",
3693 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3698 emitcode ("addc", "a,%s",
3699 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3704 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3708 emitcode ("push", "acc");
3712 _endLazyDPSEvaluation ();
3716 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3718 size = getDataSize (IC_LEFT (ic));
3719 rSize = getDataSize (IC_RESULT (ic));
3721 ADJUST_PUSHED_RESULT(size, rSize);
3723 _startLazyDPSEvaluation ();
3726 emitcode ("pop", "acc");
3727 aopPut (AOP (IC_RESULT (ic)), "a", size);
3729 _endLazyDPSEvaluation ();
3732 adjustArithmeticResult (ic);
3735 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3736 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3737 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3740 /*-----------------------------------------------------------------*/
3741 /* genMinusDec :- does subtraction with deccrement if possible */
3742 /*-----------------------------------------------------------------*/
3744 genMinusDec (iCode * ic)
3746 unsigned int icount;
3747 unsigned int size = getDataSize (IC_RESULT (ic));
3749 /* will try to generate an increment */
3750 /* if the right side is not a literal
3752 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3755 /* if the literal value of the right hand side
3756 is greater than 4 then it is not worth it */
3757 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3760 /* if decrement 16 bits in register */
3761 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3762 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3763 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3771 /* If the next instruction is a goto and the goto target
3772 * is <= 5 instructions previous to this, we can generate
3773 * jumps straight to that target.
3775 if (ic->next && ic->next->op == GOTO
3776 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3779 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3780 tlbl = IC_LABEL (ic->next);
3785 tlbl = newiTempLabel (NULL);
3789 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3790 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3791 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3792 IS_AOP_PREG (IC_RESULT (ic)))
3793 emitcode ("cjne", "%s,#0xff,%05d$"
3794 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3798 emitcode ("mov", "a,#0xff");
3799 emitcode ("cjne", "a,%s,%05d$"
3800 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3803 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3806 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3807 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3808 IS_AOP_PREG (IC_RESULT (ic)))
3809 emitcode ("cjne", "%s,#0xff,%05d$"
3810 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3814 emitcode ("cjne", "a,%s,%05d$"
3815 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3818 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3822 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3823 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3824 IS_AOP_PREG (IC_RESULT (ic)))
3825 emitcode ("cjne", "%s,#0xff,%05d$"
3826 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3830 emitcode ("cjne", "a,%s,%05d$"
3831 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3834 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3838 emitcode ("", "%05d$:", tlbl->key + 100);
3843 /* if the sizes are greater than 1 then we cannot */
3844 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3845 AOP_SIZE (IC_LEFT (ic)) > 1)
3848 /* we can if the aops of the left & result match or
3849 if they are in registers and the registers are the
3852 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3853 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3854 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3857 _startLazyDPSEvaluation ();
3860 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3862 _endLazyDPSEvaluation ();
3870 /*-----------------------------------------------------------------*/
3871 /* addSign - complete with sign */
3872 /*-----------------------------------------------------------------*/
3874 addSign (operand * result, int offset, int sign)
3876 int size = (getDataSize (result) - offset);
3879 _startLazyDPSEvaluation();
3882 emitcode ("rlc", "a");
3883 emitcode ("subb", "a,acc");
3886 aopPut (AOP (result), "a", offset++);
3893 aopPut (AOP (result), zero, offset++);
3896 _endLazyDPSEvaluation();
3900 /*-----------------------------------------------------------------*/
3901 /* genMinusBits - generates code for subtraction of two bits */
3902 /*-----------------------------------------------------------------*/
3904 genMinusBits (iCode * ic)
3906 symbol *lbl = newiTempLabel (NULL);
3908 D (emitcode (";", "genMinusBits "););
3910 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3912 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3913 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3914 emitcode ("cpl", "c");
3915 emitcode ("", "%05d$:", (lbl->key + 100));
3916 outBitC (IC_RESULT (ic));
3920 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3921 emitcode ("subb", "a,acc");
3922 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3923 emitcode ("inc", "a");
3924 emitcode ("", "%05d$:", (lbl->key + 100));
3925 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3926 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3930 /*-----------------------------------------------------------------*/
3931 /* genMinus - generates code for subtraction */
3932 /*-----------------------------------------------------------------*/
3934 genMinus (iCode * ic)
3936 int size, offset = 0;
3938 unsigned long lit = 0L;
3939 bool pushResult = FALSE;
3941 D (emitcode (";", "genMinus "););
3943 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3944 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3945 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3946 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3952 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3954 /* special cases :- */
3955 /* if both left & right are in bit space */
3956 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3957 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3963 /* if I can do an decrement instead
3964 of subtract then GOOD for ME */
3965 if (genMinusDec (ic) == TRUE)
3970 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3972 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3978 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3983 /* if literal, add a,#-lit, else normal subb */
3984 _startLazyDPSEvaluation ();
3987 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3988 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3989 emitcode ("subb", "a,%s",
3990 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3993 /* first add without previous c */
3995 if (!size && lit==-1) {
3996 emitcode ("dec", "a");
3998 emitcode ("add", "a,#0x%02x",
3999 (unsigned int) (lit & 0x0FFL));
4002 emitcode ("addc", "a,#0x%02x",
4003 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4009 emitcode ("push", "acc");
4013 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4017 _endLazyDPSEvaluation ();
4021 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4023 size = getDataSize (IC_LEFT (ic));
4024 rSize = getDataSize (IC_RESULT (ic));
4026 ADJUST_PUSHED_RESULT(size, rSize);
4028 _startLazyDPSEvaluation ();
4031 emitcode ("pop", "acc");
4032 aopPut (AOP (IC_RESULT (ic)), "a", size);
4034 _endLazyDPSEvaluation ();
4037 adjustArithmeticResult (ic);
4040 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4041 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4042 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4046 /*-----------------------------------------------------------------*/
4047 /* genMultbits :- multiplication of bits */
4048 /*-----------------------------------------------------------------*/
4050 genMultbits (operand * left,
4055 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4056 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4057 aopOp(result, ic, TRUE, FALSE);
4062 /*-----------------------------------------------------------------*/
4063 /* genMultOneByte : 8*8=8/16 bit multiplication */
4064 /*-----------------------------------------------------------------*/
4066 genMultOneByte (operand * left,
4071 sym_link *opetype = operandType (result);
4075 /* (if two literals: the value is computed before) */
4076 /* if one literal, literal on the right */
4077 if (AOP_TYPE (left) == AOP_LIT)
4082 emitcode (";", "swapped left and right");
4085 if (SPEC_USIGN(opetype)
4086 // ignore the sign of left and right, what else can we do?
4087 || (SPEC_USIGN(operandType(left)) &&
4088 SPEC_USIGN(operandType(right)))) {
4089 // just an unsigned 8*8=8/16 multiply
4090 //emitcode (";","unsigned");
4091 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4092 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4093 emitcode ("mul", "ab");
4096 aopOp(result, ic, TRUE, FALSE);
4098 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4100 // this should never happen
4101 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4102 AOP_SIZE(result), __FILE__, lineno);
4106 aopPut (AOP (result), "a", 0);
4108 if (AOP_SIZE(result)==2)
4110 aopPut (AOP (result), "b", 1);
4115 // we have to do a signed multiply
4117 emitcode (";", "signed");
4118 emitcode ("clr", "F0"); // reset sign flag
4119 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4121 lbl=newiTempLabel(NULL);
4122 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
4123 // left side is negative, 8-bit two's complement, this fails for -128
4124 emitcode ("setb", "F0"); // set sign flag
4125 emitcode ("cpl", "a");
4126 emitcode ("inc", "a");
4128 emitcode ("", "%05d$:", lbl->key+100);
4131 if (AOP_TYPE(right)==AOP_LIT) {
4132 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4133 /* AND literal negative */
4134 if ((int) val < 0) {
4135 emitcode ("cpl", "F0"); // complement sign flag
4136 emitcode ("mov", "b,#0x%02x", -val);
4138 emitcode ("mov", "b,#0x%02x", val);
4141 lbl=newiTempLabel(NULL);
4142 emitcode ("mov", "b,a");
4143 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4144 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
4145 // right side is negative, 8-bit two's complement
4146 emitcode ("cpl", "F0"); // complement sign flag
4147 emitcode ("cpl", "a");
4148 emitcode ("inc", "a");
4149 emitcode ("", "%05d$:", lbl->key+100);
4151 emitcode ("mul", "ab");
4154 aopOp(result, ic, TRUE, FALSE);
4156 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4158 // this should never happen
4159 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4160 AOP_SIZE(result), __FILE__, lineno);
4164 lbl=newiTempLabel(NULL);
4165 emitcode ("jnb", "F0,%05d$", lbl->key+100);
4166 // only ONE op was negative, we have to do a 8/16-bit two's complement
4167 emitcode ("cpl", "a"); // lsb
4168 if (AOP_SIZE(result)==1) {
4169 emitcode ("inc", "a");
4171 emitcode ("add", "a,#1");
4172 emitcode ("xch", "a,b");
4173 emitcode ("cpl", "a"); // msb
4174 emitcode ("addc", "a,#0");
4175 emitcode ("xch", "a,b");
4178 emitcode ("", "%05d$:", lbl->key+100);
4179 aopPut (AOP (result), "a", 0);
4181 if (AOP_SIZE(result)==2) {
4182 aopPut (AOP (result), "b", 1);
4186 /*-----------------------------------------------------------------*/
4187 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4188 /*-----------------------------------------------------------------*/
4189 static void genMultTwoByte (operand *left, operand *right,
4190 operand *result, iCode *ic)
4192 sym_link *retype = getSpec(operandType(right));
4193 sym_link *letype = getSpec(operandType(left));
4194 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4197 if (AOP_TYPE (left) == AOP_LIT) {
4202 /* save EA bit in F1 */
4203 lbl = newiTempLabel(NULL);
4204 emitcode ("setb","F1");
4205 emitcode ("jbc","EA,%05d$",lbl->key+100);
4206 emitcode ("clr","F1");
4207 emitcode("","%05d$:",lbl->key+100);
4209 /* load up MB with right */
4211 emitcode("clr","F0");
4212 if (AOP_TYPE(right) == AOP_LIT) {
4213 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4215 emitcode("setb","F0");
4218 emitcode ("mov","mb,#0x%02x",val & 0xff);
4219 emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4221 lbl = newiTempLabel(NULL);
4222 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4223 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4224 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4225 emitcode ("xch", "a,b");
4226 emitcode ("cpl","a");
4227 emitcode ("add", "a,#1");
4228 emitcode ("xch", "a,b");
4229 emitcode ("cpl", "a"); // msb
4230 emitcode ("addc", "a,#0");
4231 emitcode ("setb","F0");
4232 emitcode ("","%05d$:",lbl->key+100);
4233 emitcode ("mov","mb,b");
4234 emitcode ("mov","mb,a");
4237 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4238 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4240 /* load up MA with left */
4242 lbl = newiTempLabel(NULL);
4243 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4244 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4245 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4246 emitcode ("xch", "a,b");
4247 emitcode ("cpl","a");
4248 emitcode ("add", "a,#1");
4249 emitcode ("xch", "a,b");
4250 emitcode ("cpl", "a"); // msb
4251 emitcode ("addc","a,#0");
4252 emitcode ("jbc","F0,%05d$",lbl->key+100);
4253 emitcode ("setb","F0");
4254 emitcode ("","%05d$:",lbl->key+100);
4255 emitcode ("mov","ma,b");
4256 emitcode ("mov","ma,a");
4258 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4259 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4261 /* wait for multiplication to finish */
4262 lbl = newiTempLabel(NULL);
4263 emitcode("","%05d$:", lbl->key+100);
4264 emitcode("mov","a,mcnt1");
4265 emitcode("anl","a,#0x80");
4266 emitcode("jnz","%05d$",lbl->key+100);
4268 freeAsmop (left, NULL, ic, TRUE);
4269 freeAsmop (right, NULL, ic,TRUE);
4270 aopOp(result, ic, TRUE, FALSE);
4272 /* if unsigned then simple */
4274 emitcode ("mov","a,ma");
4275 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4276 emitcode ("mov","a,ma");
4277 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4278 aopPut(AOP(result),"ma",1);
4279 aopPut(AOP(result),"ma",0);
4281 emitcode("push","ma");
4282 emitcode("push","ma");
4283 emitcode("push","ma");
4285 /* negate result if needed */
4286 lbl = newiTempLabel(NULL);
4287 emitcode("jnb","F0,%05d$",lbl->key+100);
4288 emitcode("cpl","a");
4289 emitcode("add","a,#1");
4290 emitcode("","%05d$:", lbl->key+100);
4291 if (AOP_TYPE(result) == AOP_ACC)
4293 D(emitcode(";", "ACC special case."););
4294 /* We know result is the only live aop, and
4295 * it's obviously not a DPTR2, so AP is available.
4297 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4301 aopPut(AOP(result),"a",0);
4304 emitcode("pop","acc");
4305 lbl = newiTempLabel(NULL);
4306 emitcode("jnb","F0,%05d$",lbl->key+100);
4307 emitcode("cpl","a");
4308 emitcode("addc","a,#0");
4309 emitcode("","%05d$:", lbl->key+100);
4310 aopPut(AOP(result),"a",1);
4311 emitcode("pop","acc");
4312 if (AOP_SIZE(result) >= 3) {
4313 lbl = newiTempLabel(NULL);
4314 emitcode("jnb","F0,%05d$",lbl->key+100);
4315 emitcode("cpl","a");
4316 emitcode("addc","a,#0");
4317 emitcode("","%05d$:", lbl->key+100);
4318 aopPut(AOP(result),"a",2);
4320 emitcode("pop","acc");
4321 if (AOP_SIZE(result) >= 4) {
4322 lbl = newiTempLabel(NULL);
4323 emitcode("jnb","F0,%05d$",lbl->key+100);
4324 emitcode("cpl","a");
4325 emitcode("addc","a,#0");
4326 emitcode("","%05d$:", lbl->key+100);
4327 aopPut(AOP(result),"a",3);
4329 if (AOP_TYPE(result) == AOP_ACC)
4331 /* We stashed the result away above. */
4332 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4336 freeAsmop (result, NULL, ic, TRUE);
4338 /* restore EA bit in F1 */
4339 lbl = newiTempLabel(NULL);
4340 emitcode ("jnb","F1,%05d$",lbl->key+100);
4341 emitcode ("setb","EA");
4342 emitcode("","%05d$:",lbl->key+100);
4346 /*-----------------------------------------------------------------*/
4347 /* genMult - generates code for multiplication */
4348 /*-----------------------------------------------------------------*/
4350 genMult (iCode * ic)
4352 operand *left = IC_LEFT (ic);
4353 operand *right = IC_RIGHT (ic);
4354 operand *result = IC_RESULT (ic);
4356 D (emitcode (";", "genMult "););
4358 /* assign the amsops */
4361 /* special cases first */
4363 if (AOP_TYPE (left) == AOP_CRY &&
4364 AOP_TYPE (right) == AOP_CRY)
4366 genMultbits (left, right, result, ic);
4370 /* if both are of size == 1 */
4371 if (AOP_SIZE (left) == 1 &&
4372 AOP_SIZE (right) == 1)
4374 genMultOneByte (left, right, result, ic);
4378 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4379 /* use the ds390 ARITHMETIC accel UNIT */
4380 genMultTwoByte (left, right, result, ic);
4383 /* should have been converted to function call */
4387 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4388 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4389 freeAsmop (result, NULL, ic, TRUE);
4392 /*-----------------------------------------------------------------*/
4393 /* genDivbits :- division of bits */
4394 /*-----------------------------------------------------------------*/
4396 genDivbits (operand * left,
4404 /* the result must be bit */
4405 LOAD_AB_FOR_DIV (left, right, l);
4406 emitcode ("div", "ab");
4407 emitcode ("rrc", "a");
4408 aopOp(result, ic, TRUE, FALSE);
4410 aopPut (AOP (result), "c", 0);
4413 /*-----------------------------------------------------------------*/
4414 /* genDivOneByte : 8 bit division */
4415 /*-----------------------------------------------------------------*/
4417 genDivOneByte (operand * left,
4422 sym_link *opetype = operandType (result);
4428 /* signed or unsigned */
4429 if (SPEC_USIGN (opetype))
4431 /* unsigned is easy */
4432 LOAD_AB_FOR_DIV (left, right, l);
4433 emitcode ("div", "ab");
4436 aopOp(result, ic, TRUE, FALSE);
4437 aopPut (AOP (result), "a", 0);
4440 size = AOP_SIZE (result) - 1;
4444 aopPut (AOP (result), zero, offset++);
4449 /* signed is a little bit more difficult */
4451 /* save the signs of the operands */
4452 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4454 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4455 emitcode ("push", "acc"); /* save it on the stack */
4457 /* now sign adjust for both left & right */
4458 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4460 lbl = newiTempLabel (NULL);
4461 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4462 emitcode ("cpl", "a");
4463 emitcode ("inc", "a");
4464 emitcode ("", "%05d$:", (lbl->key + 100));
4465 emitcode ("mov", "b,a");
4467 /* sign adjust left side */
4468 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4471 lbl = newiTempLabel (NULL);
4472 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4473 emitcode ("cpl", "a");
4474 emitcode ("inc", "a");
4475 emitcode ("", "%05d$:", (lbl->key + 100));
4477 /* now the division */
4478 emitcode ("nop", "; workaround for DS80C390 div bug.");
4479 emitcode ("div", "ab");
4480 /* we are interested in the lower order
4482 emitcode ("mov", "b,a");
4483 lbl = newiTempLabel (NULL);
4484 emitcode ("pop", "acc");
4485 /* if there was an over flow we don't
4486 adjust the sign of the result */
4487 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4488 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4490 emitcode ("clr", "a");
4491 emitcode ("subb", "a,b");
4492 emitcode ("mov", "b,a");
4493 emitcode ("", "%05d$:", (lbl->key + 100));
4495 /* now we are done */
4497 aopOp(result, ic, TRUE, FALSE);
4499 aopPut (AOP (result), "b", 0);
4501 size = AOP_SIZE (result) - 1;
4505 emitcode ("mov", "c,b.7");
4506 emitcode ("subb", "a,acc");
4510 aopPut (AOP (result), "a", offset++);
4516 /*-----------------------------------------------------------------*/
4517 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4518 /*-----------------------------------------------------------------*/
4519 static void genDivTwoByte (operand *left, operand *right,
4520 operand *result, iCode *ic)
4522 sym_link *retype = getSpec(operandType(right));
4523 sym_link *letype = getSpec(operandType(left));
4524 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4527 /* save EA bit in F1 */
4528 lbl = newiTempLabel(NULL);
4529 emitcode ("setb","F1");
4530 emitcode ("jbc","EA,%05d$",lbl->key+100);
4531 emitcode ("clr","F1");
4532 emitcode("","%05d$:",lbl->key+100);
4534 /* load up MA with left */
4536 emitcode("clr","F0");
4537 lbl = newiTempLabel(NULL);
4538 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4539 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4540 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4541 emitcode ("xch", "a,b");
4542 emitcode ("cpl","a");
4543 emitcode ("add", "a,#1");
4544 emitcode ("xch", "a,b");
4545 emitcode ("cpl", "a"); // msb
4546 emitcode ("addc","a,#0");
4547 emitcode ("setb","F0");
4548 emitcode ("","%05d$:",lbl->key+100);
4549 emitcode ("mov","ma,b");
4550 emitcode ("mov","ma,a");
4552 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4553 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4556 /* load up MB with right */
4558 if (AOP_TYPE(right) == AOP_LIT) {
4559 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4561 lbl = newiTempLabel(NULL);
4562 emitcode ("jbc","F0,%05d$",lbl->key+100);
4563 emitcode("setb","F0");
4564 emitcode ("","%05d$:",lbl->key+100);
4567 emitcode ("mov","mb,#0x%02x",val & 0xff);
4568 emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4570 lbl = newiTempLabel(NULL);
4571 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4572 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4573 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4574 emitcode ("xch", "a,b");
4575 emitcode ("cpl","a");
4576 emitcode ("add", "a,#1");
4577 emitcode ("xch", "a,b");
4578 emitcode ("cpl", "a"); // msb
4579 emitcode ("addc", "a,#0");
4580 emitcode ("jbc","F0,%05d$",lbl->key+100);
4581 emitcode ("setb","F0");
4582 emitcode ("","%05d$:",lbl->key+100);
4583 emitcode ("mov","mb,b");
4584 emitcode ("mov","mb,a");
4587 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4588 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4591 /* wait for multiplication to finish */
4592 lbl = newiTempLabel(NULL);
4593 emitcode("","%05d$:", lbl->key+100);
4594 emitcode("mov","a,mcnt1");
4595 emitcode("anl","a,#0x80");
4596 emitcode("jnz","%05d$",lbl->key+100);
4598 freeAsmop (left, NULL, ic, TRUE);
4599 freeAsmop (right, NULL, ic,TRUE);
4600 aopOp(result, ic, TRUE, FALSE);
4602 /* if unsigned then simple */
4604 aopPut(AOP(result),"ma",1);
4605 aopPut(AOP(result),"ma",0);
4607 emitcode("push","ma");
4609 /* negate result if needed */
4610 lbl = newiTempLabel(NULL);
4611 emitcode("jnb","F0,%05d$",lbl->key+100);
4612 emitcode("cpl","a");
4613 emitcode("add","a,#1");
4614 emitcode("","%05d$:", lbl->key+100);
4615 aopPut(AOP(result),"a",0);
4616 emitcode("pop","acc");
4617 lbl = newiTempLabel(NULL);
4618 emitcode("jnb","F0,%05d$",lbl->key+100);
4619 emitcode("cpl","a");
4620 emitcode("addc","a,#0");
4621 emitcode("","%05d$:", lbl->key+100);
4622 aopPut(AOP(result),"a",1);
4624 freeAsmop (result, NULL, ic, TRUE);
4625 /* restore EA bit in F1 */
4626 lbl = newiTempLabel(NULL);
4627 emitcode ("jnb","F1,%05d$",lbl->key+100);
4628 emitcode ("setb","EA");
4629 emitcode("","%05d$:",lbl->key+100);
4633 /*-----------------------------------------------------------------*/
4634 /* genDiv - generates code for division */
4635 /*-----------------------------------------------------------------*/
4639 operand *left = IC_LEFT (ic);
4640 operand *right = IC_RIGHT (ic);
4641 operand *result = IC_RESULT (ic);
4643 D (emitcode (";", "genDiv "););
4645 /* assign the amsops */
4648 /* special cases first */
4650 if (AOP_TYPE (left) == AOP_CRY &&
4651 AOP_TYPE (right) == AOP_CRY)
4653 genDivbits (left, right, result, ic);
4657 /* if both are of size == 1 */
4658 if (AOP_SIZE (left) == 1 &&
4659 AOP_SIZE (right) == 1)
4661 genDivOneByte (left, right, result, ic);
4665 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4666 /* use the ds390 ARITHMETIC accel UNIT */
4667 genDivTwoByte (left, right, result, ic);
4670 /* should have been converted to function call */
4673 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4674 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4675 freeAsmop (result, NULL, ic, TRUE);
4678 /*-----------------------------------------------------------------*/
4679 /* genModbits :- modulus of bits */
4680 /*-----------------------------------------------------------------*/
4682 genModbits (operand * left,
4690 /* the result must be bit */
4691 LOAD_AB_FOR_DIV (left, right, l);
4692 emitcode ("div", "ab");
4693 emitcode ("mov", "a,b");
4694 emitcode ("rrc", "a");
4695 aopOp(result, ic, TRUE, FALSE);
4696 aopPut (AOP (result), "c", 0);
4699 /*-----------------------------------------------------------------*/
4700 /* genModOneByte : 8 bit modulus */
4701 /*-----------------------------------------------------------------*/
4703 genModOneByte (operand * left,
4708 sym_link *opetype = operandType (result);
4712 /* signed or unsigned */
4713 if (SPEC_USIGN (opetype))
4715 /* unsigned is easy */
4716 LOAD_AB_FOR_DIV (left, right, l);
4717 emitcode ("div", "ab");
4718 aopOp(result, ic, TRUE, FALSE);
4719 aopPut (AOP (result), "b", 0);
4723 /* signed is a little bit more difficult */
4725 /* save the signs of the operands */
4726 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4729 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4730 emitcode ("push", "acc"); /* save it on the stack */
4732 /* now sign adjust for both left & right */
4733 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4736 lbl = newiTempLabel (NULL);
4737 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4738 emitcode ("cpl", "a");
4739 emitcode ("inc", "a");
4740 emitcode ("", "%05d$:", (lbl->key + 100));
4741 emitcode ("mov", "b,a");
4743 /* sign adjust left side */
4744 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4747 lbl = newiTempLabel (NULL);
4748 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4749 emitcode ("cpl", "a");
4750 emitcode ("inc", "a");
4751 emitcode ("", "%05d$:", (lbl->key + 100));
4753 /* now the multiplication */
4754 emitcode ("nop", "; workaround for DS80C390 div bug.");
4755 emitcode ("div", "ab");
4756 /* we are interested in the lower order
4758 lbl = newiTempLabel (NULL);
4759 emitcode ("pop", "acc");
4760 /* if there was an over flow we don't
4761 adjust the sign of the result */
4762 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4763 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4765 emitcode ("clr", "a");
4766 emitcode ("subb", "a,b");
4767 emitcode ("mov", "b,a");
4768 emitcode ("", "%05d$:", (lbl->key + 100));
4770 /* now we are done */
4771 aopOp(result, ic, TRUE, FALSE);
4772 aopPut (AOP (result), "b", 0);
4776 /*-----------------------------------------------------------------*/
4777 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
4778 /*-----------------------------------------------------------------*/
4779 static void genModTwoByte (operand *left, operand *right,
4780 operand *result, iCode *ic)
4782 sym_link *retype = getSpec(operandType(right));
4783 sym_link *letype = getSpec(operandType(left));
4784 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4787 /* load up MA with left */
4788 /* save EA bit in F1 */
4789 lbl = newiTempLabel(NULL);
4790 emitcode ("setb","F1");
4791 emitcode ("jbc","EA,%05d$",lbl->key+100);
4792 emitcode ("clr","F1");
4793 emitcode("","%05d$:",lbl->key+100);
4796 lbl = newiTempLabel(NULL);
4797 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4798 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4799 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4800 emitcode ("xch", "a,b");
4801 emitcode ("cpl","a");
4802 emitcode ("add", "a,#1");
4803 emitcode ("xch", "a,b");
4804 emitcode ("cpl", "a"); // msb
4805 emitcode ("addc","a,#0");
4806 emitcode ("","%05d$:",lbl->key+100);
4807 emitcode ("mov","ma,b");
4808 emitcode ("mov","ma,a");
4810 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4811 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4814 /* load up MB with right */
4816 if (AOP_TYPE(right) == AOP_LIT) {
4817 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4821 emitcode ("mov","mb,#0x%02x",val & 0xff);
4822 emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4824 lbl = newiTempLabel(NULL);
4825 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4826 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4827 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4828 emitcode ("xch", "a,b");
4829 emitcode ("cpl","a");
4830 emitcode ("add", "a,#1");
4831 emitcode ("xch", "a,b");
4832 emitcode ("cpl", "a"); // msb
4833 emitcode ("addc", "a,#0");
4834 emitcode ("","%05d$:",lbl->key+100);
4835 emitcode ("mov","mb,b");
4836 emitcode ("mov","mb,a");
4839 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4840 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4843 /* wait for multiplication to finish */
4844 lbl = newiTempLabel(NULL);
4845 emitcode("","%05d$:", lbl->key+100);
4846 emitcode("mov","a,mcnt1");
4847 emitcode("anl","a,#0x80");
4848 emitcode("jnz","%05d$",lbl->key+100);
4850 freeAsmop (left, NULL, ic, TRUE);
4851 freeAsmop (right, NULL, ic,TRUE);
4852 aopOp(result, ic, TRUE, FALSE);
4854 aopPut(AOP(result),"mb",1);
4855 aopPut(AOP(result),"mb",0);
4856 freeAsmop (result, NULL, ic, TRUE);
4858 /* restore EA bit in F1 */
4859 lbl = newiTempLabel(NULL);
4860 emitcode ("jnb","F1,%05d$",lbl->key+100);
4861 emitcode ("setb","EA");
4862 emitcode("","%05d$:",lbl->key+100);
4866 /*-----------------------------------------------------------------*/
4867 /* genMod - generates code for division */
4868 /*-----------------------------------------------------------------*/
4872 operand *left = IC_LEFT (ic);
4873 operand *right = IC_RIGHT (ic);
4874 operand *result = IC_RESULT (ic);
4876 D (emitcode (";", "genMod "); );
4878 /* assign the amsops */
4881 /* special cases first */
4883 if (AOP_TYPE (left) == AOP_CRY &&
4884 AOP_TYPE (right) == AOP_CRY)
4886 genModbits (left, right, result, ic);
4890 /* if both are of size == 1 */
4891 if (AOP_SIZE (left) == 1 &&
4892 AOP_SIZE (right) == 1)
4894 genModOneByte (left, right, result, ic);
4898 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4899 /* use the ds390 ARITHMETIC accel UNIT */
4900 genModTwoByte (left, right, result, ic);
4904 /* should have been converted to function call */
4908 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4909 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4910 freeAsmop (result, NULL, ic, TRUE);
4913 /*-----------------------------------------------------------------*/
4914 /* genIfxJump :- will create a jump depending on the ifx */
4915 /*-----------------------------------------------------------------*/
4917 genIfxJump (iCode * ic, char *jval)
4920 symbol *tlbl = newiTempLabel (NULL);
4923 D (emitcode (";", "genIfxJump ");
4926 /* if true label then we jump if condition
4930 jlbl = IC_TRUE (ic);
4931 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4932 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4936 /* false label is present */
4937 jlbl = IC_FALSE (ic);
4938 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4939 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4941 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4942 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4944 emitcode (inst, "%05d$", tlbl->key + 100);
4945 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4946 emitcode ("", "%05d$:", tlbl->key + 100);
4948 /* mark the icode as generated */
4952 /*-----------------------------------------------------------------*/
4953 /* genCmp :- greater or less than comparison */
4954 /*-----------------------------------------------------------------*/
4956 genCmp (operand * left, operand * right,
4957 iCode * ic, iCode * ifx, int sign)
4959 int size, offset = 0;
4960 unsigned long lit = 0L;
4963 D (emitcode (";", "genCmp");
4966 result = IC_RESULT (ic);
4968 /* if left & right are bit variables */
4969 if (AOP_TYPE (left) == AOP_CRY &&
4970 AOP_TYPE (right) == AOP_CRY)
4972 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4973 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4977 /* subtract right from left if at the
4978 end the carry flag is set then we know that
4979 left is greater than right */
4980 size = max (AOP_SIZE (left), AOP_SIZE (right));
4982 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4983 if ((size == 1) && !sign &&
4984 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4986 symbol *lbl = newiTempLabel (NULL);
4987 emitcode ("cjne", "%s,%s,%05d$",
4988 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4989 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4991 emitcode ("", "%05d$:", lbl->key + 100);
4995 if (AOP_TYPE (right) == AOP_LIT)
4997 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4998 /* optimize if(x < 0) or if(x >= 0) */
5007 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5009 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5010 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5012 aopOp (result, ic, FALSE, FALSE);
5014 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5016 freeAsmop (result, NULL, ic, TRUE);
5017 genIfxJump (ifx, "acc.7");
5022 emitcode ("rlc", "a");
5024 goto release_freedLR;
5032 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5033 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5034 emitcode (";", "genCmp #2");
5035 if (sign && (size == 0))
5037 emitcode (";", "genCmp #3");
5038 emitcode ("xrl", "a,#0x80");
5039 if (AOP_TYPE (right) == AOP_LIT)
5041 unsigned long lit = (unsigned long)
5042 floatFromVal (AOP (right)->aopu.aop_lit);
5043 emitcode (";", "genCmp #3.1");
5044 emitcode ("subb", "a,#0x%02x",
5045 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5049 emitcode (";", "genCmp #3.2");
5050 if (AOP_NEEDSACC (right))
5052 emitcode ("push", "acc");
5054 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
5055 FALSE, FALSE, FALSE));
5056 emitcode ("xrl", "b,#0x80");
5057 if (AOP_NEEDSACC (right))
5059 emitcode ("pop", "acc");
5061 emitcode ("subb", "a,b");
5068 emitcode (";", "genCmp #4");
5069 if (AOP_NEEDSACC (right))
5072 emitcode (";", "genCmp #4.1");
5073 emitcode ("xch", "a, b");
5074 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
5075 emitcode ("xch", "a, b");
5080 emitcode (";", "genCmp #4.2");
5081 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
5084 emitcode ("subb", "a,%s", s);
5091 /* Don't need the left & right operands any more; do need the result. */
5092 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5093 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5095 aopOp (result, ic, FALSE, FALSE);
5099 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5105 /* if the result is used in the next
5106 ifx conditional branch then generate
5107 code a little differently */
5110 genIfxJump (ifx, "c");
5116 /* leave the result in acc */
5118 freeAsmop (result, NULL, ic, TRUE);
5121 /*-----------------------------------------------------------------*/
5122 /* genCmpGt :- greater than comparison */
5123 /*-----------------------------------------------------------------*/
5125 genCmpGt (iCode * ic, iCode * ifx)
5127 operand *left, *right;
5128 sym_link *letype, *retype;
5131 D (emitcode (";", "genCmpGt ");
5134 left = IC_LEFT (ic);
5135 right = IC_RIGHT (ic);
5137 letype = getSpec (operandType (left));
5138 retype = getSpec (operandType (right));
5139 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5141 /* assign the left & right amsops */
5144 genCmp (right, left, ic, ifx, sign);
5147 /*-----------------------------------------------------------------*/
5148 /* genCmpLt - less than comparisons */
5149 /*-----------------------------------------------------------------*/
5151 genCmpLt (iCode * ic, iCode * ifx)
5153 operand *left, *right;
5154 sym_link *letype, *retype;
5157 D (emitcode (";", "genCmpLt "););
5159 left = IC_LEFT (ic);
5160 right = IC_RIGHT (ic);
5162 letype = getSpec (operandType (left));
5163 retype = getSpec (operandType (right));
5164 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5166 /* assign the left & right amsops */
5169 genCmp (left, right, ic, ifx, sign);
5172 /*-----------------------------------------------------------------*/
5173 /* gencjneshort - compare and jump if not equal */
5174 /*-----------------------------------------------------------------*/
5176 gencjneshort (operand * left, operand * right, symbol * lbl)
5178 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5180 unsigned long lit = 0L;
5182 D (emitcode (";", "gencjneshort");
5185 /* if the left side is a literal or
5186 if the right is in a pointer register and left
5188 if ((AOP_TYPE (left) == AOP_LIT) ||
5189 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5196 if (AOP_TYPE (right) == AOP_LIT)
5197 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5199 if (opIsGptr (left) || opIsGptr (right))
5201 /* We are comparing a generic pointer to something.
5202 * Exclude the generic type byte from the comparison.
5205 D (emitcode (";", "cjneshort: generic ptr special case.");
5210 /* if the right side is a literal then anything goes */
5211 if (AOP_TYPE (right) == AOP_LIT &&
5212 AOP_TYPE (left) != AOP_DIR)
5216 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5218 emitcode ("cjne", "a,%s,%05d$",
5219 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5225 /* if the right side is in a register or in direct space or
5226 if the left is a pointer register & right is not */
5227 else if (AOP_TYPE (right) == AOP_REG ||
5228 AOP_TYPE (right) == AOP_DIR ||
5229 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5230 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5234 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5235 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5236 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5237 emitcode ("jnz", "%05d$", lbl->key + 100);
5239 emitcode ("cjne", "a,%s,%05d$",
5240 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5247 /* right is a pointer reg need both a & b */
5250 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5251 if (strcmp (l, "b"))
5252 emitcode ("mov", "b,%s", l);
5253 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5254 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5260 /*-----------------------------------------------------------------*/
5261 /* gencjne - compare and jump if not equal */
5262 /*-----------------------------------------------------------------*/
5264 gencjne (operand * left, operand * right, symbol * lbl)
5266 symbol *tlbl = newiTempLabel (NULL);
5268 D (emitcode (";", "gencjne");
5271 gencjneshort (left, right, lbl);
5273 emitcode ("mov", "a,%s", one);
5274 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5275 emitcode ("", "%05d$:", lbl->key + 100);
5276 emitcode ("clr", "a");
5277 emitcode ("", "%05d$:", tlbl->key + 100);
5280 /*-----------------------------------------------------------------*/
5281 /* genCmpEq - generates code for equal to */
5282 /*-----------------------------------------------------------------*/
5284 genCmpEq (iCode * ic, iCode * ifx)
5286 operand *left, *right, *result;
5288 D (emitcode (";", "genCmpEq ");
5292 AOP_SET_LOCALS (ic);
5294 /* if literal, literal on the right or
5295 if the right is in a pointer register and left
5297 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5298 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5300 operand *t = IC_RIGHT (ic);
5301 IC_RIGHT (ic) = IC_LEFT (ic);
5305 if (ifx && /* !AOP_SIZE(result) */
5306 OP_SYMBOL (result) &&
5307 OP_SYMBOL (result)->regType == REG_CND)
5310 /* if they are both bit variables */
5311 if (AOP_TYPE (left) == AOP_CRY &&
5312 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5314 if (AOP_TYPE (right) == AOP_LIT)
5316 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5319 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5320 emitcode ("cpl", "c");
5324 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5328 emitcode ("clr", "c");
5330 /* AOP_TYPE(right) == AOP_CRY */
5334 symbol *lbl = newiTempLabel (NULL);
5335 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5336 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5337 emitcode ("cpl", "c");
5338 emitcode ("", "%05d$:", (lbl->key + 100));
5340 /* if true label then we jump if condition
5342 tlbl = newiTempLabel (NULL);
5345 emitcode ("jnc", "%05d$", tlbl->key + 100);
5346 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5350 emitcode ("jc", "%05d$", tlbl->key + 100);
5351 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5353 emitcode ("", "%05d$:", tlbl->key + 100);
5357 tlbl = newiTempLabel (NULL);
5358 gencjneshort (left, right, tlbl);
5361 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5362 emitcode ("", "%05d$:", tlbl->key + 100);
5366 symbol *lbl = newiTempLabel (NULL);
5367 emitcode ("sjmp", "%05d$", lbl->key + 100);
5368 emitcode ("", "%05d$:", tlbl->key + 100);
5369 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5370 emitcode ("", "%05d$:", lbl->key + 100);
5373 /* mark the icode as generated */
5376 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5377 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5381 /* if they are both bit variables */
5382 if (AOP_TYPE (left) == AOP_CRY &&
5383 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5385 if (AOP_TYPE (right) == AOP_LIT)
5387 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5390 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5391 emitcode ("cpl", "c");
5395 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5399 emitcode ("clr", "c");
5401 /* AOP_TYPE(right) == AOP_CRY */
5405 symbol *lbl = newiTempLabel (NULL);
5406 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5407 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5408 emitcode ("cpl", "c");
5409 emitcode ("", "%05d$:", (lbl->key + 100));
5412 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5413 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5415 aopOp (result, ic, TRUE, FALSE);
5418 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5425 genIfxJump (ifx, "c");
5428 /* if the result is used in an arithmetic operation
5429 then put the result in place */
5434 gencjne (left, right, newiTempLabel (NULL));
5436 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5437 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5439 aopOp (result, ic, TRUE, FALSE);
5441 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5443 aopPut (AOP (result), "a", 0);
5448 genIfxJump (ifx, "a");
5451 /* if the result is used in an arithmetic operation
5452 then put the result in place */
5453 if (AOP_TYPE (result) != AOP_CRY)
5455 /* leave the result in acc */
5459 freeAsmop (result, NULL, ic, TRUE);
5462 /*-----------------------------------------------------------------*/
5463 /* ifxForOp - returns the icode containing the ifx for operand */
5464 /*-----------------------------------------------------------------*/
5466 ifxForOp (operand * op, iCode * ic)
5468 /* if true symbol then needs to be assigned */
5469 if (IS_TRUE_SYMOP (op))
5472 /* if this has register type condition and
5473 the next instruction is ifx with the same operand
5474 and live to of the operand is upto the ifx only then */
5476 ic->next->op == IFX &&
5477 IC_COND (ic->next)->key == op->key &&
5478 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5483 /*-----------------------------------------------------------------*/
5484 /* hasInc - operand is incremented before any other use */
5485 /*-----------------------------------------------------------------*/
5487 hasInc (operand *op, iCode *ic)
5489 sym_link *type = operandType(op);
5490 sym_link *retype = getSpec (type);
5491 iCode *lic = ic->next;
5494 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5495 if (!IS_SYMOP(op)) return NULL;
5497 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5498 isize = getSize(type->next);
5500 /* if operand of the form op = op + <sizeof *op> */
5501 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5502 isOperandEqual(IC_RESULT(lic),op) &&
5503 isOperandLiteral(IC_RIGHT(lic)) &&
5504 operandLitValue(IC_RIGHT(lic)) == isize) {
5507 /* if the operand used or deffed */
5508 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5511 /* if GOTO or IFX */
5512 if (lic->op == IFX || lic->op == GOTO) break;
5518 /*-----------------------------------------------------------------*/
5519 /* genAndOp - for && operation */
5520 /*-----------------------------------------------------------------*/
5522 genAndOp (iCode * ic)
5524 operand *left, *right, *result;
5527 D (emitcode (";", "genAndOp "););
5529 /* note here that && operations that are in an
5530 if statement are taken away by backPatchLabels
5531 only those used in arthmetic operations remain */
5533 AOP_SET_LOCALS (ic);
5535 /* if both are bit variables */
5536 if (AOP_TYPE (left) == AOP_CRY &&
5537 AOP_TYPE (right) == AOP_CRY)
5539 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5540 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5541 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5542 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5544 aopOp (result,ic,FALSE, FALSE);
5549 tlbl = newiTempLabel (NULL);
5551 emitcode ("jz", "%05d$", tlbl->key + 100);
5553 emitcode ("", "%05d$:", tlbl->key + 100);
5554 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5555 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5557 aopOp (result,ic,FALSE, FALSE);
5560 freeAsmop (result, NULL, ic, TRUE);
5564 /*-----------------------------------------------------------------*/
5565 /* genOrOp - for || operation */
5566 /*-----------------------------------------------------------------*/
5568 genOrOp (iCode * ic)
5570 operand *left, *right, *result;
5573 D (emitcode (";", "genOrOp "););
5575 /* note here that || operations that are in an
5576 if statement are taken away by backPatchLabels
5577 only those used in arthmetic operations remain */
5579 AOP_SET_LOCALS (ic);
5581 /* if both are bit variables */
5582 if (AOP_TYPE (left) == AOP_CRY &&
5583 AOP_TYPE (right) == AOP_CRY)
5585 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5586 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5587 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5588 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5590 aopOp (result,ic,FALSE, FALSE);
5596 tlbl = newiTempLabel (NULL);
5598 emitcode ("jnz", "%05d$", tlbl->key + 100);
5600 emitcode ("", "%05d$:", tlbl->key + 100);
5601 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5602 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5604 aopOp (result,ic,FALSE, FALSE);
5609 freeAsmop (result, NULL, ic, TRUE);
5612 /*-----------------------------------------------------------------*/
5613 /* isLiteralBit - test if lit == 2^n */
5614 /*-----------------------------------------------------------------*/
5616 isLiteralBit (unsigned long lit)
5618 unsigned long pw[32] =
5619 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5620 0x100L, 0x200L, 0x400L, 0x800L,
5621 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5622 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5623 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5624 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5625 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5628 for (idx = 0; idx < 32; idx++)
5634 /*-----------------------------------------------------------------*/
5635 /* continueIfTrue - */
5636 /*-----------------------------------------------------------------*/
5638 continueIfTrue (iCode * ic)
5641 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5645 /*-----------------------------------------------------------------*/
5647 /*-----------------------------------------------------------------*/
5649 jumpIfTrue (iCode * ic)
5652 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5656 /*-----------------------------------------------------------------*/
5657 /* jmpTrueOrFalse - */
5658 /*-----------------------------------------------------------------*/
5660 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5662 // ugly but optimized by peephole
5665 symbol *nlbl = newiTempLabel (NULL);
5666 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5667 emitcode ("", "%05d$:", tlbl->key + 100);
5668 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5669 emitcode ("", "%05d$:", nlbl->key + 100);
5673 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5674 emitcode ("", "%05d$:", tlbl->key + 100);
5679 // Generate code to perform a bit-wise logic operation
5680 // on two operands in far space (assumed to already have been
5681 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5682 // in far space. This requires pushing the result on the stack
5683 // then popping it into the result.
5685 genFarFarLogicOp(iCode *ic, char *logicOp)
5687 int size, resultSize, compSize;
5691 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5692 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5693 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5695 _startLazyDPSEvaluation();
5696 for (size = compSize; (size--); offset++)
5698 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5699 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5700 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5702 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5703 emitcode ("push", "acc");
5705 _endLazyDPSEvaluation();
5707 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5708 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5709 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5711 resultSize = AOP_SIZE(IC_RESULT(ic));
5713 ADJUST_PUSHED_RESULT(compSize, resultSize);
5715 _startLazyDPSEvaluation();
5718 emitcode ("pop", "acc");
5719 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5721 _endLazyDPSEvaluation();
5722 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5726 /*-----------------------------------------------------------------*/
5727 /* genAnd - code for and */
5728 /*-----------------------------------------------------------------*/
5730 genAnd (iCode * ic, iCode * ifx)
5732 operand *left, *right, *result;
5733 int size, offset = 0;
5734 unsigned long lit = 0L;
5739 D (emitcode (";", "genAnd "););
5741 AOP_OP_3_NOFATAL (ic, pushResult);
5742 AOP_SET_LOCALS (ic);
5746 genFarFarLogicOp(ic, "anl");
5751 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5753 AOP_TYPE (left), AOP_TYPE (right));
5754 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5756 AOP_SIZE (left), AOP_SIZE (right));
5759 /* if left is a literal & right is not then exchange them */
5760 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5761 #ifdef LOGIC_OPS_BROKEN
5762 || AOP_NEEDSACC (left)
5766 operand *tmp = right;
5771 /* if result = right then exchange them */
5772 if (sameRegs (AOP (result), AOP (right)))
5774 operand *tmp = right;
5779 /* if right is bit then exchange them */
5780 if (AOP_TYPE (right) == AOP_CRY &&
5781 AOP_TYPE (left) != AOP_CRY)
5783 operand *tmp = right;
5787 if (AOP_TYPE (right) == AOP_LIT)
5788 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5790 size = AOP_SIZE (result);
5793 // result = bit & yy;
5794 if (AOP_TYPE (left) == AOP_CRY)
5796 // c = bit & literal;
5797 if (AOP_TYPE (right) == AOP_LIT)
5801 if (size && sameRegs (AOP (result), AOP (left)))
5804 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5809 if (size && (AOP_TYPE (result) == AOP_CRY))
5811 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5814 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5819 emitcode ("clr", "c");
5824 if (AOP_TYPE (right) == AOP_CRY)
5827 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5828 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5833 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5835 emitcode ("rrc", "a");
5836 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5844 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5845 genIfxJump (ifx, "c");
5849 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5850 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5851 if ((AOP_TYPE (right) == AOP_LIT) &&
5852 (AOP_TYPE (result) == AOP_CRY) &&
5853 (AOP_TYPE (left) != AOP_CRY))
5855 int posbit = isLiteralBit (lit);
5860 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5863 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5869 sprintf (buffer, "acc.%d", posbit & 0x07);
5870 genIfxJump (ifx, buffer);
5877 symbol *tlbl = newiTempLabel (NULL);
5878 int sizel = AOP_SIZE (left);
5880 emitcode ("setb", "c");
5883 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5885 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5887 if ((posbit = isLiteralBit (bytelit)) != 0)
5888 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5891 if (bytelit != 0x0FFL)
5892 emitcode ("anl", "a,%s",
5893 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5894 emitcode ("jnz", "%05d$", tlbl->key + 100);
5899 // bit = left & literal
5902 emitcode ("clr", "c");
5903 emitcode ("", "%05d$:", tlbl->key + 100);
5905 // if(left & literal)
5909 jmpTrueOrFalse (ifx, tlbl);
5917 /* if left is same as result */
5918 if (sameRegs (AOP (result), AOP (left)))
5920 for (; size--; offset++)
5922 if (AOP_TYPE (right) == AOP_LIT)
5924 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5926 else if (bytelit == 0)
5927 aopPut (AOP (result), zero, offset);
5928 else if (IS_AOP_PREG (result))
5930 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5931 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5932 aopPut (AOP (result), "a", offset);
5935 emitcode ("anl", "%s,%s",
5936 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5937 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5941 if (AOP_TYPE (left) == AOP_ACC)
5942 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5945 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5946 if (IS_AOP_PREG (result))
5948 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5949 aopPut (AOP (result), "a", offset);
5953 emitcode ("anl", "%s,a",
5954 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5961 // left & result in different registers
5962 if (AOP_TYPE (result) == AOP_CRY)
5965 // if(size), result in bit
5966 // if(!size && ifx), conditional oper: if(left & right)
5967 symbol *tlbl = newiTempLabel (NULL);
5968 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5970 emitcode ("setb", "c");
5973 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5974 emitcode ("anl", "a,%s",
5975 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5977 if (AOP_TYPE(left)==AOP_ACC) {
5978 emitcode("mov", "b,a");
5979 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5980 emitcode("anl", "a,b");
5982 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5983 emitcode ("anl", "a,%s",
5984 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5987 emitcode ("jnz", "%05d$", tlbl->key + 100);
5993 emitcode ("", "%05d$:", tlbl->key + 100);
5997 jmpTrueOrFalse (ifx, tlbl);
6001 for (; (size--); offset++)
6004 // result = left & right
6005 if (AOP_TYPE (right) == AOP_LIT)
6007 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6009 aopPut (AOP (result),
6010 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6014 else if (bytelit == 0)
6016 aopPut (AOP (result), zero, offset);
6019 D (emitcode (";", "better literal AND."););
6020 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6021 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6022 FALSE, FALSE, FALSE));
6027 // faster than result <- left, anl result,right
6028 // and better if result is SFR
6029 if (AOP_TYPE (left) == AOP_ACC)
6031 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
6032 FALSE, FALSE, FALSE));
6036 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6037 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6039 emitcode("mov", "b,a");
6043 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6044 emitcode ("anl", "a,%s", rOp);
6047 aopPut (AOP (result), "a", offset);
6053 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6054 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6055 freeAsmop (result, NULL, ic, TRUE);
6059 /*-----------------------------------------------------------------*/
6060 /* genOr - code for or */
6061 /*-----------------------------------------------------------------*/
6063 genOr (iCode * ic, iCode * ifx)
6065 operand *left, *right, *result;
6066 int size, offset = 0;
6067 unsigned long lit = 0L;
6070 D (emitcode (";", "genOr "););
6072 AOP_OP_3_NOFATAL (ic, pushResult);
6073 AOP_SET_LOCALS (ic);
6077 genFarFarLogicOp(ic, "orl");
6083 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6085 AOP_TYPE (left), AOP_TYPE (right));
6086 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6088 AOP_SIZE (left), AOP_SIZE (right));
6091 /* if left is a literal & right is not then exchange them */
6092 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6093 #ifdef LOGIC_OPS_BROKEN
6094 || AOP_NEEDSACC (left) // I think this is a net loss now.
6098 operand *tmp = right;
6103 /* if result = right then exchange them */
6104 if (sameRegs (AOP (result), AOP (right)))
6106 operand *tmp = right;
6111 /* if right is bit then exchange them */
6112 if (AOP_TYPE (right) == AOP_CRY &&
6113 AOP_TYPE (left) != AOP_CRY)
6115 operand *tmp = right;
6119 if (AOP_TYPE (right) == AOP_LIT)
6120 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6122 size = AOP_SIZE (result);
6126 if (AOP_TYPE (left) == AOP_CRY)
6128 if (AOP_TYPE (right) == AOP_LIT)
6130 // c = bit & literal;
6133 // lit != 0 => result = 1
6134 if (AOP_TYPE (result) == AOP_CRY)
6137 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6139 continueIfTrue (ifx);
6142 emitcode ("setb", "c");
6146 // lit == 0 => result = left
6147 if (size && sameRegs (AOP (result), AOP (left)))
6149 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6154 if (AOP_TYPE (right) == AOP_CRY)
6157 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6158 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6163 symbol *tlbl = newiTempLabel (NULL);
6164 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6165 emitcode ("setb", "c");
6166 emitcode ("jb", "%s,%05d$",
6167 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6169 emitcode ("jnz", "%05d$", tlbl->key + 100);
6170 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6172 jmpTrueOrFalse (ifx, tlbl);
6178 emitcode ("", "%05d$:", tlbl->key + 100);
6187 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6188 genIfxJump (ifx, "c");
6192 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6193 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6194 if ((AOP_TYPE (right) == AOP_LIT) &&
6195 (AOP_TYPE (result) == AOP_CRY) &&
6196 (AOP_TYPE (left) != AOP_CRY))
6202 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6204 continueIfTrue (ifx);
6209 // lit = 0, result = boolean(left)
6211 emitcode ("setb", "c");
6215 symbol *tlbl = newiTempLabel (NULL);
6216 emitcode ("jnz", "%05d$", tlbl->key + 100);
6218 emitcode ("", "%05d$:", tlbl->key + 100);
6222 genIfxJump (ifx, "a");
6230 /* if left is same as result */
6231 if (sameRegs (AOP (result), AOP (left)))
6233 for (; size--; offset++)
6235 if (AOP_TYPE (right) == AOP_LIT)
6237 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6243 if (IS_AOP_PREG (left))
6245 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6246 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6247 aopPut (AOP (result), "a", offset);
6251 emitcode ("orl", "%s,%s",
6252 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6253 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6259 if (AOP_TYPE (left) == AOP_ACC)
6261 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6265 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6266 if (IS_AOP_PREG (left))
6268 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6269 aopPut (AOP (result), "a", offset);
6273 emitcode ("orl", "%s,a",
6274 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6282 // left & result in different registers
6283 if (AOP_TYPE (result) == AOP_CRY)
6286 // if(size), result in bit
6287 // if(!size && ifx), conditional oper: if(left | right)
6288 symbol *tlbl = newiTempLabel (NULL);
6289 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6291 emitcode ("setb", "c");
6294 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6295 emitcode ("orl", "a,%s",
6296 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6298 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6299 emitcode ("orl", "a,%s",
6300 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6302 emitcode ("jnz", "%05d$", tlbl->key + 100);
6308 emitcode ("", "%05d$:", tlbl->key + 100);
6312 jmpTrueOrFalse (ifx, tlbl);
6316 _startLazyDPSEvaluation();
6317 for (; (size--); offset++)
6320 // result = left & right
6321 if (AOP_TYPE (right) == AOP_LIT)
6323 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6325 aopPut (AOP (result),
6326 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6330 D (emitcode (";", "better literal OR."););
6331 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6332 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6333 FALSE, FALSE, FALSE));
6338 // faster than result <- left, anl result,right
6339 // and better if result is SFR
6340 if (AOP_TYPE (left) == AOP_ACC)
6342 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6343 FALSE, FALSE, FALSE));
6347 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6349 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6351 emitcode("mov", "b,a");
6355 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6356 emitcode ("orl", "a,%s", rOp);
6359 aopPut (AOP (result), "a", offset);
6361 _endLazyDPSEvaluation();
6366 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6367 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6368 freeAsmop (result, NULL, ic, TRUE);
6371 /*-----------------------------------------------------------------*/
6372 /* genXor - code for xclusive or */
6373 /*-----------------------------------------------------------------*/
6375 genXor (iCode * ic, iCode * ifx)
6377 operand *left, *right, *result;
6378 int size, offset = 0;
6379 unsigned long lit = 0L;
6382 D (emitcode (";", "genXor "););
6384 AOP_OP_3_NOFATAL (ic, pushResult);
6385 AOP_SET_LOCALS (ic);
6389 genFarFarLogicOp(ic, "xrl");
6394 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6396 AOP_TYPE (left), AOP_TYPE (right));
6397 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6399 AOP_SIZE (left), AOP_SIZE (right));
6402 /* if left is a literal & right is not ||
6403 if left needs acc & right does not */
6404 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6405 #ifdef LOGIC_OPS_BROKEN
6406 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6410 operand *tmp = right;
6415 /* if result = right then exchange them */
6416 if (sameRegs (AOP (result), AOP (right)))
6418 operand *tmp = right;
6423 /* if right is bit then exchange them */
6424 if (AOP_TYPE (right) == AOP_CRY &&
6425 AOP_TYPE (left) != AOP_CRY)
6427 operand *tmp = right;
6431 if (AOP_TYPE (right) == AOP_LIT)
6432 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6434 size = AOP_SIZE (result);
6438 if (AOP_TYPE (left) == AOP_CRY)
6440 if (AOP_TYPE (right) == AOP_LIT)
6442 // c = bit & literal;
6445 // lit>>1 != 0 => result = 1
6446 if (AOP_TYPE (result) == AOP_CRY)
6449 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6451 continueIfTrue (ifx);
6454 emitcode ("setb", "c");
6461 // lit == 0, result = left
6462 if (size && sameRegs (AOP (result), AOP (left)))
6464 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6468 // lit == 1, result = not(left)
6469 if (size && sameRegs (AOP (result), AOP (left)))
6471 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6476 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6477 emitcode ("cpl", "c");
6486 symbol *tlbl = newiTempLabel (NULL);
6487 if (AOP_TYPE (right) == AOP_CRY)
6490 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6494 int sizer = AOP_SIZE (right);
6496 // if val>>1 != 0, result = 1
6497 emitcode ("setb", "c");
6500 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6502 // test the msb of the lsb
6503 emitcode ("anl", "a,#0xfe");
6504 emitcode ("jnz", "%05d$", tlbl->key + 100);
6508 emitcode ("rrc", "a");
6510 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6511 emitcode ("cpl", "c");
6512 emitcode ("", "%05d$:", (tlbl->key + 100));
6519 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6520 genIfxJump (ifx, "c");
6524 if (sameRegs (AOP (result), AOP (left)))
6526 /* if left is same as result */
6527 for (; size--; offset++)
6529 if (AOP_TYPE (right) == AOP_LIT)
6531 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6533 else if (IS_AOP_PREG (left))
6535 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6536 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6537 aopPut (AOP (result), "a", offset);
6540 emitcode ("xrl", "%s,%s",
6541 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6542 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6546 if (AOP_TYPE (left) == AOP_ACC)
6547 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6550 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6551 if (IS_AOP_PREG (left))
6553 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6554 aopPut (AOP (result), "a", offset);
6557 emitcode ("xrl", "%s,a",
6558 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6565 // left & result in different registers
6566 if (AOP_TYPE (result) == AOP_CRY)
6569 // if(size), result in bit
6570 // if(!size && ifx), conditional oper: if(left ^ right)
6571 symbol *tlbl = newiTempLabel (NULL);
6572 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6575 emitcode ("setb", "c");
6578 if ((AOP_TYPE (right) == AOP_LIT) &&
6579 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6581 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6585 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6586 emitcode ("xrl", "a,%s",
6587 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6589 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6590 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6592 emitcode("mov", "b,a");
6596 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6597 emitcode ("xrl", "a,%s", rOp);
6600 emitcode ("jnz", "%05d$", tlbl->key + 100);
6606 emitcode ("", "%05d$:", tlbl->key + 100);
6610 jmpTrueOrFalse (ifx, tlbl);
6614 for (; (size--); offset++)
6617 // result = left & right
6618 if (AOP_TYPE (right) == AOP_LIT)
6620 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6622 aopPut (AOP (result),
6623 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6627 D (emitcode (";", "better literal XOR."););
6628 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6629 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6630 FALSE, FALSE, FALSE));
6634 // faster than result <- left, anl result,right
6635 // and better if result is SFR
6636 if (AOP_TYPE (left) == AOP_ACC)
6638 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6639 FALSE, FALSE, FALSE));
6643 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6644 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6646 emitcode("mov", "b,a");
6650 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6651 emitcode ("xrl", "a,%s", rOp);
6654 aopPut (AOP (result), "a", offset);
6661 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6662 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6663 freeAsmop (result, NULL, ic, TRUE);
6666 /*-----------------------------------------------------------------*/
6667 /* genInline - write the inline code out */
6668 /*-----------------------------------------------------------------*/
6670 genInline (iCode * ic)
6672 char *buffer, *bp, *bp1;
6674 D (emitcode (";", "genInline ");
6677 _G.inLine += (!options.asmpeep);
6679 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6680 strcpy (buffer, IC_INLINE (ic));
6682 /* emit each line as a code */
6707 /* emitcode("",buffer); */
6708 _G.inLine -= (!options.asmpeep);
6711 /*-----------------------------------------------------------------*/
6712 /* genRRC - rotate right with carry */
6713 /*-----------------------------------------------------------------*/
6717 operand *left, *result;
6718 int size, offset = 0;
6721 D (emitcode (";", "genRRC ");
6724 /* rotate right with carry */
6725 left = IC_LEFT (ic);
6726 result = IC_RESULT (ic);
6727 aopOp (left, ic, FALSE, FALSE);
6728 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6730 /* move it to the result */
6731 size = AOP_SIZE (result);
6735 _startLazyDPSEvaluation ();
6738 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6740 emitcode ("rrc", "a");
6741 if (AOP_SIZE (result) > 1)
6742 aopPut (AOP (result), "a", offset--);
6744 _endLazyDPSEvaluation ();
6746 /* now we need to put the carry into the
6747 highest order byte of the result */
6748 if (AOP_SIZE (result) > 1)
6750 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6753 emitcode ("mov", "acc.7,c");
6754 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6755 freeAsmop (left, NULL, ic, TRUE);
6756 freeAsmop (result, NULL, ic, TRUE);
6759 /*-----------------------------------------------------------------*/
6760 /* genRLC - generate code for rotate left with carry */
6761 /*-----------------------------------------------------------------*/
6765 operand *left, *result;
6766 int size, offset = 0;
6769 D (emitcode (";", "genRLC ");
6772 /* rotate right with carry */
6773 left = IC_LEFT (ic);
6774 result = IC_RESULT (ic);
6775 aopOp (left, ic, FALSE, FALSE);
6776 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6778 /* move it to the result */
6779 size = AOP_SIZE (result);
6783 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6785 emitcode ("add", "a,acc");
6786 if (AOP_SIZE (result) > 1)
6788 aopPut (AOP (result), "a", offset++);
6791 _startLazyDPSEvaluation ();
6794 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6796 emitcode ("rlc", "a");
6797 if (AOP_SIZE (result) > 1)
6798 aopPut (AOP (result), "a", offset++);
6800 _endLazyDPSEvaluation ();
6802 /* now we need to put the carry into the
6803 highest order byte of the result */
6804 if (AOP_SIZE (result) > 1)
6806 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6809 emitcode ("mov", "acc.0,c");
6810 aopPut (AOP (result), "a", 0);
6811 freeAsmop (left, NULL, ic, TRUE);
6812 freeAsmop (result, NULL, ic, TRUE);
6815 /*-----------------------------------------------------------------*/
6816 /* genGetHbit - generates code get highest order bit */
6817 /*-----------------------------------------------------------------*/
6819 genGetHbit (iCode * ic)
6821 operand *left, *result;
6822 left = IC_LEFT (ic);
6823 result = IC_RESULT (ic);
6824 aopOp (left, ic, FALSE, FALSE);
6825 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6827 D (emitcode (";", "genGetHbit ");
6830 /* get the highest order byte into a */
6831 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6832 if (AOP_TYPE (result) == AOP_CRY)
6834 emitcode ("rlc", "a");
6839 emitcode ("rl", "a");
6840 emitcode ("anl", "a,#0x01");
6845 freeAsmop (left, NULL, ic, TRUE);
6846 freeAsmop (result, NULL, ic, TRUE);
6849 /*-----------------------------------------------------------------*/
6850 /* AccRol - rotate left accumulator by known count */
6851 /*-----------------------------------------------------------------*/
6853 AccRol (int shCount)
6855 shCount &= 0x0007; // shCount : 0..7
6862 emitcode ("rl", "a");
6865 emitcode ("rl", "a");
6866 emitcode ("rl", "a");
6869 emitcode ("swap", "a");
6870 emitcode ("rr", "a");
6873 emitcode ("swap", "a");
6876 emitcode ("swap", "a");
6877 emitcode ("rl", "a");
6880 emitcode ("rr", "a");
6881 emitcode ("rr", "a");
6884 emitcode ("rr", "a");
6889 /*-----------------------------------------------------------------*/
6890 /* AccLsh - left shift accumulator by known count */
6891 /*-----------------------------------------------------------------*/
6893 AccLsh (int shCount)
6898 emitcode ("add", "a,acc");
6899 else if (shCount == 2)
6901 emitcode ("add", "a,acc");
6902 emitcode ("add", "a,acc");
6906 /* rotate left accumulator */
6908 /* and kill the lower order bits */
6909 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6914 /*-----------------------------------------------------------------*/
6915 /* AccRsh - right shift accumulator by known count */
6916 /*-----------------------------------------------------------------*/
6918 AccRsh (int shCount)
6925 emitcode ("rrc", "a");
6929 /* rotate right accumulator */
6930 AccRol (8 - shCount);
6931 /* and kill the higher order bits */
6932 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6937 #ifdef BETTER_LITERAL_SHIFT
6938 /*-----------------------------------------------------------------*/
6939 /* AccSRsh - signed right shift accumulator by known count */
6940 /*-----------------------------------------------------------------*/
6942 AccSRsh (int shCount)
6949 emitcode ("mov", "c,acc.7");
6950 emitcode ("rrc", "a");
6952 else if (shCount == 2)
6954 emitcode ("mov", "c,acc.7");
6955 emitcode ("rrc", "a");
6956 emitcode ("mov", "c,acc.7");
6957 emitcode ("rrc", "a");
6961 tlbl = newiTempLabel (NULL);
6962 /* rotate right accumulator */
6963 AccRol (8 - shCount);
6964 /* and kill the higher order bits */
6965 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6966 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6967 emitcode ("orl", "a,#0x%02x",
6968 (unsigned char) ~SRMask[shCount]);
6969 emitcode ("", "%05d$:", tlbl->key + 100);
6975 #ifdef BETTER_LITERAL_SHIFT
6976 /*-----------------------------------------------------------------*/
6977 /* shiftR1Left2Result - shift right one byte from left to result */
6978 /*-----------------------------------------------------------------*/
6980 shiftR1Left2Result (operand * left, int offl,
6981 operand * result, int offr,
6982 int shCount, int sign)
6984 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6985 /* shift right accumulator */
6990 aopPut (AOP (result), "a", offr);
6994 #ifdef BETTER_LITERAL_SHIFT
6995 /*-----------------------------------------------------------------*/
6996 /* shiftL1Left2Result - shift left one byte from left to result */
6997 /*-----------------------------------------------------------------*/
6999 shiftL1Left2Result (operand * left, int offl,
7000 operand * result, int offr, int shCount)
7002 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7003 /* shift left accumulator */
7005 aopPut (AOP (result), "a", offr);
7009 #ifdef BETTER_LITERAL_SHIFT
7010 /*-----------------------------------------------------------------*/
7011 /* movLeft2Result - move byte from left to result */
7012 /*-----------------------------------------------------------------*/
7014 movLeft2Result (operand * left, int offl,
7015 operand * result, int offr, int sign)
7018 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7020 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
7022 if (*l == '@' && (IS_AOP_PREG (result)))
7024 emitcode ("mov", "a,%s", l);
7025 aopPut (AOP (result), "a", offr);
7031 aopPut (AOP (result), l, offr);
7035 /* MSB sign in acc.7 ! */
7036 if (getDataSize (left) == offl + 1)
7038 emitcode ("mov", "a,%s", l);
7039 aopPut (AOP (result), "a", offr);
7047 #ifdef BETTER_LITERAL_SHIFT
7048 /*-----------------------------------------------------------------*/
7049 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7050 /*-----------------------------------------------------------------*/
7054 emitcode ("rrc", "a");
7055 emitcode ("xch", "a,%s", x);
7056 emitcode ("rrc", "a");
7057 emitcode ("xch", "a,%s", x);
7061 #ifdef BETTER_LITERAL_SHIFT
7063 /*-----------------------------------------------------------------*/
7064 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7065 /*-----------------------------------------------------------------*/
7069 emitcode ("xch", "a,%s", x);
7070 emitcode ("rlc", "a");
7071 emitcode ("xch", "a,%s", x);
7072 emitcode ("rlc", "a");
7076 #ifdef BETTER_LITERAL_SHIFT
7077 /*-----------------------------------------------------------------*/
7078 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7079 /*-----------------------------------------------------------------*/
7083 emitcode ("xch", "a,%s", x);
7084 emitcode ("add", "a,acc");
7085 emitcode ("xch", "a,%s", x);
7086 emitcode ("rlc", "a");
7090 #ifdef BETTER_LITERAL_SHIFT
7091 /*-----------------------------------------------------------------*/
7092 /* AccAXLsh - left shift a:x by known count (0..7) */
7093 /*-----------------------------------------------------------------*/
7095 AccAXLsh (char *x, int shCount)
7110 case 5: // AAAAABBB:CCCCCDDD
7112 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7114 emitcode ("anl", "a,#0x%02x",
7115 SLMask[shCount]); // BBB00000:CCCCCDDD
7117 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7119 AccRol (shCount); // DDDCCCCC:BBB00000
7121 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7123 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7125 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7127 emitcode ("anl", "a,#0x%02x",
7128 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7130 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7132 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7135 case 6: // AAAAAABB:CCCCCCDD
7136 emitcode ("anl", "a,#0x%02x",
7137 SRMask[shCount]); // 000000BB:CCCCCCDD
7138 emitcode ("mov", "c,acc.0"); // c = B
7139 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7141 AccAXRrl1 (x); // BCCCCCCD:D000000B
7142 AccAXRrl1 (x); // BBCCCCCC:DD000000
7144 emitcode("rrc","a");
7145 emitcode("xch","a,%s", x);
7146 emitcode("rrc","a");
7147 emitcode("mov","c,acc.0"); //<< get correct bit
7148 emitcode("xch","a,%s", x);
7150 emitcode("rrc","a");
7151 emitcode("xch","a,%s", x);
7152 emitcode("rrc","a");
7153 emitcode("xch","a,%s", x);
7156 case 7: // a:x <<= 7
7158 emitcode ("anl", "a,#0x%02x",
7159 SRMask[shCount]); // 0000000B:CCCCCCCD
7161 emitcode ("mov", "c,acc.0"); // c = B
7163 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7165 AccAXRrl1 (x); // BCCCCCCC:D0000000
7174 #ifdef BETTER_LITERAL_SHIFT
7176 /*-----------------------------------------------------------------*/
7177 /* AccAXRsh - right shift a:x known count (0..7) */
7178 /*-----------------------------------------------------------------*/
7180 AccAXRsh (char *x, int shCount)
7188 AccAXRrl1 (x); // 0->a:x
7193 AccAXRrl1 (x); // 0->a:x
7196 AccAXRrl1 (x); // 0->a:x
7201 case 5: // AAAAABBB:CCCCCDDD = a:x
7203 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7205 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7207 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7209 emitcode ("anl", "a,#0x%02x",
7210 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7212 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7214 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7216 emitcode ("anl", "a,#0x%02x",
7217 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7219 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7221 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7223 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7226 case 6: // AABBBBBB:CCDDDDDD
7228 emitcode ("mov", "c,acc.7");
7229 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7231 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7233 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7235 emitcode ("anl", "a,#0x%02x",
7236 SRMask[shCount]); // 000000AA:BBBBBBCC
7239 case 7: // ABBBBBBB:CDDDDDDD
7241 emitcode ("mov", "c,acc.7"); // c = A
7243 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7245 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7247 emitcode ("anl", "a,#0x%02x",
7248 SRMask[shCount]); // 0000000A:BBBBBBBC
7257 #ifdef BETTER_LITERAL_SHIFT
7258 /*-----------------------------------------------------------------*/
7259 /* AccAXRshS - right shift signed a:x known count (0..7) */
7260 /*-----------------------------------------------------------------*/
7262 AccAXRshS (char *x, int shCount)
7270 emitcode ("mov", "c,acc.7");
7271 AccAXRrl1 (x); // s->a:x
7275 emitcode ("mov", "c,acc.7");
7276 AccAXRrl1 (x); // s->a:x
7278 emitcode ("mov", "c,acc.7");
7279 AccAXRrl1 (x); // s->a:x
7284 case 5: // AAAAABBB:CCCCCDDD = a:x
7286 tlbl = newiTempLabel (NULL);
7287 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7289 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7291 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7293 emitcode ("anl", "a,#0x%02x",
7294 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7296 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7298 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7300 emitcode ("anl", "a,#0x%02x",
7301 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7303 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7305 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7307 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7309 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7310 emitcode ("orl", "a,#0x%02x",
7311 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7313 emitcode ("", "%05d$:", tlbl->key + 100);
7314 break; // SSSSAAAA:BBBCCCCC
7316 case 6: // AABBBBBB:CCDDDDDD
7318 tlbl = newiTempLabel (NULL);
7319 emitcode ("mov", "c,acc.7");
7320 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7322 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7324 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7326 emitcode ("anl", "a,#0x%02x",
7327 SRMask[shCount]); // 000000AA:BBBBBBCC
7329 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7330 emitcode ("orl", "a,#0x%02x",
7331 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7333 emitcode ("", "%05d$:", tlbl->key + 100);
7335 case 7: // ABBBBBBB:CDDDDDDD
7337 tlbl = newiTempLabel (NULL);
7338 emitcode ("mov", "c,acc.7"); // c = A
7340 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7342 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7344 emitcode ("anl", "a,#0x%02x",
7345 SRMask[shCount]); // 0000000A:BBBBBBBC
7347 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7348 emitcode ("orl", "a,#0x%02x",
7349 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7351 emitcode ("", "%05d$:", tlbl->key + 100);
7359 #ifdef BETTER_LITERAL_SHIFT
7361 _loadLeftIntoAx(char **lsb,
7367 // Get the initial value from left into a pair of registers.
7368 // MSB must be in A, LSB can be any register.
7370 // If the result is held in registers, it is an optimization
7371 // if the LSB can be held in the register which will hold the,
7372 // result LSB since this saves us from having to copy it into
7373 // the result following AccAXLsh.
7375 // If the result is addressed indirectly, this is not a gain.
7376 if (AOP_NEEDSACC(result))
7380 _startLazyDPSEvaluation();
7381 if (AOP_TYPE(left) == AOP_DPTR2)
7384 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7385 // get LSB in DP2_RESULT_REG.
7386 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7387 assert(!strcmp(leftByte, DP2_RESULT_REG));
7391 // get LSB into DP2_RESULT_REG
7392 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7393 if (strcmp(leftByte, DP2_RESULT_REG))
7396 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7399 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7400 assert(strcmp(leftByte, DP2_RESULT_REG));
7403 _endLazyDPSEvaluation();
7404 *lsb = DP2_RESULT_REG;
7408 if (sameRegs (AOP (result), AOP (left)) &&
7409 ((offl + MSB16) == offr))
7411 /* don't crash result[offr] */
7412 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7413 emitcode ("xch", "a,%s",
7414 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7418 movLeft2Result (left, offl, result, offr, 0);
7419 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7421 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7422 assert(strcmp(*lsb,"a"));
7427 _storeAxResults(char *lsb,
7431 _startLazyDPSEvaluation();
7432 if (AOP_NEEDSACC(result))
7434 /* We have to explicitly update the result LSB.
7436 emitcode("xch","a,%s", lsb);
7437 aopPut(AOP(result), "a", offr);
7438 emitcode("mov","a,%s", lsb);
7440 if (getDataSize (result) > 1)
7442 aopPut (AOP (result), "a", offr + MSB16);
7444 _endLazyDPSEvaluation();
7447 /*-----------------------------------------------------------------*/
7448 /* shiftL2Left2Result - shift left two bytes from left to result */
7449 /*-----------------------------------------------------------------*/
7451 shiftL2Left2Result (operand * left, int offl,
7452 operand * result, int offr, int shCount)
7456 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7458 AccAXLsh (lsb, shCount);
7460 _storeAxResults(lsb, result, offr);
7464 #ifdef BETTER_LITERAL_SHIFT
7465 /*-----------------------------------------------------------------*/
7466 /* shiftR2Left2Result - shift right two bytes from left to result */
7467 /*-----------------------------------------------------------------*/
7469 shiftR2Left2Result (operand * left, int offl,
7470 operand * result, int offr,
7471 int shCount, int sign)
7475 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7477 /* a:x >> shCount (x = lsb(result)) */
7480 AccAXRshS(lsb, shCount);
7484 AccAXRsh(lsb, shCount);
7487 _storeAxResults(lsb, result, offr);
7493 /*-----------------------------------------------------------------*/
7494 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7495 /*-----------------------------------------------------------------*/
7497 shiftLLeftOrResult (operand * left, int offl,
7498 operand * result, int offr, int shCount)
7500 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7501 /* shift left accumulator */
7503 /* or with result */
7504 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7505 /* back to result */
7506 aopPut (AOP (result), "a", offr);
7512 /*-----------------------------------------------------------------*/
7513 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7514 /*-----------------------------------------------------------------*/
7516 shiftRLeftOrResult (operand * left, int offl,
7517 operand * result, int offr, int shCount)
7519 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7520 /* shift right accumulator */
7522 /* or with result */
7523 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7524 /* back to result */
7525 aopPut (AOP (result), "a", offr);
7529 #ifdef BETTER_LITERAL_SHIFT
7530 /*-----------------------------------------------------------------*/
7531 /* genlshOne - left shift a one byte quantity by known count */
7532 /*-----------------------------------------------------------------*/
7534 genlshOne (operand * result, operand * left, int shCount)
7536 D (emitcode (";", "genlshOne "););
7537 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7541 #ifdef BETTER_LITERAL_SHIFT
7542 /*-----------------------------------------------------------------*/
7543 /* genlshTwo - left shift two bytes by known amount != 0 */
7544 /*-----------------------------------------------------------------*/
7546 genlshTwo (operand * result, operand * left, int shCount)
7550 D (emitcode (";", "genlshTwo "););
7552 size = getDataSize (result);
7554 /* if shCount >= 8 */
7559 _startLazyDPSEvaluation();
7565 _endLazyDPSEvaluation();
7566 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7567 aopPut (AOP (result), zero, LSB);
7571 movLeft2Result (left, LSB, result, MSB16, 0);
7572 aopPut (AOP (result), zero, LSB);
7573 _endLazyDPSEvaluation();
7578 aopPut (AOP (result), zero, LSB);
7579 _endLazyDPSEvaluation();
7583 /* 1 <= shCount <= 7 */
7588 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7592 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7600 /*-----------------------------------------------------------------*/
7601 /* shiftLLong - shift left one long from left to result */
7602 /* offl = LSB or MSB16 */
7603 /*-----------------------------------------------------------------*/
7605 shiftLLong (operand * left, operand * result, int offr)
7608 int size = AOP_SIZE (result);
7610 if (size >= LSB + offr)
7612 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7614 emitcode ("add", "a,acc");
7615 if (sameRegs (AOP (left), AOP (result)) &&
7616 size >= MSB16 + offr && offr != LSB)
7617 emitcode ("xch", "a,%s",
7618 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7620 aopPut (AOP (result), "a", LSB + offr);
7623 if (size >= MSB16 + offr)
7625 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7627 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7630 emitcode ("rlc", "a");
7631 if (sameRegs (AOP (left), AOP (result)) &&
7632 size >= MSB24 + offr && offr != LSB)
7633 emitcode ("xch", "a,%s",
7634 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7636 aopPut (AOP (result), "a", MSB16 + offr);
7639 if (size >= MSB24 + offr)
7641 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7643 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7646 emitcode ("rlc", "a");
7647 if (sameRegs (AOP (left), AOP (result)) &&
7648 size >= MSB32 + offr && offr != LSB)
7649 emitcode ("xch", "a,%s",
7650 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7652 aopPut (AOP (result), "a", MSB24 + offr);
7655 if (size > MSB32 + offr)
7657 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7659 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7662 emitcode ("rlc", "a");
7663 aopPut (AOP (result), "a", MSB32 + offr);
7666 aopPut (AOP (result), zero, LSB);
7672 /*-----------------------------------------------------------------*/
7673 /* genlshFour - shift four byte by a known amount != 0 */
7674 /*-----------------------------------------------------------------*/
7676 genlshFour (operand * result, operand * left, int shCount)
7680 D (emitcode (";", "genlshFour ");
7683 size = AOP_SIZE (result);
7685 /* if shifting more that 3 bytes */
7690 /* lowest order of left goes to the highest
7691 order of the destination */
7692 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7694 movLeft2Result (left, LSB, result, MSB32, 0);
7695 aopPut (AOP (result), zero, LSB);
7696 aopPut (AOP (result), zero, MSB16);
7697 aopPut (AOP (result), zero, MSB24);
7701 /* more than two bytes */
7702 else if (shCount >= 16)
7704 /* lower order two bytes goes to higher order two bytes */
7706 /* if some more remaining */
7708 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7711 movLeft2Result (left, MSB16, result, MSB32, 0);
7712 movLeft2Result (left, LSB, result, MSB24, 0);
7714 aopPut (AOP (result), zero, MSB16);
7715 aopPut (AOP (result), zero, LSB);
7719 /* if more than 1 byte */
7720 else if (shCount >= 8)
7722 /* lower order three bytes goes to higher order three bytes */
7727 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7729 movLeft2Result (left, LSB, result, MSB16, 0);
7735 movLeft2Result (left, MSB24, result, MSB32, 0);
7736 movLeft2Result (left, MSB16, result, MSB24, 0);
7737 movLeft2Result (left, LSB, result, MSB16, 0);
7738 aopPut (AOP (result), zero, LSB);
7740 else if (shCount == 1)
7741 shiftLLong (left, result, MSB16);
7744 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7745 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7746 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7747 aopPut (AOP (result), zero, LSB);
7752 /* 1 <= shCount <= 7 */
7753 else if (shCount <= 2)
7755 shiftLLong (left, result, LSB);
7757 shiftLLong (result, result, LSB);
7759 /* 3 <= shCount <= 7, optimize */
7762 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7763 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7764 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7769 #ifdef BETTER_LITERAL_SHIFT
7770 /*-----------------------------------------------------------------*/
7771 /* genLeftShiftLiteral - left shifting by known count */
7772 /*-----------------------------------------------------------------*/
7774 genLeftShiftLiteral (operand * left,
7779 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7782 size = getSize (operandType (result));
7784 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7786 /* We only handle certain easy cases so far. */
7788 && (shCount < (size * 8))
7792 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7796 freeAsmop (right, NULL, ic, TRUE);
7798 aopOp(left, ic, FALSE, FALSE);
7799 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7802 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7804 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7805 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7807 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7810 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7812 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7813 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7815 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7821 emitcode ("; shift left ", "result %d, left %d", size,
7825 /* I suppose that the left size >= result size */
7828 _startLazyDPSEvaluation();
7831 movLeft2Result (left, size, result, size, 0);
7833 _endLazyDPSEvaluation();
7835 else if (shCount >= (size * 8))
7837 _startLazyDPSEvaluation();
7840 aopPut (AOP (result), zero, size);
7842 _endLazyDPSEvaluation();
7849 genlshOne (result, left, shCount);
7853 genlshTwo (result, left, shCount);
7857 genlshFour (result, left, shCount);
7861 fprintf(stderr, "*** ack! mystery literal shift!\n");
7865 freeAsmop (left, NULL, ic, TRUE);
7866 freeAsmop (result, NULL, ic, TRUE);
7871 /*-----------------------------------------------------------------*/
7872 /* genLeftShift - generates code for left shifting */
7873 /*-----------------------------------------------------------------*/
7875 genLeftShift (iCode * ic)
7877 operand *left, *right, *result;
7880 symbol *tlbl, *tlbl1;
7882 D (emitcode (";", "genLeftShift "););
7884 right = IC_RIGHT (ic);
7885 left = IC_LEFT (ic);
7886 result = IC_RESULT (ic);
7888 aopOp (right, ic, FALSE, FALSE);
7891 #ifdef BETTER_LITERAL_SHIFT
7892 /* if the shift count is known then do it
7893 as efficiently as possible */
7894 if (AOP_TYPE (right) == AOP_LIT)
7896 if (genLeftShiftLiteral (left, right, result, ic))
7903 /* shift count is unknown then we have to form
7904 a loop get the loop count in B : Note: we take
7905 only the lower order byte since shifting
7906 more that 32 bits make no sense anyway, ( the
7907 largest size of an object can be only 32 bits ) */
7909 if (AOP_TYPE (right) == AOP_LIT)
7911 /* Really should be handled by genLeftShiftLiteral,
7912 * but since I'm too lazy to fix that today, at least we can make
7913 * some small improvement.
7915 emitcode("mov", "b,#0x%02x",
7916 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7920 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7921 emitcode ("inc", "b");
7923 freeAsmop (right, NULL, ic, TRUE);
7924 aopOp (left, ic, FALSE, FALSE);
7925 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7927 /* now move the left to the result if they are not the
7929 if (!sameRegs (AOP (left), AOP (result)) &&
7930 AOP_SIZE (result) > 1)
7933 size = AOP_SIZE (result);
7935 _startLazyDPSEvaluation ();
7938 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7939 if (*l == '@' && (IS_AOP_PREG (result)))
7942 emitcode ("mov", "a,%s", l);
7943 aopPut (AOP (result), "a", offset);
7946 aopPut (AOP (result), l, offset);
7949 _endLazyDPSEvaluation ();
7952 tlbl = newiTempLabel (NULL);
7953 size = AOP_SIZE (result);
7955 tlbl1 = newiTempLabel (NULL);
7957 /* if it is only one byte then */
7960 symbol *tlbl1 = newiTempLabel (NULL);
7962 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7964 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7965 emitcode ("", "%05d$:", tlbl->key + 100);
7966 emitcode ("add", "a,acc");
7967 emitcode ("", "%05d$:", tlbl1->key + 100);
7968 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7969 aopPut (AOP (result), "a", 0);
7973 reAdjustPreg (AOP (result));
7975 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7976 emitcode ("", "%05d$:", tlbl->key + 100);
7977 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7979 emitcode ("add", "a,acc");
7980 aopPut (AOP (result), "a", offset++);
7981 _startLazyDPSEvaluation ();
7984 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7986 emitcode ("rlc", "a");
7987 aopPut (AOP (result), "a", offset++);
7989 _endLazyDPSEvaluation ();
7990 reAdjustPreg (AOP (result));
7992 emitcode ("", "%05d$:", tlbl1->key + 100);
7993 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7995 freeAsmop (left, NULL, ic, TRUE);
7996 freeAsmop (result, NULL, ic, TRUE);
7999 #ifdef BETTER_LITERAL_SHIFT
8000 /*-----------------------------------------------------------------*/
8001 /* genrshOne - right shift a one byte quantity by known count */
8002 /*-----------------------------------------------------------------*/
8004 genrshOne (operand * result, operand * left,
8005 int shCount, int sign)
8007 D (emitcode (";", "genrshOne"););
8008 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8012 #ifdef BETTER_LITERAL_SHIFT
8013 /*-----------------------------------------------------------------*/
8014 /* genrshTwo - right shift two bytes by known amount != 0 */
8015 /*-----------------------------------------------------------------*/
8017 genrshTwo (operand * result, operand * left,
8018 int shCount, int sign)
8020 D (emitcode (";", "genrshTwo"););
8022 /* if shCount >= 8 */
8026 _startLazyDPSEvaluation();
8029 shiftR1Left2Result (left, MSB16, result, LSB,
8034 movLeft2Result (left, MSB16, result, LSB, sign);
8036 addSign (result, MSB16, sign);
8037 _endLazyDPSEvaluation();
8040 /* 1 <= shCount <= 7 */
8043 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8050 /*-----------------------------------------------------------------*/
8051 /* shiftRLong - shift right one long from left to result */
8052 /* offl = LSB or MSB16 */
8053 /*-----------------------------------------------------------------*/
8055 shiftRLong (operand * left, int offl,
8056 operand * result, int sign)
8058 int isSameRegs=sameRegs(AOP(left),AOP(result));
8060 if (isSameRegs && offl>1) {
8061 // we are in big trouble, but this shouldn't happen
8062 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8065 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
8070 emitcode ("rlc", "a");
8071 emitcode ("subb", "a,acc");
8072 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
8074 aopPut (AOP(result), zero, MSB32);
8079 emitcode ("clr", "c");
8081 emitcode ("mov", "c,acc.7");
8084 emitcode ("rrc", "a");
8086 if (isSameRegs && offl==MSB16) {
8087 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
8089 aopPut (AOP (result), "a", MSB32);
8090 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
8093 emitcode ("rrc", "a");
8094 if (isSameRegs && offl==1) {
8095 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
8097 aopPut (AOP (result), "a", MSB24);
8098 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
8100 emitcode ("rrc", "a");
8101 aopPut (AOP (result), "a", MSB16 - offl);
8105 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
8106 emitcode ("rrc", "a");
8107 aopPut (AOP (result), "a", LSB);
8114 /*-----------------------------------------------------------------*/
8115 /* genrshFour - shift four byte by a known amount != 0 */
8116 /*-----------------------------------------------------------------*/
8118 genrshFour (operand * result, operand * left,
8119 int shCount, int sign)
8121 D (emitcode (";", "genrshFour");
8124 /* if shifting more that 3 bytes */
8129 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8131 movLeft2Result (left, MSB32, result, LSB, sign);
8132 addSign (result, MSB16, sign);
8134 else if (shCount >= 16)
8138 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8141 movLeft2Result (left, MSB24, result, LSB, 0);
8142 movLeft2Result (left, MSB32, result, MSB16, sign);
8144 addSign (result, MSB24, sign);
8146 else if (shCount >= 8)
8150 shiftRLong (left, MSB16, result, sign);
8151 else if (shCount == 0)
8153 movLeft2Result (left, MSB16, result, LSB, 0);
8154 movLeft2Result (left, MSB24, result, MSB16, 0);
8155 movLeft2Result (left, MSB32, result, MSB24, sign);
8156 addSign (result, MSB32, sign);
8160 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8161 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8162 /* the last shift is signed */
8163 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8164 addSign (result, MSB32, sign);
8168 { /* 1 <= shCount <= 7 */
8171 shiftRLong (left, LSB, result, sign);
8173 shiftRLong (result, LSB, result, sign);
8177 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8178 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8179 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8185 #ifdef BETTER_LITERAL_SHIFT
8186 /*-----------------------------------------------------------------*/
8187 /* genRightShiftLiteral - right shifting by known count */
8188 /*-----------------------------------------------------------------*/
8190 genRightShiftLiteral (operand * left,
8196 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8199 size = getSize (operandType (result));
8201 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8203 /* We only handle certain easy cases so far. */
8205 && (shCount < (size * 8))
8209 D(emitcode (";", "genRightShiftLiteral wimping out"););
8213 freeAsmop (right, NULL, ic, TRUE);
8215 aopOp (left, ic, FALSE, FALSE);
8216 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8219 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8223 /* test the LEFT size !!! */
8225 /* I suppose that the left size >= result size */
8228 size = getDataSize (result);
8229 _startLazyDPSEvaluation();
8232 movLeft2Result (left, size, result, size, 0);
8234 _endLazyDPSEvaluation();
8236 else if (shCount >= (size * 8))
8240 /* get sign in acc.7 */
8241 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8243 addSign (result, LSB, sign);
8250 genrshOne (result, left, shCount, sign);
8254 genrshTwo (result, left, shCount, sign);
8258 genrshFour (result, left, shCount, sign);
8265 freeAsmop (left, NULL, ic, TRUE);
8266 freeAsmop (result, NULL, ic, TRUE);
8272 /*-----------------------------------------------------------------*/
8273 /* genSignedRightShift - right shift of signed number */
8274 /*-----------------------------------------------------------------*/
8276 genSignedRightShift (iCode * ic)
8278 operand *right, *left, *result;
8281 symbol *tlbl, *tlbl1;
8283 D (emitcode (";", "genSignedRightShift "););
8285 /* we do it the hard way put the shift count in b
8286 and loop thru preserving the sign */
8288 right = IC_RIGHT (ic);
8289 left = IC_LEFT (ic);
8290 result = IC_RESULT (ic);
8292 aopOp (right, ic, FALSE, FALSE);
8294 #ifdef BETTER_LITERAL_SHIFT
8295 if (AOP_TYPE (right) == AOP_LIT)
8297 if (genRightShiftLiteral (left, right, result, ic, 1))
8303 /* shift count is unknown then we have to form
8304 a loop get the loop count in B : Note: we take
8305 only the lower order byte since shifting
8306 more that 32 bits make no sense anyway, ( the
8307 largest size of an object can be only 32 bits ) */
8309 if (AOP_TYPE (right) == AOP_LIT)
8311 /* Really should be handled by genRightShiftLiteral,
8312 * but since I'm too lazy to fix that today, at least we can make
8313 * some small improvement.
8315 emitcode("mov", "b,#0x%02x",
8316 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8320 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8321 emitcode ("inc", "b");
8323 freeAsmop (right, NULL, ic, TRUE);
8324 aopOp (left, ic, FALSE, FALSE);
8325 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8327 /* now move the left to the result if they are not the
8329 if (!sameRegs (AOP (left), AOP (result)) &&
8330 AOP_SIZE (result) > 1)
8333 size = AOP_SIZE (result);
8335 _startLazyDPSEvaluation ();
8338 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8339 if (*l == '@' && IS_AOP_PREG (result))
8342 emitcode ("mov", "a,%s", l);
8343 aopPut (AOP (result), "a", offset);
8346 aopPut (AOP (result), l, offset);
8349 _endLazyDPSEvaluation ();
8352 /* mov the highest order bit to OVR */
8353 tlbl = newiTempLabel (NULL);
8354 tlbl1 = newiTempLabel (NULL);
8356 size = AOP_SIZE (result);
8358 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8359 emitcode ("rlc", "a");
8360 emitcode ("mov", "ov,c");
8361 /* if it is only one byte then */
8364 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8366 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8367 emitcode ("", "%05d$:", tlbl->key + 100);
8368 emitcode ("mov", "c,ov");
8369 emitcode ("rrc", "a");
8370 emitcode ("", "%05d$:", tlbl1->key + 100);
8371 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8372 aopPut (AOP (result), "a", 0);
8376 reAdjustPreg (AOP (result));
8377 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8378 emitcode ("", "%05d$:", tlbl->key + 100);
8379 emitcode ("mov", "c,ov");
8380 _startLazyDPSEvaluation ();
8383 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8385 emitcode ("rrc", "a");
8386 aopPut (AOP (result), "a", offset--);
8388 _endLazyDPSEvaluation ();
8389 reAdjustPreg (AOP (result));
8390 emitcode ("", "%05d$:", tlbl1->key + 100);
8391 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8394 freeAsmop (left, NULL, ic, TRUE);
8395 freeAsmop (result, NULL, ic, TRUE);
8398 /*-----------------------------------------------------------------*/
8399 /* genRightShift - generate code for right shifting */
8400 /*-----------------------------------------------------------------*/
8402 genRightShift (iCode * ic)
8404 operand *right, *left, *result;
8408 symbol *tlbl, *tlbl1;
8410 D (emitcode (";", "genRightShift "););
8412 /* if signed then we do it the hard way preserve the
8413 sign bit moving it inwards */
8414 retype = getSpec (operandType (IC_RESULT (ic)));
8416 if (!SPEC_USIGN (retype))
8418 genSignedRightShift (ic);
8422 /* signed & unsigned types are treated the same : i.e. the
8423 signed is NOT propagated inwards : quoting from the
8424 ANSI - standard : "for E1 >> E2, is equivalent to division
8425 by 2**E2 if unsigned or if it has a non-negative value,
8426 otherwise the result is implementation defined ", MY definition
8427 is that the sign does not get propagated */
8429 right = IC_RIGHT (ic);
8430 left = IC_LEFT (ic);
8431 result = IC_RESULT (ic);
8433 aopOp (right, ic, FALSE, FALSE);
8435 #ifdef BETTER_LITERAL_SHIFT
8436 /* if the shift count is known then do it
8437 as efficiently as possible */
8438 if (AOP_TYPE (right) == AOP_LIT)
8440 if (genRightShiftLiteral (left, right, result, ic, 0))
8447 /* shift count is unknown then we have to form
8448 a loop get the loop count in B : Note: we take
8449 only the lower order byte since shifting
8450 more that 32 bits make no sense anyway, ( the
8451 largest size of an object can be only 32 bits ) */
8453 if (AOP_TYPE (right) == AOP_LIT)
8455 /* Really should be handled by genRightShiftLiteral,
8456 * but since I'm too lazy to fix that today, at least we can make
8457 * some small improvement.
8459 emitcode("mov", "b,#0x%02x",
8460 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8464 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8465 emitcode ("inc", "b");
8467 freeAsmop (right, NULL, ic, TRUE);
8468 aopOp (left, ic, FALSE, FALSE);
8469 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8471 /* now move the left to the result if they are not the
8473 if (!sameRegs (AOP (left), AOP (result)) &&
8474 AOP_SIZE (result) > 1)
8477 size = AOP_SIZE (result);
8479 _startLazyDPSEvaluation ();
8482 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8483 if (*l == '@' && IS_AOP_PREG (result))
8486 emitcode ("mov", "a,%s", l);
8487 aopPut (AOP (result), "a", offset);
8490 aopPut (AOP (result), l, offset);
8493 _endLazyDPSEvaluation ();
8496 tlbl = newiTempLabel (NULL);
8497 tlbl1 = newiTempLabel (NULL);
8498 size = AOP_SIZE (result);
8501 /* if it is only one byte then */
8504 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8506 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8507 emitcode ("", "%05d$:", tlbl->key + 100);
8509 emitcode ("rrc", "a");
8510 emitcode ("", "%05d$:", tlbl1->key + 100);
8511 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8512 aopPut (AOP (result), "a", 0);
8516 reAdjustPreg (AOP (result));
8517 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8518 emitcode ("", "%05d$:", tlbl->key + 100);
8520 _startLazyDPSEvaluation ();
8523 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8525 emitcode ("rrc", "a");
8526 aopPut (AOP (result), "a", offset--);
8528 _endLazyDPSEvaluation ();
8529 reAdjustPreg (AOP (result));
8531 emitcode ("", "%05d$:", tlbl1->key + 100);
8532 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8535 freeAsmop (left, NULL, ic, TRUE);
8536 freeAsmop (result, NULL, ic, TRUE);
8539 /*-----------------------------------------------------------------*/
8540 /* genUnpackBits - generates code for unpacking bits */
8541 /*-----------------------------------------------------------------*/
8543 genUnpackBits (operand * result, char *rname, int ptype)
8550 D (emitcode (";", "genUnpackBits ");
8553 etype = getSpec (operandType (result));
8555 /* read the first byte */
8561 emitcode ("mov", "a,@%s", rname);
8565 emitcode ("movx", "a,@%s", rname);
8569 emitcode ("movx", "a,@dptr");
8573 emitcode ("clr", "a");
8574 emitcode ("movc", "a,@a+dptr");
8578 emitcode ("lcall", "__gptrget");
8582 /* if we have bitdisplacement then it fits */
8583 /* into this byte completely or if length is */
8584 /* less than a byte */
8585 if ((shCnt = SPEC_BSTR (etype)) ||
8586 (SPEC_BLEN (etype) <= 8))
8589 /* shift right acc */
8592 emitcode ("anl", "a,#0x%02x",
8593 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8594 aopPut (AOP (result), "a", offset);
8598 /* bit field did not fit in a byte */
8599 rlen = SPEC_BLEN (etype) - 8;
8600 aopPut (AOP (result), "a", offset++);
8609 emitcode ("inc", "%s", rname);
8610 emitcode ("mov", "a,@%s", rname);
8614 emitcode ("inc", "%s", rname);
8615 emitcode ("movx", "a,@%s", rname);
8619 emitcode ("inc", "dptr");
8620 emitcode ("movx", "a,@dptr");
8624 emitcode ("clr", "a");
8625 emitcode ("inc", "dptr");
8626 emitcode ("movc", "a,@a+dptr");
8630 emitcode ("inc", "dptr");
8631 emitcode ("lcall", "__gptrget");
8636 /* if we are done */
8640 aopPut (AOP (result), "a", offset++);
8646 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
8647 aopPut (AOP (result), "a", offset);
8654 /*-----------------------------------------------------------------*/
8655 /* genDataPointerGet - generates code when ptr offset is known */
8656 /*-----------------------------------------------------------------*/
8658 genDataPointerGet (operand * left,
8664 int size, offset = 0;
8665 aopOp (result, ic, TRUE, FALSE);
8667 /* get the string representation of the name */
8668 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8669 size = AOP_SIZE (result);
8670 _startLazyDPSEvaluation ();
8674 sprintf (buffer, "(%s + %d)", l + 1, offset);
8676 sprintf (buffer, "%s", l + 1);
8677 aopPut (AOP (result), buffer, offset++);
8679 _endLazyDPSEvaluation ();
8681 freeAsmop (left, NULL, ic, TRUE);
8682 freeAsmop (result, NULL, ic, TRUE);
8685 /*-----------------------------------------------------------------*/
8686 /* genNearPointerGet - emitcode for near pointer fetch */
8687 /*-----------------------------------------------------------------*/
8689 genNearPointerGet (operand * left,
8697 sym_link *rtype, *retype, *letype;
8698 sym_link *ltype = operandType (left);
8701 rtype = operandType (result);
8702 retype = getSpec (rtype);
8703 letype = getSpec (ltype);
8705 aopOp (left, ic, FALSE, FALSE);
8707 /* if left is rematerialisable and
8708 result is not bit variable type and
8709 the left is pointer to data space i.e
8710 lower 128 bytes of space */
8711 if (AOP_TYPE (left) == AOP_IMMD &&
8712 !IS_BITVAR (retype) &&
8713 !IS_BITVAR (letype) &&
8714 DCL_TYPE (ltype) == POINTER)
8716 genDataPointerGet (left, result, ic);
8720 /* if the value is already in a pointer register
8721 then don't need anything more */
8722 if (!AOP_INPREG (AOP (left)))
8724 /* otherwise get a free pointer register */
8726 preg = getFreePtr (ic, &aop, FALSE);
8727 emitcode ("mov", "%s,%s",
8729 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8733 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8735 freeAsmop (left, NULL, ic, TRUE);
8736 aopOp (result, ic, FALSE, FALSE);
8738 /* if bitfield then unpack the bits */
8739 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8740 genUnpackBits (result, rname, POINTER);
8743 /* we have can just get the values */
8744 int size = AOP_SIZE (result);
8749 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8752 emitcode ("mov", "a,@%s", rname);
8753 aopPut (AOP (result), "a", offset);
8757 sprintf (buffer, "@%s", rname);
8758 aopPut (AOP (result), buffer, offset);
8762 emitcode ("inc", "%s", rname);
8766 /* now some housekeeping stuff */
8769 /* we had to allocate for this iCode */
8770 if (pi) { /* post increment present */
8771 aopPut(AOP ( left ),rname,0);
8773 freeAsmop (NULL, aop, ic, TRUE);
8777 /* we did not allocate which means left
8778 already in a pointer register, then
8779 if size > 0 && this could be used again
8780 we have to point it back to where it
8782 if (AOP_SIZE (result) > 1 &&
8783 !OP_SYMBOL (left)->remat &&
8784 (OP_SYMBOL (left)->liveTo > ic->seq ||
8788 int size = AOP_SIZE (result) - 1;
8790 emitcode ("dec", "%s", rname);
8795 freeAsmop (result, NULL, ic, TRUE);
8796 if (pi) pi->generated = 1;
8799 /*-----------------------------------------------------------------*/
8800 /* genPagedPointerGet - emitcode for paged pointer fetch */
8801 /*-----------------------------------------------------------------*/
8803 genPagedPointerGet (operand * left,
8811 sym_link *rtype, *retype, *letype;
8813 rtype = operandType (result);
8814 retype = getSpec (rtype);
8815 letype = getSpec (operandType (left));
8816 aopOp (left, ic, FALSE, FALSE);
8818 /* if the value is already in a pointer register
8819 then don't need anything more */
8820 if (!AOP_INPREG (AOP (left)))
8822 /* otherwise get a free pointer register */
8824 preg = getFreePtr (ic, &aop, FALSE);
8825 emitcode ("mov", "%s,%s",
8827 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8831 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8833 freeAsmop (left, NULL, ic, TRUE);
8834 aopOp (result, ic, FALSE, FALSE);
8836 /* if bitfield then unpack the bits */
8837 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8838 genUnpackBits (result, rname, PPOINTER);
8841 /* we have can just get the values */
8842 int size = AOP_SIZE (result);
8848 emitcode ("movx", "a,@%s", rname);
8849 aopPut (AOP (result), "a", offset);
8854 emitcode ("inc", "%s", rname);
8858 /* now some housekeeping stuff */
8861 /* we had to allocate for this iCode */
8862 if (pi) aopPut ( AOP (left), rname, 0);
8863 freeAsmop (NULL, aop, ic, TRUE);
8867 /* we did not allocate which means left
8868 already in a pointer register, then
8869 if size > 0 && this could be used again
8870 we have to point it back to where it
8872 if (AOP_SIZE (result) > 1 &&
8873 !OP_SYMBOL (left)->remat &&
8874 (OP_SYMBOL (left)->liveTo > ic->seq ||
8878 int size = AOP_SIZE (result) - 1;
8880 emitcode ("dec", "%s", rname);
8885 freeAsmop (result, NULL, ic, TRUE);
8886 if (pi) pi->generated = 1;
8889 /*-----------------------------------------------------------------*/
8890 /* genFarPointerGet - gget value from far space */
8891 /*-----------------------------------------------------------------*/
8893 genFarPointerGet (operand * left,
8894 operand * result, iCode * ic, iCode *pi)
8896 int size, offset, dopi=1;
8897 sym_link *retype = getSpec (operandType (result));
8898 sym_link *letype = getSpec (operandType (left));
8899 D (emitcode (";", "genFarPointerGet");
8902 aopOp (left, ic, FALSE, FALSE);
8904 /* if the operand is already in dptr
8905 then we do nothing else we move the value to dptr */
8906 if (AOP_TYPE (left) != AOP_STR)
8908 /* if this is remateriazable */
8909 if (AOP_TYPE (left) == AOP_IMMD)
8911 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8915 /* we need to get it byte by byte */
8916 _startLazyDPSEvaluation ();
8917 if (AOP_TYPE (left) != AOP_DPTR)
8919 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8920 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8921 if (options.model == MODEL_FLAT24)
8922 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8926 /* We need to generate a load to DPTR indirect through DPTR. */
8927 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8929 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8930 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8931 if (options.model == MODEL_FLAT24)
8932 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8933 emitcode ("pop", "dph");
8934 emitcode ("pop", "dpl");
8937 _endLazyDPSEvaluation ();
8940 /* so dptr know contains the address */
8941 aopOp (result, ic, FALSE, TRUE);
8943 /* if bit then unpack */
8944 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8945 genUnpackBits (result, "dptr", FPOINTER);
8948 size = AOP_SIZE (result);
8951 _startLazyDPSEvaluation ();
8958 emitcode ("movx", "a,@dptr");
8959 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
8960 emitcode ("inc", "dptr");
8962 aopPut (AOP (result), "a", offset++);
8964 _endLazyDPSEvaluation ();
8966 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
8967 aopPut ( AOP (left), "dpl", 0);
8968 aopPut ( AOP (left), "dph", 1);
8969 if (options.model == MODEL_FLAT24)
8970 aopPut ( AOP (left), "dpx", 2);
8972 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
8973 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
8975 size = AOP_SIZE (result) - 1;
8976 while (size--) emitcode ("lcall","__decdptr");
8979 freeAsmop (left, NULL, ic, TRUE);
8980 freeAsmop (result, NULL, ic, TRUE);
8983 /*-----------------------------------------------------------------*/
8984 /* emitcodePointerGet - gget value from code space */
8985 /*-----------------------------------------------------------------*/
8987 emitcodePointerGet (operand * left,
8988 operand * result, iCode * ic, iCode *pi)
8990 int size, offset, dopi=1;
8991 sym_link *retype = getSpec (operandType (result));
8993 aopOp (left, ic, FALSE, FALSE);
8995 /* if the operand is already in dptr
8996 then we do nothing else we move the value to dptr */
8997 if (AOP_TYPE (left) != AOP_STR)
8999 /* if this is remateriazable */
9000 if (AOP_TYPE (left) == AOP_IMMD)
9002 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9005 { /* we need to get it byte by byte */
9006 _startLazyDPSEvaluation ();
9007 if (AOP_TYPE (left) != AOP_DPTR)
9009 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9010 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9011 if (options.model == MODEL_FLAT24)
9012 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9016 /* We need to generate a load to DPTR indirect through DPTR. */
9017 D (emitcode (";", "gencodePointerGet -- indirection special case.");
9019 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9020 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9021 if (options.model == MODEL_FLAT24)
9022 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9023 emitcode ("pop", "dph");
9024 emitcode ("pop", "dpl");
9027 _endLazyDPSEvaluation ();
9030 /* so dptr know contains the address */
9031 aopOp (result, ic, FALSE, TRUE);
9033 /* if bit then unpack */
9034 if (IS_BITVAR (retype))
9035 genUnpackBits (result, "dptr", CPOINTER);
9038 size = AOP_SIZE (result);
9041 _startLazyDPSEvaluation ();
9047 emitcode ("clr", "a");
9048 emitcode ("movc", "a,@a+dptr");
9049 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9050 emitcode ("inc", "dptr");
9051 aopPut (AOP (result), "a", offset++);
9053 _endLazyDPSEvaluation ();
9055 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9056 aopPut ( AOP (left), "dpl", 0);
9057 aopPut ( AOP (left), "dph", 1);
9058 if (options.model == MODEL_FLAT24)
9059 aopPut ( AOP (left), "dpx", 2);
9061 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9062 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9064 size = AOP_SIZE (result) - 1;
9065 while (size--) emitcode ("lcall","__decdptr");
9068 freeAsmop (left, NULL, ic, TRUE);
9069 freeAsmop (result, NULL, ic, TRUE);
9072 /*-----------------------------------------------------------------*/
9073 /* genGenPointerGet - gget value from generic pointer space */
9074 /*-----------------------------------------------------------------*/
9076 genGenPointerGet (operand * left,
9077 operand * result, iCode * ic, iCode * pi)
9080 sym_link *retype = getSpec (operandType (result));
9081 sym_link *letype = getSpec (operandType (left));
9083 D (emitcode (";", "genGenPointerGet "); );
9085 aopOp (left, ic, FALSE, (OP_SYMBOL(left)->ruonly ? FALSE : TRUE));
9087 /* if the operand is already in dptr
9088 then we do nothing else we move the value to dptr */
9089 if (AOP_TYPE (left) != AOP_STR)
9091 /* if this is remateriazable */
9092 if (AOP_TYPE (left) == AOP_IMMD)
9094 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9095 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9096 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
9098 emitcode ("mov", "b,#%d", pointerCode (retype));
9101 { /* we need to get it byte by byte */
9102 _startLazyDPSEvaluation ();
9103 if (AOP(left)->type==AOP_DPTR2) {
9105 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
9108 emitcode ("mov", "dpl,%s", l);
9109 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
9112 emitcode ("mov", "dph,%s", l);
9113 if (options.model == MODEL_FLAT24) {
9114 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
9117 emitcode ("mov", "dpx,%s", l);
9118 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9120 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9123 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
9124 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
9125 if (options.model == MODEL_FLAT24) {
9126 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9127 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9129 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9132 _endLazyDPSEvaluation ();
9135 /* so dptr know contains the address */
9136 aopOp (result, ic, FALSE, TRUE);
9138 /* if bit then unpack */
9139 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9140 genUnpackBits (result, "dptr", GPOINTER);
9143 size = AOP_SIZE (result);
9148 emitcode ("lcall", "__gptrget");
9149 aopPut (AOP (result), "a", offset++);
9150 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9151 emitcode ("inc", "dptr");
9155 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9156 aopPut ( AOP (left), "dpl", 0);
9157 aopPut ( AOP (left), "dph", 1);
9158 if (options.model == MODEL_FLAT24) {
9159 aopPut ( AOP (left), "dpx", 2);
9160 aopPut ( AOP (left), "b", 3);
9161 } else aopPut ( AOP (left), "b", 2);
9163 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9164 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9166 size = AOP_SIZE (result) - 1;
9167 while (size--) emitcode ("lcall","__decdptr");
9170 freeAsmop (left, NULL, ic, TRUE);
9171 freeAsmop (result, NULL, ic, TRUE);
9174 /*-----------------------------------------------------------------*/
9175 /* genPointerGet - generate code for pointer get */
9176 /*-----------------------------------------------------------------*/
9178 genPointerGet (iCode * ic, iCode *pi)
9180 operand *left, *result;
9181 sym_link *type, *etype;
9184 D (emitcode (";", "genPointerGet ");
9187 left = IC_LEFT (ic);
9188 result = IC_RESULT (ic);
9190 /* depending on the type of pointer we need to
9191 move it to the correct pointer register */
9192 type = operandType (left);
9193 etype = getSpec (type);
9194 /* if left is of type of pointer then it is simple */
9195 if (IS_PTR (type) && !IS_FUNC (type->next))
9196 p_type = DCL_TYPE (type);
9199 /* we have to go by the storage class */
9200 p_type = PTR_TYPE (SPEC_OCLS (etype));
9202 /* special case when cast remat */
9203 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9204 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9205 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9206 type = type = operandType (left);
9207 p_type = DCL_TYPE (type);
9209 /* now that we have the pointer type we assign
9210 the pointer values */
9216 genNearPointerGet (left, result, ic, pi);
9220 genPagedPointerGet (left, result, ic, pi);
9224 genFarPointerGet (left, result, ic, pi);
9228 emitcodePointerGet (left, result, ic, pi);
9232 genGenPointerGet (left, result, ic, pi);
9238 /*-----------------------------------------------------------------*/
9239 /* genPackBits - generates code for packed bit storage */
9240 /*-----------------------------------------------------------------*/
9242 genPackBits (sym_link * etype,
9244 char *rname, int p_type)
9252 blen = SPEC_BLEN (etype);
9253 bstr = SPEC_BSTR (etype);
9255 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9258 /* if the bit lenth is less than or */
9259 /* it exactly fits a byte then */
9260 if (SPEC_BLEN (etype) <= 8)
9262 shCount = SPEC_BSTR (etype);
9264 /* shift left acc */
9267 if (SPEC_BLEN (etype) < 8)
9268 { /* if smaller than a byte */
9274 emitcode ("mov", "b,a");
9275 emitcode ("mov", "a,@%s", rname);
9279 emitcode ("mov", "b,a");
9280 emitcode ("movx", "a,@dptr");
9284 emitcode ("push", "b");
9285 emitcode ("push", "acc");
9286 emitcode ("lcall", "__gptrget");
9287 emitcode ("pop", "b");
9291 emitcode ("anl", "a,#0x%02x", (unsigned char)
9292 ((unsigned char) (0xFF << (blen + bstr)) |
9293 (unsigned char) (0xFF >> (8 - bstr))));
9294 emitcode ("orl", "a,b");
9295 if (p_type == GPOINTER)
9296 emitcode ("pop", "b");
9303 emitcode ("mov", "@%s,a", rname);
9307 emitcode ("movx", "@dptr,a");
9311 emitcode ("lcall", "__gptrput");
9316 if (SPEC_BLEN (etype) <= 8)
9319 emitcode ("inc", "%s", rname);
9320 rLen = SPEC_BLEN (etype);
9322 /* now generate for lengths greater than one byte */
9326 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9338 emitcode ("mov", "@%s,a", rname);
9341 emitcode ("mov", "@%s,%s", rname, l);
9346 emitcode ("movx", "@dptr,a");
9351 emitcode ("lcall", "__gptrput");
9354 emitcode ("inc", "%s", rname);
9359 /* last last was not complete */
9362 /* save the byte & read byte */
9366 emitcode ("mov", "b,a");
9367 emitcode ("mov", "a,@%s", rname);
9371 emitcode ("mov", "b,a");
9372 emitcode ("movx", "a,@dptr");
9376 emitcode ("push", "b");
9377 emitcode ("push", "acc");
9378 emitcode ("lcall", "__gptrget");
9379 emitcode ("pop", "b");
9383 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
9384 emitcode ("orl", "a,b");
9387 if (p_type == GPOINTER)
9388 emitcode ("pop", "b");
9394 emitcode ("mov", "@%s,a", rname);
9398 emitcode ("movx", "@dptr,a");
9402 emitcode ("lcall", "__gptrput");
9406 /*-----------------------------------------------------------------*/
9407 /* genDataPointerSet - remat pointer to data space */
9408 /*-----------------------------------------------------------------*/
9410 genDataPointerSet (operand * right,
9414 int size, offset = 0;
9415 char *l, buffer[256];
9417 aopOp (right, ic, FALSE, FALSE);
9419 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9420 size = AOP_SIZE (right);
9424 sprintf (buffer, "(%s + %d)", l + 1, offset);
9426 sprintf (buffer, "%s", l + 1);
9427 emitcode ("mov", "%s,%s", buffer,
9428 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9431 freeAsmop (right, NULL, ic, TRUE);
9432 freeAsmop (result, NULL, ic, TRUE);
9435 /*-----------------------------------------------------------------*/
9436 /* genNearPointerSet - emitcode for near pointer put */
9437 /*-----------------------------------------------------------------*/
9439 genNearPointerSet (operand * right,
9447 sym_link *retype, *letype;
9448 sym_link *ptype = operandType (result);
9450 retype = getSpec (operandType (right));
9451 letype = getSpec (ptype);
9453 aopOp (result, ic, FALSE, FALSE);
9455 /* if the result is rematerializable &
9456 in data space & not a bit variable */
9457 if (AOP_TYPE (result) == AOP_IMMD &&
9458 DCL_TYPE (ptype) == POINTER &&
9459 !IS_BITVAR (retype) &&
9460 !IS_BITVAR (letype))
9462 genDataPointerSet (right, result, ic);
9466 /* if the value is already in a pointer register
9467 then don't need anything more */
9468 if (!AOP_INPREG (AOP (result)))
9470 /* otherwise get a free pointer register */
9472 preg = getFreePtr (ic, &aop, FALSE);
9473 emitcode ("mov", "%s,%s",
9475 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9479 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9481 aopOp (right, ic, FALSE, FALSE);
9483 /* if bitfield then unpack the bits */
9484 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9485 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9488 /* we have can just get the values */
9489 int size = AOP_SIZE (right);
9494 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9498 emitcode ("mov", "@%s,a", rname);
9501 emitcode ("mov", "@%s,%s", rname, l);
9503 emitcode ("inc", "%s", rname);
9508 /* now some housekeeping stuff */
9511 /* we had to allocate for this iCode */
9512 if (pi) aopPut (AOP (result),rname,0);
9513 freeAsmop (NULL, aop, ic, TRUE);
9517 /* we did not allocate which means left
9518 already in a pointer register, then
9519 if size > 0 && this could be used again
9520 we have to point it back to where it
9522 if (AOP_SIZE (right) > 1 &&
9523 !OP_SYMBOL (result)->remat &&
9524 (OP_SYMBOL (result)->liveTo > ic->seq ||
9528 int size = AOP_SIZE (right) - 1;
9530 emitcode ("dec", "%s", rname);
9535 if (pi) pi->generated = 1;
9536 freeAsmop (result, NULL, ic, TRUE);
9537 freeAsmop (right, NULL, ic, TRUE);
9542 /*-----------------------------------------------------------------*/
9543 /* genPagedPointerSet - emitcode for Paged pointer put */
9544 /*-----------------------------------------------------------------*/
9546 genPagedPointerSet (operand * right,
9554 sym_link *retype, *letype;
9556 retype = getSpec (operandType (right));
9557 letype = getSpec (operandType (result));
9559 aopOp (result, ic, FALSE, FALSE);
9561 /* if the value is already in a pointer register
9562 then don't need anything more */
9563 if (!AOP_INPREG (AOP (result)))
9565 /* otherwise get a free pointer register */
9567 preg = getFreePtr (ic, &aop, FALSE);
9568 emitcode ("mov", "%s,%s",
9570 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9574 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9576 aopOp (right, ic, FALSE, FALSE);
9578 /* if bitfield then unpack the bits */
9579 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9580 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9583 /* we have can just get the values */
9584 int size = AOP_SIZE (right);
9589 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9592 emitcode ("movx", "@%s,a", rname);
9595 emitcode ("inc", "%s", rname);
9601 /* now some housekeeping stuff */
9604 if (pi) aopPut (AOP (result),rname,0);
9605 /* we had to allocate for this iCode */
9606 freeAsmop (NULL, aop, ic, TRUE);
9610 /* we did not allocate which means left
9611 already in a pointer register, then
9612 if size > 0 && this could be used again
9613 we have to point it back to where it
9615 if (AOP_SIZE (right) > 1 &&
9616 !OP_SYMBOL (result)->remat &&
9617 (OP_SYMBOL (result)->liveTo > ic->seq ||
9621 int size = AOP_SIZE (right) - 1;
9623 emitcode ("dec", "%s", rname);
9628 if (pi) pi->generated = 1;
9629 freeAsmop (result, NULL, ic, TRUE);
9630 freeAsmop (right, NULL, ic, TRUE);
9635 /*-----------------------------------------------------------------*/
9636 /* genFarPointerSet - set value from far space */
9637 /*-----------------------------------------------------------------*/
9639 genFarPointerSet (operand * right,
9640 operand * result, iCode * ic, iCode *pi)
9642 int size, offset, dopi=1;
9643 sym_link *retype = getSpec (operandType (right));
9644 sym_link *letype = getSpec (operandType (result));
9646 aopOp (result, ic, FALSE, FALSE);
9648 /* if the operand is already in dptr
9649 then we do nothing else we move the value to dptr */
9650 if (AOP_TYPE (result) != AOP_STR)
9652 /* if this is remateriazable */
9653 if (AOP_TYPE (result) == AOP_IMMD)
9654 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9657 /* we need to get it byte by byte */
9658 _startLazyDPSEvaluation ();
9659 if (AOP_TYPE (result) != AOP_DPTR)
9661 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9662 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9663 if (options.model == MODEL_FLAT24)
9664 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9668 /* We need to generate a load to DPTR indirect through DPTR. */
9669 D (emitcode (";", "genFarPointerSet -- indirection special case.");
9671 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9672 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9673 if (options.model == MODEL_FLAT24)
9674 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9675 emitcode ("pop", "dph");
9676 emitcode ("pop", "dpl");
9679 _endLazyDPSEvaluation ();
9682 /* so dptr know contains the address */
9683 aopOp (right, ic, FALSE, TRUE);
9685 /* if bit then unpack */
9686 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9687 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9690 size = AOP_SIZE (right);
9693 _startLazyDPSEvaluation ();
9696 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9702 emitcode ("movx", "@dptr,a");
9703 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
9704 emitcode ("inc", "dptr");
9706 _endLazyDPSEvaluation ();
9709 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
9710 aopPut (AOP(result),"dpl",0);
9711 aopPut (AOP(result),"dph",1);
9712 if (options.model == MODEL_FLAT24)
9713 aopPut (AOP(result),"dpx",2);
9715 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9716 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9718 size = AOP_SIZE (right) - 1;
9719 while (size--) emitcode ("lcall","__decdptr");
9721 freeAsmop (result, NULL, ic, TRUE);
9722 freeAsmop (right, NULL, ic, TRUE);
9725 /*-----------------------------------------------------------------*/
9726 /* genGenPointerSet - set value from generic pointer space */
9727 /*-----------------------------------------------------------------*/
9729 genGenPointerSet (operand * right,
9730 operand * result, iCode * ic, iCode *pi)
9733 sym_link *retype = getSpec (operandType (right));
9734 sym_link *letype = getSpec (operandType (result));
9736 aopOp (result, ic, FALSE, OP_SYMBOL(result)->ruonly ? FALSE : TRUE);
9738 /* if the operand is already in dptr
9739 then we do nothing else we move the value to dptr */
9740 if (AOP_TYPE (result) != AOP_STR)
9742 _startLazyDPSEvaluation ();
9743 /* if this is remateriazable */
9744 if (AOP_TYPE (result) == AOP_IMMD)
9746 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9747 if (AOP(result)->aopu.aop_immd.from_cast_remat)
9748 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
9750 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9753 { /* we need to get it byte by byte */
9754 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9755 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9756 if (options.model == MODEL_FLAT24) {
9757 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9758 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9760 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9763 _endLazyDPSEvaluation ();
9765 /* so dptr know contains the address */
9766 aopOp (right, ic, FALSE, TRUE);
9768 /* if bit then unpack */
9769 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9770 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9773 size = AOP_SIZE (right);
9776 _startLazyDPSEvaluation ();
9779 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9785 emitcode ("lcall", "__gptrput");
9786 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
9787 emitcode ("inc", "dptr");
9789 _endLazyDPSEvaluation ();
9792 if (pi && AOP_TYPE (result) != AOP_IMMD) {
9793 aopPut (AOP(result),"dpl",0);
9794 aopPut (AOP(result),"dph",1);
9795 if (options.model == MODEL_FLAT24) {
9796 aopPut (AOP(result),"dpx",2);
9797 aopPut (AOP(result),"b",3);
9799 aopPut (AOP(result),"b",2);
9802 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9803 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9805 size = AOP_SIZE (right) - 1;
9806 while (size--) emitcode ("lcall","__decdptr");
9808 freeAsmop (result, NULL, ic, TRUE);
9809 freeAsmop (right, NULL, ic, TRUE);
9812 /*-----------------------------------------------------------------*/
9813 /* genPointerSet - stores the value into a pointer location */
9814 /*-----------------------------------------------------------------*/
9816 genPointerSet (iCode * ic, iCode *pi)
9818 operand *right, *result;
9819 sym_link *type, *etype;
9822 D (emitcode (";", "genPointerSet ");
9825 right = IC_RIGHT (ic);
9826 result = IC_RESULT (ic);
9828 /* depending on the type of pointer we need to
9829 move it to the correct pointer register */
9830 type = operandType (result);
9831 etype = getSpec (type);
9832 /* if left is of type of pointer then it is simple */
9833 if (IS_PTR (type) && !IS_FUNC (type->next))
9835 p_type = DCL_TYPE (type);
9839 /* we have to go by the storage class */
9840 p_type = PTR_TYPE (SPEC_OCLS (etype));
9842 /* special case when cast remat */
9843 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9844 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9845 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9846 type = type = operandType (result);
9847 p_type = DCL_TYPE (type);
9850 /* now that we have the pointer type we assign
9851 the pointer values */
9857 genNearPointerSet (right, result, ic, pi);
9861 genPagedPointerSet (right, result, ic, pi);
9865 genFarPointerSet (right, result, ic, pi);
9869 genGenPointerSet (right, result, ic, pi);
9875 /*-----------------------------------------------------------------*/
9876 /* genIfx - generate code for Ifx statement */
9877 /*-----------------------------------------------------------------*/
9879 genIfx (iCode * ic, iCode * popIc)
9881 operand *cond = IC_COND (ic);
9884 D (emitcode (";", "genIfx "););
9886 aopOp (cond, ic, FALSE, FALSE);
9888 /* get the value into acc */
9889 if (AOP_TYPE (cond) != AOP_CRY)
9893 /* the result is now in the accumulator */
9894 freeAsmop (cond, NULL, ic, TRUE);
9896 /* if there was something to be popped then do it */
9900 /* if the condition is a bit variable */
9901 if (isbit && IS_ITEMP (cond) &&
9903 genIfxJump (ic, SPIL_LOC (cond)->rname);
9904 else if (isbit && !IS_ITEMP (cond))
9905 genIfxJump (ic, OP_SYMBOL (cond)->rname);
9907 genIfxJump (ic, "a");
9912 /*-----------------------------------------------------------------*/
9913 /* genAddrOf - generates code for address of */
9914 /*-----------------------------------------------------------------*/
9916 genAddrOf (iCode * ic)
9918 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9921 D (emitcode (";", "genAddrOf ");
9924 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9926 /* if the operand is on the stack then we
9927 need to get the stack offset of this
9931 /* if 10 bit stack */
9932 if (options.stack10bit) {
9934 sprintf(buff,"#0x%02x",(options.stack_loc >> 16) & 0xff);
9935 /* if it has an offset then we need to compute it */
9936 emitcode ("subb", "a,#0x%02x",
9937 -((sym->stack < 0) ?
9938 ((short) (sym->stack - _G.nRegsSaved)) :
9939 ((short) sym->stack)) & 0xff);
9940 emitcode ("mov","b,a");
9941 emitcode ("mov","a,#0x%02x",(-((sym->stack < 0) ?
9942 ((short) (sym->stack - _G.nRegsSaved)) :
9943 ((short) sym->stack)) >> 8) & 0xff);
9945 emitcode ("mov", "a,_bpx");
9946 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
9947 ((char) (sym->stack - _G.nRegsSaved)) :
9948 ((char) sym->stack )) & 0xff);
9949 emitcode ("mov", "b,a");
9950 emitcode ("mov", "a,_bpx+1");
9951 emitcode ("addc","a,#0x%02x", (((sym->stack < 0) ?
9952 ((short) (sym->stack - _G.nRegsSaved)) :
9953 ((short) sym->stack )) >> 8) & 0xff);
9954 aopPut (AOP (IC_RESULT (ic)), "b", 0);
9955 aopPut (AOP (IC_RESULT (ic)), "a", 1);
9956 aopPut (AOP (IC_RESULT (ic)), buff, 2);
9958 /* we can just move _bp */
9959 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
9960 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
9961 aopPut (AOP (IC_RESULT (ic)), buff, 2);
9964 /* if it has an offset then we need to compute it */
9966 emitcode ("mov", "a,_bp");
9967 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9968 aopPut (AOP (IC_RESULT (ic)), "a", 0);
9970 /* we can just move _bp */
9971 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9973 /* fill the result with zero */
9974 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9977 if (options.stack10bit && size < (FPTRSIZE - 1)) {
9979 "*** warning: pointer to stack var truncated.\n");
9984 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9990 /* object not on stack then we need the name */
9991 size = AOP_SIZE (IC_RESULT (ic));
9996 char s[SDCC_NAME_MAX];
9998 sprintf (s, "#(%s >> %d)",
10002 sprintf (s, "#%s", sym->rname);
10003 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10007 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10011 /*-----------------------------------------------------------------*/
10012 /* genArrayInit - generates code for address of */
10013 /*-----------------------------------------------------------------*/
10015 genArrayInit (iCode * ic)
10017 literalList *iLoop;
10019 int elementSize = 0, eIndex;
10020 unsigned val, lastVal;
10022 operand *left=IC_LEFT(ic);
10024 D (emitcode (";", "genArrayInit "););
10026 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10028 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10030 // Load immediate value into DPTR.
10031 emitcode("mov", "dptr, %s",
10032 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
10034 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10037 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10038 "Unexpected operand to genArrayInit.\n");
10041 // a regression because of SDCCcse.c:1.52
10042 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
10043 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
10044 if (options.model == MODEL_FLAT24)
10045 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
10049 type = operandType(IC_LEFT(ic));
10051 if (type && type->next)
10053 elementSize = getSize(type->next);
10057 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10058 "can't determine element size in genArrayInit.\n");
10062 iLoop = IC_ARRAYILIST(ic);
10067 bool firstpass = TRUE;
10069 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10070 iLoop->count, (int)iLoop->literalValue, elementSize);
10076 symbol *tlbl = NULL;
10078 count = ix > 256 ? 256 : ix;
10082 tlbl = newiTempLabel (NULL);
10083 if (firstpass || (count & 0xff))
10085 emitcode("mov", "b, #0x%x", count & 0xff);
10088 emitcode ("", "%05d$:", tlbl->key + 100);
10093 for (eIndex = 0; eIndex < elementSize; eIndex++)
10095 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10096 if (val != lastVal)
10098 emitcode("mov", "a, #0x%x", val);
10102 emitcode("movx", "@dptr, a");
10103 emitcode("inc", "dptr");
10108 emitcode("djnz", "b, %05d$", tlbl->key + 100);
10114 iLoop = iLoop->next;
10117 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10120 /*-----------------------------------------------------------------*/
10121 /* genFarFarAssign - assignment when both are in far space */
10122 /*-----------------------------------------------------------------*/
10124 genFarFarAssign (operand * result, operand * right, iCode * ic)
10126 int size = AOP_SIZE (right);
10128 symbol *rSym = NULL;
10132 /* quick & easy case. */
10133 D(emitcode(";","genFarFarAssign (1 byte case)"););
10134 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
10135 freeAsmop (right, NULL, ic, FALSE);
10136 /* now assign DPTR to result */
10138 aopOp(result, ic, FALSE, FALSE);
10140 aopPut(AOP(result), "a", 0);
10141 freeAsmop(result, NULL, ic, FALSE);
10145 /* See if we've got an underlying symbol to abuse. */
10146 if (IS_SYMOP(result) && OP_SYMBOL(result))
10148 if (IS_TRUE_SYMOP(result))
10150 rSym = OP_SYMBOL(result);
10152 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10154 rSym = OP_SYMBOL(result)->usl.spillLoc;
10158 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10160 /* We can use the '390 auto-toggle feature to good effect here. */
10162 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10163 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
10164 emitcode ("mov", "dptr,#%s", rSym->rname);
10165 /* DP2 = result, DP1 = right, DP1 is current. */
10168 emitcode("movx", "a,@dptr");
10169 emitcode("movx", "@dptr,a");
10172 emitcode("inc", "dptr");
10173 emitcode("inc", "dptr");
10176 emitcode("mov", "dps, #0");
10177 freeAsmop (right, NULL, ic, FALSE);
10179 some alternative code for processors without auto-toggle
10180 no time to test now, so later well put in...kpb
10181 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10182 emitcode("mov", "dps, #0x01"); /* Select DPTR2. */
10183 emitcode ("mov", "dptr,#%s", rSym->rname);
10184 /* DP2 = result, DP1 = right, DP1 is current. */
10188 emitcode("movx", "a,@dptr");
10190 emitcode("inc", "dptr");
10191 emitcode("inc", "dps");
10192 emitcode("movx", "@dptr,a");
10194 emitcode("inc", "dptr");
10195 emitcode("inc", "dps");
10197 emitcode("mov", "dps, #0");
10198 freeAsmop (right, NULL, ic, FALSE);
10203 D (emitcode (";", "genFarFarAssign"););
10204 aopOp (result, ic, TRUE, TRUE);
10206 _startLazyDPSEvaluation ();
10210 aopPut (AOP (result),
10211 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10214 _endLazyDPSEvaluation ();
10215 freeAsmop (result, NULL, ic, FALSE);
10216 freeAsmop (right, NULL, ic, FALSE);
10220 /*-----------------------------------------------------------------*/
10221 /* genAssign - generate code for assignment */
10222 /*-----------------------------------------------------------------*/
10224 genAssign (iCode * ic)
10226 operand *result, *right;
10228 unsigned long lit = 0L;
10230 D (emitcode (";", "genAssign ");
10233 result = IC_RESULT (ic);
10234 right = IC_RIGHT (ic);
10236 /* if they are the same */
10237 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10240 aopOp (right, ic, FALSE, FALSE);
10242 emitcode (";", "genAssign: resultIsFar = %s",
10243 isOperandInFarSpace (result) ?
10246 /* special case both in far space */
10247 if ((AOP_TYPE (right) == AOP_DPTR ||
10248 AOP_TYPE (right) == AOP_DPTR2) &&
10249 /* IS_TRUE_SYMOP(result) && */
10250 isOperandInFarSpace (result))
10252 genFarFarAssign (result, right, ic);
10256 aopOp (result, ic, TRUE, FALSE);
10258 /* if they are the same registers */
10259 if (sameRegs (AOP (right), AOP (result)))
10262 /* if the result is a bit */
10263 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10265 /* if the right size is a literal then
10266 we know what the value is */
10267 if (AOP_TYPE (right) == AOP_LIT)
10269 if (((int) operandLitValue (right)))
10270 aopPut (AOP (result), one, 0);
10272 aopPut (AOP (result), zero, 0);
10276 /* the right is also a bit variable */
10277 if (AOP_TYPE (right) == AOP_CRY)
10279 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10280 aopPut (AOP (result), "c", 0);
10284 /* we need to or */
10286 aopPut (AOP (result), "a", 0);
10290 /* bit variables done */
10292 size = AOP_SIZE (result);
10294 if (AOP_TYPE (right) == AOP_LIT)
10295 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10298 (AOP_TYPE (result) != AOP_REG) &&
10299 (AOP_TYPE (right) == AOP_LIT) &&
10300 !IS_FLOAT (operandType (right)))
10302 _startLazyDPSEvaluation ();
10303 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10305 aopPut (AOP (result),
10306 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10311 /* And now fill the rest with zeros. */
10314 emitcode ("clr", "a");
10318 aopPut (AOP (result), "a", offset++);
10320 _endLazyDPSEvaluation ();
10324 _startLazyDPSEvaluation ();
10327 aopPut (AOP (result),
10328 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10332 _endLazyDPSEvaluation ();
10336 freeAsmop (right, NULL, ic, FALSE);
10337 freeAsmop (result, NULL, ic, TRUE);
10340 /*-----------------------------------------------------------------*/
10341 /* genJumpTab - generates code for jump table */
10342 /*-----------------------------------------------------------------*/
10344 genJumpTab (iCode * ic)
10349 D (emitcode (";", "genJumpTab ");
10352 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10353 /* get the condition into accumulator */
10354 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10356 /* multiply by four! */
10357 emitcode ("add", "a,acc");
10358 emitcode ("add", "a,acc");
10359 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10361 jtab = newiTempLabel (NULL);
10362 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10363 emitcode ("jmp", "@a+dptr");
10364 emitcode ("", "%05d$:", jtab->key + 100);
10365 /* now generate the jump labels */
10366 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10367 jtab = setNextItem (IC_JTLABELS (ic)))
10368 emitcode ("ljmp", "%05d$", jtab->key + 100);
10372 /*-----------------------------------------------------------------*/
10373 /* genCast - gen code for casting */
10374 /*-----------------------------------------------------------------*/
10376 genCast (iCode * ic)
10378 operand *result = IC_RESULT (ic);
10379 sym_link *ctype = operandType (IC_LEFT (ic));
10380 sym_link *rtype = operandType (IC_RIGHT (ic));
10381 operand *right = IC_RIGHT (ic);
10384 D (emitcode (";", "genCast ");
10387 /* if they are equivalent then do nothing */
10388 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10391 aopOp (right, ic, FALSE, FALSE);
10392 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10394 /* if the result is a bit */
10395 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10396 if (IS_BITVAR(OP_SYMBOL(result)->type))
10398 /* if the right size is a literal then
10399 we know what the value is */
10400 if (AOP_TYPE (right) == AOP_LIT)
10402 if (((int) operandLitValue (right)))
10403 aopPut (AOP (result), one, 0);
10405 aopPut (AOP (result), zero, 0);
10410 /* the right is also a bit variable */
10411 if (AOP_TYPE (right) == AOP_CRY)
10413 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10414 aopPut (AOP (result), "c", 0);
10418 /* we need to or */
10420 aopPut (AOP (result), "a", 0);
10424 /* if they are the same size : or less */
10425 if (AOP_SIZE (result) <= AOP_SIZE (right))
10428 /* if they are in the same place */
10429 if (sameRegs (AOP (right), AOP (result)))
10432 /* if they in different places then copy */
10433 size = AOP_SIZE (result);
10435 _startLazyDPSEvaluation ();
10438 aopPut (AOP (result),
10439 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10443 _endLazyDPSEvaluation ();
10448 /* if the result is of type pointer */
10449 if (IS_PTR (ctype))
10453 sym_link *type = operandType (right);
10455 /* pointer to generic pointer */
10456 if (IS_GENPTR (ctype))
10462 p_type = DCL_TYPE (type);
10466 #if OLD_CAST_BEHAVIOR
10467 /* KV: we are converting a non-pointer type to
10468 * a generic pointer. This (ifdef'd out) code
10469 * says that the resulting generic pointer
10470 * should have the same class as the storage
10471 * location of the non-pointer variable.
10473 * For example, converting an int (which happens
10474 * to be stored in DATA space) to a pointer results
10475 * in a DATA generic pointer; if the original int
10476 * in XDATA space, so will be the resulting pointer.
10478 * I don't like that behavior, and thus this change:
10479 * all such conversions will be forced to XDATA and
10480 * throw a warning. If you want some non-XDATA
10481 * type, or you want to suppress the warning, you
10482 * must go through an intermediate cast, like so:
10484 * char _generic *gp = (char _xdata *)(intVar);
10486 sym_link *etype = getSpec (type);
10488 /* we have to go by the storage class */
10489 if (SPEC_OCLS (etype) != generic)
10491 p_type = PTR_TYPE (SPEC_OCLS (etype));
10496 /* Converting unknown class (i.e. register variable)
10497 * to generic pointer. This is not good, but
10498 * we'll make a guess (and throw a warning).
10501 werror (W_INT_TO_GEN_PTR_CAST);
10505 /* the first two bytes are known */
10506 size = GPTRSIZE - 1;
10508 _startLazyDPSEvaluation ();
10511 aopPut (AOP (result),
10512 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10516 _endLazyDPSEvaluation ();
10518 /* the last byte depending on type */
10536 /* this should never happen */
10537 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10538 "got unknown pointer type");
10541 aopPut (AOP (result), l, GPTRSIZE - 1);
10545 /* just copy the pointers */
10546 size = AOP_SIZE (result);
10548 _startLazyDPSEvaluation ();
10551 aopPut (AOP (result),
10552 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10556 _endLazyDPSEvaluation ();
10560 /* so we now know that the size of destination is greater
10561 than the size of the source */
10562 /* we move to result for the size of source */
10563 size = AOP_SIZE (right);
10565 _startLazyDPSEvaluation ();
10568 aopPut (AOP (result),
10569 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10573 _endLazyDPSEvaluation ();
10575 /* now depending on the sign of the source && destination */
10576 size = AOP_SIZE (result) - AOP_SIZE (right);
10577 /* if unsigned or not an integral type */
10578 /* also, if the source is a bit, we don't need to sign extend, because
10579 * it can't possibly have set the sign bit.
10581 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10585 aopPut (AOP (result), zero, offset++);
10590 /* we need to extend the sign :{ */
10591 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10592 FALSE, FALSE, TRUE);
10594 emitcode ("rlc", "a");
10595 emitcode ("subb", "a,acc");
10597 aopPut (AOP (result), "a", offset++);
10600 /* we are done hurray !!!! */
10603 freeAsmop (right, NULL, ic, TRUE);
10604 freeAsmop (result, NULL, ic, TRUE);
10608 /*-----------------------------------------------------------------*/
10609 /* genDjnz - generate decrement & jump if not zero instrucion */
10610 /*-----------------------------------------------------------------*/
10612 genDjnz (iCode * ic, iCode * ifx)
10614 symbol *lbl, *lbl1;
10618 /* if the if condition has a false label
10619 then we cannot save */
10620 if (IC_FALSE (ifx))
10623 /* if the minus is not of the form
10625 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10626 !IS_OP_LITERAL (IC_RIGHT (ic)))
10629 if (operandLitValue (IC_RIGHT (ic)) != 1)
10632 /* if the size of this greater than one then no
10634 if (getSize (operandType (IC_RESULT (ic))) > 1)
10637 /* otherwise we can save BIG */
10638 D(emitcode(";", "genDjnz"););
10640 lbl = newiTempLabel (NULL);
10641 lbl1 = newiTempLabel (NULL);
10643 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10645 if (AOP_NEEDSACC(IC_RESULT(ic)))
10647 /* If the result is accessed indirectly via
10648 * the accumulator, we must explicitly write
10649 * it back after the decrement.
10651 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10653 if (strcmp(rByte, "a"))
10655 /* Something is hopelessly wrong */
10656 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10657 __FILE__, __LINE__);
10658 /* We can just give up; the generated code will be inefficient,
10659 * but what the hey.
10661 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10664 emitcode ("dec", "%s", rByte);
10665 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10666 emitcode ("jnz", "%05d$", lbl->key + 100);
10668 else if (IS_AOP_PREG (IC_RESULT (ic)))
10670 emitcode ("dec", "%s",
10671 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10672 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10673 emitcode ("jnz", "%05d$", lbl->key + 100);
10677 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10680 emitcode ("sjmp", "%05d$", lbl1->key + 100);
10681 emitcode ("", "%05d$:", lbl->key + 100);
10682 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10683 emitcode ("", "%05d$:", lbl1->key + 100);
10685 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10686 ifx->generated = 1;
10690 /*-----------------------------------------------------------------*/
10691 /* genReceive - generate code for a receive iCode */
10692 /*-----------------------------------------------------------------*/
10694 genReceive (iCode * ic)
10697 D (emitcode (";", "genReceive ");
10700 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10701 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10702 IS_TRUE_SYMOP (IC_RESULT (ic))))
10704 int size = getSize (operandType (IC_RESULT (ic)));
10705 int offset = fReturnSizeDS390 - size;
10708 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10709 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10712 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10713 size = AOP_SIZE (IC_RESULT (ic));
10717 emitcode ("pop", "acc");
10718 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10725 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10727 assignResultValue (IC_RESULT (ic));
10730 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10733 /*-----------------------------------------------------------------*/
10734 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
10735 /*-----------------------------------------------------------------*/
10736 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
10738 operand *from , *to , *count;
10741 /* we know it has to be 3 parameters */
10742 assert (nparms == 3);
10748 aopOp (from, ic->next, FALSE, FALSE);
10750 /* get from into DPTR1 */
10751 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
10752 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
10753 if (options.model == MODEL_FLAT24) {
10754 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
10757 freeAsmop (from, NULL, ic, FALSE);
10758 aopOp (to, ic, FALSE, FALSE);
10759 /* get "to" into DPTR */
10760 /* if the operand is already in dptr
10761 then we do nothing else we move the value to dptr */
10762 if (AOP_TYPE (to) != AOP_STR) {
10763 /* if already in DPTR then we need to push */
10764 if (AOP_TYPE(to) == AOP_DPTR) {
10765 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
10766 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
10767 if (options.model == MODEL_FLAT24)
10768 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10769 emitcode ("pop", "dph");
10770 emitcode ("pop", "dpl");
10772 _startLazyDPSEvaluation ();
10773 /* if this is remateriazable */
10774 if (AOP_TYPE (to) == AOP_IMMD) {
10775 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
10776 } else { /* we need to get it byte by byte */
10777 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
10778 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
10779 if (options.model == MODEL_FLAT24) {
10780 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10783 _endLazyDPSEvaluation ();
10786 freeAsmop (to, NULL, ic, FALSE);
10788 aopOp (count, ic->next->next, FALSE,FALSE);
10789 lbl =newiTempLabel(NULL);
10791 /* now for the actual copy */
10792 if (AOP_TYPE(count) == AOP_LIT &&
10793 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
10794 emitcode (";","OH! JOY auto increment with djnz (very fast)");
10795 emitcode ("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
10796 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
10797 emitcode ("","%05d$:",lbl->key+100);
10799 emitcode ("clr","a");
10800 emitcode ("movc", "a,@a+dptr");
10802 emitcode ("movx", "a,@dptr");
10803 emitcode ("movx", "@dptr,a");
10804 emitcode ("inc", "dptr");
10805 emitcode ("inc", "dptr");
10806 emitcode ("djnz","b,%05d$",lbl->key+100);
10808 symbol *lbl1 = newiTempLabel(NULL);
10810 emitcode (";"," Auto increment but no djnz");
10811 emitcode ("mov","ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
10812 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
10813 emitcode ("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
10814 emitcode ("","%05d$:",lbl->key+100);
10816 emitcode ("clr","a");
10817 emitcode ("movc", "a,@a+dptr");
10819 emitcode ("movx", "a,@dptr");
10820 emitcode ("movx", "@dptr,a");
10821 emitcode ("inc", "dptr");
10822 emitcode ("inc", "dptr");
10823 emitcode ("mov","a,b");
10824 emitcode ("orl","a,ap");
10825 emitcode ("jz","%05d$",lbl1->key+100);
10826 emitcode ("mov","a,ap");
10827 emitcode ("add","a,#0xFF");
10828 emitcode ("mov","ap,a");
10829 emitcode ("mov","a,b");
10830 emitcode ("addc","a,#0xFF");
10831 emitcode ("mov","b,a");
10832 emitcode ("sjmp","%05d$",lbl->key+100);
10833 emitcode ("","%05d$:",lbl1->key+100);
10835 emitcode ("mov", "dps, #0");
10836 freeAsmop (count, NULL, ic, FALSE);
10840 /*-----------------------------------------------------------------*/
10841 /* genMemsetX - gencode for memSetX data */
10842 /*-----------------------------------------------------------------*/
10843 static void genMemsetX(iCode *ic, int nparms, operand **parms)
10845 operand *to , *val , *count;
10848 /* we know it has to be 3 parameters */
10849 assert (nparms == 3);
10855 aopOp (to, ic, FALSE, FALSE);
10856 /* get "to" into DPTR */
10857 /* if the operand is already in dptr
10858 then we do nothing else we move the value to dptr */
10859 if (AOP_TYPE (to) != AOP_STR) {
10860 /* if already in DPTR then we need to push */
10861 if (AOP_TYPE(to) == AOP_DPTR) {
10862 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
10863 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
10864 if (options.model == MODEL_FLAT24)
10865 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10866 emitcode ("pop", "dph");
10867 emitcode ("pop", "dpl");
10869 _startLazyDPSEvaluation ();
10870 /* if this is remateriazable */
10871 if (AOP_TYPE (to) == AOP_IMMD) {
10872 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
10873 } else { /* we need to get it byte by byte */
10874 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
10875 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
10876 if (options.model == MODEL_FLAT24) {
10877 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10880 _endLazyDPSEvaluation ();
10883 freeAsmop (to, NULL, ic, FALSE);
10885 aopOp (val, ic->next->next, FALSE,FALSE);
10886 aopOp (count, ic->next->next, FALSE,FALSE);
10887 lbl =newiTempLabel(NULL);
10888 /* now for the actual copy */
10889 if (AOP_TYPE(count) == AOP_LIT &&
10890 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
10891 l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
10892 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
10894 emitcode ("","%05d$:",lbl->key+100);
10895 emitcode ("movx", "@dptr,a");
10896 emitcode ("inc", "dptr");
10897 emitcode ("djnz","b,%05d$",lbl->key+100);
10899 symbol *lbl1 = newiTempLabel(NULL);
10901 emitcode ("mov","ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
10902 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
10903 emitcode ("","%05d$:",lbl->key+100);
10904 l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
10906 emitcode ("movx", "a,@dptr");
10907 emitcode ("inc", "dptr");
10908 emitcode ("mov","a,b");
10909 emitcode ("orl","a,ap");
10910 emitcode ("jz","%05d$",lbl1->key+100);
10911 emitcode ("mov","a,ap");
10912 emitcode ("add","a,#0xFF");
10913 emitcode ("mov","ap,a");
10914 emitcode ("mov","a,b");
10915 emitcode ("addc","a,#0xFF");
10916 emitcode ("mov","b,a");
10917 emitcode ("sjmp","%05d$",lbl->key+100);
10918 emitcode ("","%05d$:",lbl1->key+100);
10920 freeAsmop (count, NULL, ic, FALSE);
10923 /*-----------------------------------------------------------------*/
10924 /* genBuiltIn - calls the appropriate function to generating code */
10925 /* for a built in function */
10926 /*-----------------------------------------------------------------*/
10927 static void genBuiltIn (iCode *ic)
10929 operand *bi_parms[MAX_BUILTIN_ARGS];
10934 /* get all the arguments for a built in function */
10935 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
10937 /* which function is it */
10938 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
10939 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
10940 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
10941 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
10942 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
10943 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
10944 genMemsetX(bi_iCode,nbi_parms,bi_parms);
10946 werror(E_INTERNAL_ERROR,"unknown builtin function encountered\n");
10952 /*-----------------------------------------------------------------*/
10953 /* gen390Code - generate code for Dallas 390 based controllers */
10954 /*-----------------------------------------------------------------*/
10956 gen390Code (iCode * lic)
10961 lineHead = lineCurr = NULL;
10963 if (options.model == MODEL_FLAT24) {
10964 fReturnSizeDS390 = 5;
10965 fReturn = fReturn24;
10967 fReturnSizeDS390 = 4;
10968 fReturn = fReturn16;
10969 options.stack10bit=0;
10973 /* print the allocation information */
10975 printAllocInfo (currFunc, codeOutFile);
10977 /* if debug information required */
10978 if (options.debug && currFunc)
10980 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
10982 if (IS_STATIC (currFunc->etype))
10983 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
10985 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
10988 /* stack pointer name */
10989 if (options.useXstack)
10995 for (ic = lic; ic; ic = ic->next)
10998 if (cln != ic->lineno)
11003 emitcode ("", "C$%s$%d$%d$%d ==.",
11004 FileBaseName (ic->filename), ic->lineno,
11005 ic->level, ic->block);
11008 emitcode (";", "%s %d", ic->filename, ic->lineno);
11011 /* if the result is marked as
11012 spilt and rematerializable or code for
11013 this has already been generated then
11015 if (resultRemat (ic) || ic->generated)
11018 /* depending on the operation */
11038 /* IPOP happens only when trying to restore a
11039 spilt live range, if there is an ifx statement
11040 following this pop then the if statement might
11041 be using some of the registers being popped which
11042 would destory the contents of the register so
11043 we need to check for this condition and handle it */
11045 ic->next->op == IFX &&
11046 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11047 genIfx (ic->next, ic);
11065 genEndFunction (ic);
11085 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11102 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11106 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11113 /* note these two are xlated by algebraic equivalence
11114 during parsing SDCC.y */
11115 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11116 "got '>=' or '<=' shouldn't have come here");
11120 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11132 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11136 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11140 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11164 genRightShift (ic);
11167 case GET_VALUE_AT_ADDRESS:
11168 genPointerGet (ic,hasInc(IC_LEFT(ic),ic));
11172 if (POINTER_SET (ic))
11173 genPointerSet (ic,hasInc(IC_RESULT(ic),ic));
11199 if (ic->builtinSEND) genBuiltIn(ic);
11200 else addSet (&_G.sendSet, ic);
11213 /* now we are ready to call the
11214 peep hole optimizer */
11215 if (!options.nopeep)
11216 peepHole (&lineHead);
11218 /* now do the actual printing */
11219 printLine (lineHead, codeOutFile);