1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for DS80C390
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 DS390 adaptation by Kevin Vigor <kevin@vigor.nu>
9 This program is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 In other words, you are welcome to use, share and improve this program.
24 You are forbidden to forbid anyone else to use, share and improve
25 what you give them. Help stamp out software-hoarding!
26 -------------------------------------------------------------------------*/
36 #include "SDCCglobl.h"
39 #ifdef HAVE_SYS_ISA_DEFS_H
40 #include <sys/isa_defs.h>
42 #ifdef HAVE_MACHINE_ENDIAN_H
43 #include <machine/endian.h>
48 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
49 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
50 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
56 #define BETTER_LITERAL_SHIFT
58 char *aopLiteral (value * val, int offset);
60 /* this is the down and dirty file with all kinds of
61 kludgy & hacky stuff. This is what it is all about
62 CODE GENERATION for a specific MCU . some of the
63 routines may be reusable, will have to see */
65 static char *zero = "#0x00";
66 static char *one = "#0x01";
71 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
72 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
74 unsigned fReturnSizeDS390 = 5; /* shared with ralloc.c */
75 static char *fReturn24[] =
76 {"dpl", "dph", "dpx", "b", "a"};
77 static char *fReturn16[] =
78 {"dpl", "dph", "b", "a"};
79 static char **fReturn = fReturn24;
80 static char *accUse[] =
83 static short rbank = -1;
97 static void saveRBank (int, iCode *, bool);
99 #define RESULTONSTACK(x) \
100 (IC_RESULT(x) && IC_RESULT(x)->aop && \
101 IC_RESULT(x)->aop->type == AOP_STK )
103 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
104 #define MOVA(x) { char *_mova_tmp = strdup(x); \
105 if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
107 emitcode("mov","a,%s",_mova_tmp); \
111 #define CLRC emitcode("clr","c")
112 #define SETC emitcode("setb","c")
114 // A scratch register which will be used to hold
115 // result bytes from operands in far space via DPTR2.
116 #define DP2_RESULT_REG "ap"
118 static lineNode *lineHead = NULL;
119 static lineNode *lineCurr = NULL;
121 static unsigned char SLMask[] =
122 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
123 0xE0, 0xC0, 0x80, 0x00};
124 static unsigned char SRMask[] =
125 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
126 0x07, 0x03, 0x01, 0x00};
133 /*-----------------------------------------------------------------*/
134 /* emitcode - writes the code into a file : for now it is simple */
135 /*-----------------------------------------------------------------*/
137 emitcode (char *inst, char *fmt,...)
140 char lb[INITIAL_INLINEASM];
148 sprintf (lb, "%s\t", inst);
150 sprintf (lb, "%s", inst);
151 vsprintf (lb + (strlen (lb)), fmt, ap);
154 vsprintf (lb, fmt, ap);
156 while (isspace (*lbp))
160 lineCurr = (lineCurr ?
161 connectLine (lineCurr, newLineNode (lb)) :
162 (lineHead = newLineNode (lb)));
163 lineCurr->isInline = _G.inLine;
164 lineCurr->isDebug = _G.debugLine;
168 /*-----------------------------------------------------------------*/
169 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
170 /*-----------------------------------------------------------------*/
172 getFreePtr (iCode * ic, asmop ** aopp, bool result)
174 bool r0iu = FALSE, r1iu = FALSE;
175 bool r0ou = FALSE, r1ou = FALSE;
177 /* the logic: if r0 & r1 used in the instruction
178 then we are in trouble otherwise */
180 /* first check if r0 & r1 are used by this
181 instruction, in which case we are in trouble */
182 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
183 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
188 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
189 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
191 /* if no usage of r0 then return it */
194 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
195 (*aopp)->type = AOP_R0;
197 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
200 /* if no usage of r1 then return it */
203 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
204 (*aopp)->type = AOP_R1;
206 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
209 /* now we know they both have usage */
210 /* if r0 not used in this instruction */
213 /* push it if not already pushed */
216 emitcode ("push", "%s",
217 ds390_regWithIdx (R0_IDX)->dname);
221 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
222 (*aopp)->type = AOP_R0;
224 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
227 /* if r1 not used then */
231 /* push it if not already pushed */
234 emitcode ("push", "%s",
235 ds390_regWithIdx (R1_IDX)->dname);
239 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
240 (*aopp)->type = AOP_R1;
241 return ds390_regWithIdx (R1_IDX);
245 /* I said end of world but not quite end of world yet */
246 /* if this is a result then we can push it on the stack */
249 (*aopp)->type = AOP_STK;
253 /* other wise this is true end of the world */
254 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
255 "getFreePtr should never reach here");
259 /*-----------------------------------------------------------------*/
260 /* newAsmop - creates a new asmOp */
261 /*-----------------------------------------------------------------*/
263 newAsmop (short type)
267 aop = Safe_calloc (1, sizeof (asmop));
272 static int _currentDPS; /* Current processor DPS. */
273 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
274 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
276 /*-----------------------------------------------------------------*/
277 /* genSetDPTR: generate code to select which DPTR is in use (zero */
278 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
279 /* alternate DPTR (DPL1/DPH1/DPX1). */
280 /*-----------------------------------------------------------------*/
285 /* If we are doing lazy evaluation, simply note the desired
286 * change, but don't emit any code yet.
296 emitcode ("mov", "dps, #0x00");
301 emitcode ("mov", "dps, #0x01");
305 /*-----------------------------------------------------------------*/
306 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
308 /* Any code that operates on DPTR (NB: not on the individual */
309 /* components, like DPH) *must* call _flushLazyDPS() before using */
310 /* DPTR within a lazy DPS evaluation block. */
312 /* Note that aopPut and aopGet already contain the proper calls to */
313 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
314 /* DPS evaluation block. */
316 /* Also, _flushLazyDPS must be called before any flow control */
317 /* operations that could potentially branch out of the block. */
319 /* Lazy DPS evaluation is simply an optimization (though an */
320 /* important one), so if in doubt, leave it out. */
321 /*-----------------------------------------------------------------*/
323 _startLazyDPSEvaluation (void)
327 #ifdef BETTER_LITERAL_SHIFT
334 /*-----------------------------------------------------------------*/
335 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
336 /* desired one. Call before using DPTR within a lazy DPS evaluation */
338 /*-----------------------------------------------------------------*/
348 if (_desiredDPS != _currentDPS)
352 emitcode ("inc", "dps");
356 emitcode ("dec", "dps");
358 _currentDPS = _desiredDPS;
362 /*-----------------------------------------------------------------*/
363 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
365 /* Forces us back to the safe state (standard DPTR selected). */
366 /*-----------------------------------------------------------------*/
368 _endLazyDPSEvaluation (void)
370 #ifdef BETTER_LITERAL_SHIFT
389 /*-----------------------------------------------------------------*/
390 /* pointerCode - returns the code for a pointer type */
391 /*-----------------------------------------------------------------*/
393 pointerCode (sym_link * etype)
396 return PTR_TYPE (SPEC_OCLS (etype));
400 /*-----------------------------------------------------------------*/
401 /* aopForSym - for a true symbol */
402 /*-----------------------------------------------------------------*/
404 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
407 memmap *space = SPEC_OCLS (sym->etype);
409 /* if already has one */
413 /* assign depending on the storage class */
414 /* if it is on the stack or indirectly addressable */
415 /* space we need to assign either r0 or r1 to it */
416 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
418 sym->aop = aop = newAsmop (0);
419 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
420 aop->size = getSize (sym->type);
422 /* now assign the address of the variable to
423 the pointer register */
424 if (aop->type != AOP_STK)
430 emitcode ("push", "acc");
432 emitcode ("mov", "a,_bp");
433 emitcode ("add", "a,#0x%02x",
435 ((char) (sym->stack - _G.nRegsSaved)) :
436 ((char) sym->stack)) & 0xff);
437 emitcode ("mov", "%s,a",
438 aop->aopu.aop_ptr->name);
441 emitcode ("pop", "acc");
444 emitcode ("mov", "%s,#%s",
445 aop->aopu.aop_ptr->name,
447 aop->paged = space->paged;
450 aop->aopu.aop_stk = sym->stack;
454 if (sym->onStack && options.stack10bit)
456 /* It's on the 10 bit stack, which is located in
461 emitcode ("push", "acc");
463 emitcode ("mov", "a,_bpx");
464 emitcode ("clr","c");
465 emitcode ("subb", "a,#0x%02x",
467 ((short) (sym->stack - _G.nRegsSaved)) :
468 ((short) sym->stack)) & 0xff);
469 emitcode ("mov","b,a");
470 emitcode ("mov","a,#0x%02x",(-((sym->stack < 0) ?
471 ((short) (sym->stack - _G.nRegsSaved)) :
472 ((short) sym->stack)) >> 8) & 0xff);
473 emitcode ("subb","a,_bpx+1");
475 if (options.model == MODEL_FLAT24)
476 emitcode ("mov", "dpx1,#0x40");
478 emitcode ("mov", "dph1,a");
479 emitcode ("mov", "dpl1,b");
481 if (options.model == MODEL_FLAT24)
482 emitcode ("mov", "dpx,#0x40");
483 emitcode ("mov", "dph,a");
484 emitcode ("mov", "dpl,b");
488 emitcode ("pop", "acc");
490 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
491 aop->size = getSize (sym->type);
495 /* if in bit space */
496 if (IN_BITSPACE (space))
498 sym->aop = aop = newAsmop (AOP_CRY);
499 aop->aopu.aop_dir = sym->rname;
500 aop->size = getSize (sym->type);
503 /* if it is in direct space */
504 if (IN_DIRSPACE (space))
506 sym->aop = aop = newAsmop (AOP_DIR);
507 aop->aopu.aop_dir = sym->rname;
508 aop->size = getSize (sym->type);
512 /* special case for a function */
513 if (IS_FUNC (sym->type))
515 sym->aop = aop = newAsmop (AOP_IMMD);
516 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
517 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
518 aop->size = FPTRSIZE;
522 /* only remaining is far space */
523 /* in which case DPTR gets the address */
524 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
529 emitcode ("mov", "dptr,#%s", sym->rname);
534 emitcode ("mov", "dptr,#%s", sym->rname);
536 aop->size = getSize (sym->type);
538 /* if it is in code space */
539 if (IN_CODESPACE (space))
545 /*-----------------------------------------------------------------*/
546 /* aopForRemat - rematerialzes an object */
547 /*-----------------------------------------------------------------*/
549 aopForRemat (symbol * sym)
551 iCode *ic = sym->rematiCode;
552 asmop *aop = newAsmop (AOP_IMMD);
559 val += (int) operandLitValue (IC_RIGHT (ic));
560 else if (ic->op == '-')
561 val -= (int) operandLitValue (IC_RIGHT (ic));
562 else if (IS_CAST_ICODE(ic)) {
563 sym_link *from_type = operandType(IC_RIGHT(ic));
564 aop->aopu.aop_immd.from_cast_remat = 1;
565 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
566 ptr_type = DCL_TYPE(from_type);
567 if (ptr_type == IPOINTER) {
574 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
578 sprintf (buffer, "(%s %c 0x%04x)",
579 OP_SYMBOL (IC_LEFT (ic))->rname,
580 val >= 0 ? '+' : '-',
583 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
585 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
586 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
587 /* set immd2 field if required */
588 if (aop->aopu.aop_immd.from_cast_remat) {
589 sprintf(buffer,"#0x%02x",ptr_type);
590 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
591 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
597 /*-----------------------------------------------------------------*/
598 /* regsInCommon - two operands have some registers in common */
599 /*-----------------------------------------------------------------*/
601 regsInCommon (operand * op1, operand * op2)
606 /* if they have registers in common */
607 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
610 sym1 = OP_SYMBOL (op1);
611 sym2 = OP_SYMBOL (op2);
613 if (sym1->nRegs == 0 || sym2->nRegs == 0)
616 for (i = 0; i < sym1->nRegs; i++)
622 for (j = 0; j < sym2->nRegs; j++)
627 if (sym2->regs[j] == sym1->regs[i])
635 /*-----------------------------------------------------------------*/
636 /* operandsEqu - equivalent */
637 /*-----------------------------------------------------------------*/
639 operandsEqu (operand * op1, operand * op2)
643 /* if they not symbols */
644 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
647 sym1 = OP_SYMBOL (op1);
648 sym2 = OP_SYMBOL (op2);
650 /* if both are itemps & one is spilt
651 and the other is not then false */
652 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
653 sym1->isspilt != sym2->isspilt)
656 /* if they are the same */
660 if (strcmp (sym1->rname, sym2->rname) == 0)
664 /* if left is a tmp & right is not */
665 if (IS_ITEMP (op1) &&
668 (sym1->usl.spillLoc == sym2))
671 if (IS_ITEMP (op2) &&
675 (sym2->usl.spillLoc == sym1))
681 /*-----------------------------------------------------------------*/
682 /* sameRegs - two asmops have the same registers */
683 /*-----------------------------------------------------------------*/
685 sameRegs (asmop * aop1, asmop * aop2)
691 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
698 if (aop1->type != AOP_REG ||
699 aop2->type != AOP_REG)
702 if (aop1->size != aop2->size)
705 for (i = 0; i < aop1->size; i++)
706 if (aop1->aopu.aop_reg[i] !=
707 aop2->aopu.aop_reg[i])
713 /*-----------------------------------------------------------------*/
714 /* aopOp - allocates an asmop for an operand : */
715 /*-----------------------------------------------------------------*/
717 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
726 /* if this a literal */
727 if (IS_OP_LITERAL (op))
729 op->aop = aop = newAsmop (AOP_LIT);
730 aop->aopu.aop_lit = op->operand.valOperand;
731 aop->size = getSize (operandType (op));
735 /* if already has a asmop then continue */
739 /* if the underlying symbol has a aop */
740 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
742 op->aop = OP_SYMBOL (op)->aop;
746 /* if this is a true symbol */
747 if (IS_TRUE_SYMOP (op))
749 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
753 /* this is a temporary : this has
759 e) can be a return use only */
761 sym = OP_SYMBOL (op);
764 /* if the type is a conditional */
765 if (sym->regType == REG_CND)
767 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
772 /* if it is spilt then two situations
774 b) has a spill location */
775 if (sym->isspilt || sym->nRegs == 0)
778 /* rematerialize it NOW */
781 sym->aop = op->aop = aop =
783 aop->size = getSize (sym->type);
790 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
791 aop->size = getSize (sym->type);
792 for (i = 0; i < 2; i++)
793 aop->aopu.aop_str[i] = accUse[i];
803 /* a AOP_STR uses DPTR, but DPTR is already in use;
806 fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use! for operand %s\n",sym->name);
809 aop = op->aop = sym->aop = newAsmop (AOP_STR);
810 aop->size = getSize (sym->type);
811 for (i = 0; i < (int) fReturnSizeDS390; i++)
812 aop->aopu.aop_str[i] = fReturn[i];
816 /* else spill location */
817 sym->aop = op->aop = aop =
818 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
819 aop->size = getSize (sym->type);
823 /* must be in a register */
824 sym->aop = op->aop = aop = newAsmop (AOP_REG);
825 aop->size = sym->nRegs;
826 for (i = 0; i < sym->nRegs; i++)
827 aop->aopu.aop_reg[i] = sym->regs[i];
830 /*-----------------------------------------------------------------*/
831 /* freeAsmop - free up the asmop given to an operand */
832 /*----------------------------------------------------------------*/
834 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
851 /* depending on the asmop type only three cases need work AOP_RO
852 , AOP_R1 && AOP_STK */
860 emitcode ("pop", "ar0");
864 bitVectUnSetBit (ic->rUsed, R0_IDX);
872 emitcode ("pop", "ar1");
876 bitVectUnSetBit (ic->rUsed, R1_IDX);
882 int stk = aop->aopu.aop_stk + aop->size;
883 bitVectUnSetBit (ic->rUsed, R0_IDX);
884 bitVectUnSetBit (ic->rUsed, R1_IDX);
886 getFreePtr (ic, &aop, FALSE);
888 if (options.stack10bit)
890 /* I'm not sure what to do here yet... */
893 "*** Warning: probably generating bad code for "
894 "10 bit stack mode.\n");
899 emitcode ("mov", "a,_bp");
900 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
901 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
905 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
910 emitcode ("pop", "acc");
911 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
914 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
917 freeAsmop (op, NULL, ic, TRUE);
920 emitcode ("pop", "ar0");
926 emitcode ("pop", "ar1");
933 /* all other cases just dealloc */
939 OP_SYMBOL (op)->aop = NULL;
940 /* if the symbol has a spill */
942 SPIL_LOC (op)->aop = NULL;
947 /*------------------------------------------------------------------*/
948 /* aopGet - for fetching value of the aop */
950 /* Set canClobberACC if you are sure it is OK to clobber the value */
951 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
952 /* just less efficient. */
953 /*------------------------------------------------------------------*/
965 /* offset is greater than
967 if (offset > (aop->size - 1) &&
968 aop->type != AOP_LIT)
971 /* depending on type */
977 /* if we need to increment it */
978 while (offset > aop->coff)
980 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
984 while (offset < aop->coff)
986 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
993 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
994 return (dname ? "acc" : "a");
996 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
997 rs = Safe_calloc (1, strlen (s) + 1);
1004 if (aop->type == AOP_DPTR2)
1010 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1016 while (offset > aop->coff)
1018 emitcode ("inc", "dptr");
1022 while (offset < aop->coff)
1024 emitcode ("lcall", "__decdptr");
1031 emitcode ("clr", "a");
1032 emitcode ("movc", "a,@a+dptr");
1036 emitcode ("movx", "a,@dptr");
1039 if (aop->type == AOP_DPTR2)
1045 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1046 return DP2_RESULT_REG;
1049 return (dname ? "acc" : "a");
1052 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1053 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1055 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1057 sprintf (s, "#(%s >> %d)",
1058 aop->aopu.aop_immd.aop_immd1,
1062 aop->aopu.aop_immd.aop_immd1);
1063 rs = Safe_calloc (1, strlen (s) + 1);
1069 sprintf (s, "(%s + %d)",
1073 sprintf (s, "%s", aop->aopu.aop_dir);
1074 rs = Safe_calloc (1, strlen (s) + 1);
1080 return aop->aopu.aop_reg[offset]->dname;
1082 return aop->aopu.aop_reg[offset]->name;
1085 emitcode ("clr", "a");
1086 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1087 emitcode ("rlc", "a");
1088 return (dname ? "acc" : "a");
1091 if (!offset && dname)
1093 return aop->aopu.aop_str[offset];
1096 return aopLiteral (aop->aopu.aop_lit, offset);
1100 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1104 return aop->aopu.aop_str[offset];
1108 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1109 "aopget got unsupported aop->type");
1112 /*-----------------------------------------------------------------*/
1113 /* aopPut - puts a string for a aop */
1114 /*-----------------------------------------------------------------*/
1116 aopPut (asmop * aop, char *s, int offset)
1120 if (aop->size && offset > (aop->size - 1))
1122 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1123 "aopPut got offset > aop->size");
1127 /* will assign value to value */
1128 /* depending on where it is ofcourse */
1133 sprintf (d, "(%s + %d)",
1134 aop->aopu.aop_dir, offset);
1136 sprintf (d, "%s", aop->aopu.aop_dir);
1139 emitcode ("mov", "%s,%s", d, s);
1144 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1145 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1148 strcmp (s, "r0") == 0 ||
1149 strcmp (s, "r1") == 0 ||
1150 strcmp (s, "r2") == 0 ||
1151 strcmp (s, "r3") == 0 ||
1152 strcmp (s, "r4") == 0 ||
1153 strcmp (s, "r5") == 0 ||
1154 strcmp (s, "r6") == 0 ||
1155 strcmp (s, "r7") == 0)
1156 emitcode ("mov", "%s,%s",
1157 aop->aopu.aop_reg[offset]->dname, s);
1159 emitcode ("mov", "%s,%s",
1160 aop->aopu.aop_reg[offset]->name, s);
1167 if (aop->type == AOP_DPTR2)
1175 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1176 "aopPut writting to code space");
1180 while (offset > aop->coff)
1183 emitcode ("inc", "dptr");
1186 while (offset < aop->coff)
1189 emitcode ("lcall", "__decdptr");
1194 /* if not in accumulater */
1197 emitcode ("movx", "@dptr,a");
1199 if (aop->type == AOP_DPTR2)
1207 while (offset > aop->coff)
1210 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1212 while (offset < aop->coff)
1215 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1222 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1228 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1230 else if (strcmp (s, "r0") == 0 ||
1231 strcmp (s, "r1") == 0 ||
1232 strcmp (s, "r2") == 0 ||
1233 strcmp (s, "r3") == 0 ||
1234 strcmp (s, "r4") == 0 ||
1235 strcmp (s, "r5") == 0 ||
1236 strcmp (s, "r6") == 0 ||
1237 strcmp (s, "r7") == 0)
1240 sprintf (buffer, "a%s", s);
1241 emitcode ("mov", "@%s,%s",
1242 aop->aopu.aop_ptr->name, buffer);
1245 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1250 if (strcmp (s, "a") == 0)
1251 emitcode ("push", "acc");
1255 emitcode ("push", "acc");
1257 emitcode ("push", s);
1263 /* if bit variable */
1264 if (!aop->aopu.aop_dir)
1266 emitcode ("clr", "a");
1267 emitcode ("rlc", "a");
1272 emitcode ("clr", "%s", aop->aopu.aop_dir);
1274 emitcode ("setb", "%s", aop->aopu.aop_dir);
1275 else if (!strcmp (s, "c"))
1276 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1279 if (strcmp (s, "a"))
1284 symbol *lbl = newiTempLabel (NULL);
1285 emitcode ("clr", "c");
1286 emitcode ("jz", "%05d$", lbl->key + 100);
1287 emitcode ("cpl", "c");
1288 emitcode ("", "%05d$:", lbl->key + 100);
1289 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1297 if (strcmp (aop->aopu.aop_str[offset], s))
1298 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1303 if (!offset && (strcmp (s, "acc") == 0))
1306 if (strcmp (aop->aopu.aop_str[offset], s))
1307 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1311 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1312 "aopPut got unsupported aop->type");
1319 /*--------------------------------------------------------------------*/
1320 /* reAdjustPreg - points a register back to where it should (coff==0) */
1321 /*--------------------------------------------------------------------*/
1323 reAdjustPreg (asmop * aop)
1325 if ((aop->coff==0) || (aop->size <= 1)) {
1334 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1338 if (aop->type == AOP_DPTR2)
1345 emitcode ("lcall", "__decdptr");
1348 if (aop->type == AOP_DPTR2)
1358 #define AOP(op) op->aop
1359 #define AOP_TYPE(op) AOP(op)->type
1360 #define AOP_SIZE(op) AOP(op)->size
1361 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1362 AOP_TYPE(x) == AOP_R0))
1364 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1365 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1368 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1369 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1370 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1372 /* Workaround for DS80C390 bug: div ab may return bogus results
1373 * if A is accessed in instruction immediately before the div.
1375 * Will be fixed in B4 rev of processor, Dallas claims.
1378 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1379 if (!AOP_NEEDSACC(RIGHT)) \
1381 /* We can load A first, then B, since \
1382 * B (the RIGHT operand) won't clobber A, \
1383 * thus avoiding touching A right before the div. \
1385 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1386 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1388 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1392 /* Just stuff in a nop after loading A. */ \
1393 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1394 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1396 emitcode("nop", "; workaround for DS80C390 div bug."); \
1399 /*-----------------------------------------------------------------*/
1400 /* genNotFloat - generates not for float operations */
1401 /*-----------------------------------------------------------------*/
1403 genNotFloat (operand * op, operand * res)
1409 D (emitcode (";", "genNotFloat ");
1412 /* we will put 127 in the first byte of
1414 aopPut (AOP (res), "#127", 0);
1415 size = AOP_SIZE (op) - 1;
1418 _startLazyDPSEvaluation ();
1419 l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1424 emitcode ("orl", "a,%s",
1426 offset++, FALSE, FALSE, FALSE));
1428 _endLazyDPSEvaluation ();
1430 tlbl = newiTempLabel (NULL);
1431 aopPut (res->aop, one, 1);
1432 emitcode ("jz", "%05d$", (tlbl->key + 100));
1433 aopPut (res->aop, zero, 1);
1434 emitcode ("", "%05d$:", (tlbl->key + 100));
1436 size = res->aop->size - 2;
1438 /* put zeros in the rest */
1440 aopPut (res->aop, zero, offset++);
1443 /*-----------------------------------------------------------------*/
1444 /* opIsGptr: returns non-zero if the passed operand is */
1445 /* a generic pointer type. */
1446 /*-----------------------------------------------------------------*/
1448 opIsGptr (operand * op)
1450 sym_link *type = operandType (op);
1452 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1459 /*-----------------------------------------------------------------*/
1460 /* getDataSize - get the operand data size */
1461 /*-----------------------------------------------------------------*/
1463 getDataSize (operand * op)
1466 size = AOP_SIZE (op);
1467 if (size == GPTRSIZE)
1469 sym_link *type = operandType (op);
1470 if (IS_GENPTR (type))
1472 /* generic pointer; arithmetic operations
1473 * should ignore the high byte (pointer type).
1481 /*-----------------------------------------------------------------*/
1482 /* outAcc - output Acc */
1483 /*-----------------------------------------------------------------*/
1485 outAcc (operand * result)
1488 size = getDataSize (result);
1491 aopPut (AOP (result), "a", 0);
1494 /* unsigned or positive */
1497 aopPut (AOP (result), zero, offset++);
1502 /*-----------------------------------------------------------------*/
1503 /* outBitC - output a bit C */
1504 /*-----------------------------------------------------------------*/
1506 outBitC (operand * result)
1508 /* if the result is bit */
1509 if (AOP_TYPE (result) == AOP_CRY)
1511 aopPut (AOP (result), "c", 0);
1515 emitcode ("clr", "a");
1516 emitcode ("rlc", "a");
1521 /*-----------------------------------------------------------------*/
1522 /* toBoolean - emit code for orl a,operator(sizeop) */
1523 /*-----------------------------------------------------------------*/
1525 toBoolean (operand * oper)
1527 int size = AOP_SIZE (oper) - 1;
1531 /* The generic part of a generic pointer should
1532 * not participate in it's truth value.
1534 * i.e. 0x10000000 is zero.
1536 if (opIsGptr (oper))
1538 D (emitcode (";", "toBoolean: generic ptr special case.");
1543 _startLazyDPSEvaluation ();
1544 if (AOP_NEEDSACC (oper) && size)
1547 emitcode ("push", "b");
1548 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1552 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1558 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1562 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1565 _endLazyDPSEvaluation ();
1569 emitcode ("mov", "a,b");
1570 emitcode ("pop", "b");
1575 /*-----------------------------------------------------------------*/
1576 /* genNot - generate code for ! operation */
1577 /*-----------------------------------------------------------------*/
1582 sym_link *optype = operandType (IC_LEFT (ic));
1584 D (emitcode (";", "genNot ");
1587 /* assign asmOps to operand & result */
1588 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1589 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1591 /* if in bit space then a special case */
1592 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1594 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1595 emitcode ("cpl", "c");
1596 outBitC (IC_RESULT (ic));
1600 /* if type float then do float */
1601 if (IS_FLOAT (optype))
1603 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1607 toBoolean (IC_LEFT (ic));
1609 tlbl = newiTempLabel (NULL);
1610 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1611 emitcode ("", "%05d$:", tlbl->key + 100);
1612 outBitC (IC_RESULT (ic));
1615 /* release the aops */
1616 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1617 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1621 /*-----------------------------------------------------------------*/
1622 /* genCpl - generate code for complement */
1623 /*-----------------------------------------------------------------*/
1630 D (emitcode (";", "genCpl ");
1634 /* assign asmOps to operand & result */
1635 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1636 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1638 /* if both are in bit space then
1640 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1641 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1644 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1645 emitcode ("cpl", "c");
1646 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1650 size = AOP_SIZE (IC_RESULT (ic));
1651 _startLazyDPSEvaluation ();
1654 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1656 emitcode ("cpl", "a");
1657 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1659 _endLazyDPSEvaluation ();
1663 /* release the aops */
1664 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1665 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1668 /*-----------------------------------------------------------------*/
1669 /* genUminusFloat - unary minus for floating points */
1670 /*-----------------------------------------------------------------*/
1672 genUminusFloat (operand * op, operand * result)
1674 int size, offset = 0;
1676 /* for this we just need to flip the
1677 first it then copy the rest in place */
1678 D (emitcode (";", "genUminusFloat");
1681 _startLazyDPSEvaluation ();
1682 size = AOP_SIZE (op) - 1;
1683 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1686 emitcode ("cpl", "acc.7");
1687 aopPut (AOP (result), "a", 3);
1691 aopPut (AOP (result),
1692 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1696 _endLazyDPSEvaluation ();
1699 /*-----------------------------------------------------------------*/
1700 /* genUminus - unary minus code generation */
1701 /*-----------------------------------------------------------------*/
1703 genUminus (iCode * ic)
1706 sym_link *optype, *rtype;
1708 D (emitcode (";", "genUminus ");
1713 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1714 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1716 /* if both in bit space then special
1718 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1719 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1722 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1723 emitcode ("cpl", "c");
1724 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1728 optype = operandType (IC_LEFT (ic));
1729 rtype = operandType (IC_RESULT (ic));
1731 /* if float then do float stuff */
1732 if (IS_FLOAT (optype))
1734 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1738 /* otherwise subtract from zero */
1739 size = AOP_SIZE (IC_LEFT (ic));
1741 _startLazyDPSEvaluation ();
1744 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1745 if (!strcmp (l, "a"))
1749 emitcode ("cpl", "a");
1750 emitcode ("addc", "a,#0");
1756 emitcode ("clr", "a");
1757 emitcode ("subb", "a,%s", l);
1759 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1761 _endLazyDPSEvaluation ();
1763 /* if any remaining bytes in the result */
1764 /* we just need to propagate the sign */
1765 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1767 emitcode ("rlc", "a");
1768 emitcode ("subb", "a,acc");
1770 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1774 /* release the aops */
1775 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1776 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1779 /*-----------------------------------------------------------------*/
1780 /* saveRegisters - will look for a call and save the registers */
1781 /*-----------------------------------------------------------------*/
1783 saveRegisters (iCode * lic)
1791 for (ic = lic; ic; ic = ic->next)
1792 if (ic->op == CALL || ic->op == PCALL)
1797 fprintf (stderr, "found parameter push with no function call\n");
1801 /* if the registers have been saved already then
1803 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type) ||
1804 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))))
1807 /* find the registers in use at this time
1808 and push them away to safety */
1809 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1813 if (options.useXstack)
1815 if (bitVectBitValue (rsave, R0_IDX))
1816 emitcode ("mov", "b,r0");
1817 emitcode ("mov", "r0,%s", spname);
1818 for (i = 0; i < ds390_nRegs; i++)
1820 if (bitVectBitValue (rsave, i))
1823 emitcode ("mov", "a,b");
1825 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1826 emitcode ("movx", "@r0,a");
1827 emitcode ("inc", "r0");
1830 emitcode ("mov", "%s,r0", spname);
1831 if (bitVectBitValue (rsave, R0_IDX))
1832 emitcode ("mov", "r0,b");
1835 for (i = 0; i < ds390_nRegs; i++)
1837 if (bitVectBitValue (rsave, i))
1838 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1841 detype = getSpec (operandType (IC_LEFT (ic)));
1844 /*-----------------------------------------------------------------*/
1845 /* unsaveRegisters - pop the pushed registers */
1846 /*-----------------------------------------------------------------*/
1848 unsaveRegisters (iCode * ic)
1852 /* find the registers in use at this time
1853 and push them away to safety */
1854 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1857 if (options.useXstack)
1859 emitcode ("mov", "r0,%s", spname);
1860 for (i = ds390_nRegs; i >= 0; i--)
1862 if (bitVectBitValue (rsave, i))
1864 emitcode ("dec", "r0");
1865 emitcode ("movx", "a,@r0");
1867 emitcode ("mov", "b,a");
1869 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1873 emitcode ("mov", "%s,r0", spname);
1874 if (bitVectBitValue (rsave, R0_IDX))
1875 emitcode ("mov", "r0,b");
1878 for (i = ds390_nRegs; i >= 0; i--)
1880 if (bitVectBitValue (rsave, i))
1881 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1887 /*-----------------------------------------------------------------*/
1889 /*-----------------------------------------------------------------*/
1891 pushSide (operand * oper, int size)
1894 _startLazyDPSEvaluation ();
1897 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1898 if (AOP_TYPE (oper) != AOP_REG &&
1899 AOP_TYPE (oper) != AOP_DIR &&
1902 emitcode ("mov", "a,%s", l);
1903 emitcode ("push", "acc");
1906 emitcode ("push", "%s", l);
1908 _endLazyDPSEvaluation ();
1911 /*-----------------------------------------------------------------*/
1912 /* assignResultValue - */
1913 /*-----------------------------------------------------------------*/
1915 assignResultValue (operand * oper)
1918 int size = AOP_SIZE (oper);
1920 _startLazyDPSEvaluation ();
1923 aopPut (AOP (oper), fReturn[offset], offset);
1926 _endLazyDPSEvaluation ();
1930 /*-----------------------------------------------------------------*/
1931 /* genXpush - pushes onto the external stack */
1932 /*-----------------------------------------------------------------*/
1934 genXpush (iCode * ic)
1936 asmop *aop = newAsmop (0);
1938 int size, offset = 0;
1940 D (emitcode (";", "genXpush ");
1943 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1944 r = getFreePtr (ic, &aop, FALSE);
1947 emitcode ("mov", "%s,_spx", r->name);
1949 size = AOP_SIZE (IC_LEFT (ic));
1950 _startLazyDPSEvaluation ();
1954 char *l = aopGet (AOP (IC_LEFT (ic)),
1955 offset++, FALSE, FALSE, TRUE);
1957 emitcode ("movx", "@%s,a", r->name);
1958 emitcode ("inc", "%s", r->name);
1961 _endLazyDPSEvaluation ();
1964 emitcode ("mov", "_spx,%s", r->name);
1966 freeAsmop (NULL, aop, ic, TRUE);
1967 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1970 /*-----------------------------------------------------------------*/
1971 /* genIpush - genrate code for pushing this gets a little complex */
1972 /*-----------------------------------------------------------------*/
1974 genIpush (iCode * ic)
1976 int size, offset = 0;
1979 D (emitcode (";", "genIpush ");
1982 /* if this is not a parm push : ie. it is spill push
1983 and spill push is always done on the local stack */
1987 /* and the item is spilt then do nothing */
1988 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1991 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1992 size = AOP_SIZE (IC_LEFT (ic));
1993 /* push it on the stack */
1994 _startLazyDPSEvaluation ();
1997 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
2003 emitcode ("push", "%s", l);
2005 _endLazyDPSEvaluation ();
2009 /* this is a paramter push: in this case we call
2010 the routine to find the call and save those
2011 registers that need to be saved */
2014 /* if use external stack then call the external
2015 stack pushing routine */
2016 if (options.useXstack)
2022 /* then do the push */
2023 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2025 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2026 size = AOP_SIZE (IC_LEFT (ic));
2028 _startLazyDPSEvaluation ();
2031 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2032 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2033 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2036 emitcode ("mov", "a,%s", l);
2037 emitcode ("push", "acc");
2040 emitcode ("push", "%s", l);
2042 _endLazyDPSEvaluation ();
2044 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2047 /*-----------------------------------------------------------------*/
2048 /* genIpop - recover the registers: can happen only for spilling */
2049 /*-----------------------------------------------------------------*/
2051 genIpop (iCode * ic)
2055 D (emitcode (";", "genIpop ");
2059 /* if the temp was not pushed then */
2060 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2063 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2064 size = AOP_SIZE (IC_LEFT (ic));
2065 offset = (size - 1);
2066 _startLazyDPSEvaluation ();
2069 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2070 FALSE, TRUE, TRUE));
2072 _endLazyDPSEvaluation ();
2074 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2077 /*-----------------------------------------------------------------*/
2078 /* unsaveRBank - restores the resgister bank from stack */
2079 /*-----------------------------------------------------------------*/
2081 unsaveRBank (int bank, iCode * ic, bool popPsw)
2087 if (options.useXstack)
2091 /* Assume r0 is available for use. */
2092 r = ds390_regWithIdx (R0_IDX);;
2097 r = getFreePtr (ic, &aop, FALSE);
2099 emitcode ("mov", "%s,_spx", r->name);
2104 if (options.useXstack)
2106 emitcode ("movx", "a,@%s", r->name);
2107 emitcode ("mov", "psw,a");
2108 emitcode ("dec", "%s", r->name);
2112 emitcode ("pop", "psw");
2116 for (i = (ds390_nRegs - 1); i >= 0; i--)
2118 if (options.useXstack)
2120 emitcode ("movx", "a,@%s", r->name);
2121 emitcode ("mov", "(%s+%d),a",
2122 regs390[i].base, 8 * bank + regs390[i].offset);
2123 emitcode ("dec", "%s", r->name);
2127 emitcode ("pop", "(%s+%d)",
2128 regs390[i].base, 8 * bank + regs390[i].offset);
2131 if (options.useXstack)
2133 emitcode ("mov", "_spx,%s", r->name);
2138 freeAsmop (NULL, aop, ic, TRUE);
2142 /*-----------------------------------------------------------------*/
2143 /* saveRBank - saves an entire register bank on the stack */
2144 /*-----------------------------------------------------------------*/
2146 saveRBank (int bank, iCode * ic, bool pushPsw)
2152 if (options.useXstack)
2156 /* Assume r0 is available for use. */
2157 r = ds390_regWithIdx (R0_IDX);;
2162 r = getFreePtr (ic, &aop, FALSE);
2164 emitcode ("mov", "%s,_spx", r->name);
2167 for (i = 0; i < ds390_nRegs; i++)
2169 if (options.useXstack)
2171 emitcode ("inc", "%s", r->name);
2172 emitcode ("mov", "a,(%s+%d)",
2173 regs390[i].base, 8 * bank + regs390[i].offset);
2174 emitcode ("movx", "@%s,a", r->name);
2177 emitcode ("push", "(%s+%d)",
2178 regs390[i].base, 8 * bank + regs390[i].offset);
2183 if (options.useXstack)
2185 emitcode ("mov", "a,psw");
2186 emitcode ("movx", "@%s,a", r->name);
2187 emitcode ("inc", "%s", r->name);
2188 emitcode ("mov", "_spx,%s", r->name);
2192 emitcode ("push", "psw");
2195 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2200 freeAsmop (NULL, aop, ic, TRUE);
2209 /*-----------------------------------------------------------------*/
2210 /* genCall - generates a call statement */
2211 /*-----------------------------------------------------------------*/
2213 genCall (iCode * ic)
2216 bool restoreBank = FALSE;
2217 bool swapBanks = FALSE;
2219 D (emitcode (";", "genCall "););
2221 /* if we are calling a not _naked function that is not using
2222 the same register bank then we need to save the
2223 destination registers on the stack */
2224 dtype = operandType (IC_LEFT (ic));
2225 if (dtype && !IFFUNC_ISNAKED(dtype) &&
2226 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2227 IFFUNC_ISISR (currFunc->type))
2231 /* This is unexpected; the bank should have been saved in
2234 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2240 /* if caller saves & we have not saved then */
2244 /* if send set is not empty the assign */
2245 /* We've saved all the registers we care about;
2246 * therefore, we may clobber any register not used
2247 * in the calling convention (i.e. anything not in
2254 for (sic = setFirstItem (_G.sendSet); sic;
2255 sic = setNextItem (_G.sendSet))
2257 int size, offset = 0;
2260 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2261 size = AOP_SIZE (IC_LEFT (sic));
2263 _startLazyDPSEvaluation ();
2266 char *l = aopGet (AOP(IC_LEFT(sic)), offset,
2267 FALSE, FALSE, TRUE);
2268 if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size)
2270 emitcode("mov", "%s,%s", regs390[offset].name, l);
2272 else if (strcmp (l, fReturn[offset]))
2274 emitcode ("mov", "%s,%s",
2280 _endLazyDPSEvaluation ();
2281 if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR)
2283 size = AOP_SIZE (IC_LEFT (sic));
2291 emitcode("mov", "%s,%s",
2292 fReturn[size], regs390[size].name);
2296 // we know that dpl(hxb) is the result, so
2297 _startLazyDPSEvaluation ();
2298 size=getSize(operandType(IC_LEFT(sic)));
2300 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2302 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2306 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2307 FALSE, FALSE, TRUE);
2308 if (strcmp (l, fReturn[offset]))
2310 emitcode ("mov", "%s,%s",
2316 _endLazyDPSEvaluation ();
2318 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2325 emitcode ("mov", "psw,#0x%02x",
2326 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2330 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2331 OP_SYMBOL (IC_LEFT (ic))->rname :
2332 OP_SYMBOL (IC_LEFT (ic))->name));
2336 emitcode ("mov", "psw,#0x%02x",
2337 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2340 /* if we need assign a result value */
2341 if ((IS_ITEMP (IC_RESULT (ic)) &&
2342 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2343 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2344 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2345 IS_TRUE_SYMOP (IC_RESULT (ic)))
2347 if (isOperandInFarSpace (IC_RESULT (ic))
2348 && getSize (operandType (IC_RESULT (ic))) <= 2)
2350 int size = getSize (operandType (IC_RESULT (ic)));
2352 /* Special case for 1 or 2 byte return in far space. */
2356 emitcode ("mov", "b,%s", fReturn[1]);
2359 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2360 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2364 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2366 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2371 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2374 assignResultValue (IC_RESULT (ic));
2376 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2380 /* adjust the stack for parameters if
2382 if (ic->parmBytes) {
2383 if (options.stack10bit) {
2384 emitcode ("clr","c");
2385 emitcode ("mov","a,sp");
2386 emitcode ("subb","a,#0x%02x",ic->parmBytes & 0xff);
2387 emitcode ("mov","sp,a");
2388 emitcode ("mov","a,#0x%02x",(ic->parmBytes >> 8) & 0xff);
2389 emitcode ("subb","a,_ESP");
2390 emitcode ("mov","_ESP,a");
2393 if (ic->parmBytes > 3) {
2394 emitcode ("mov", "a,%s", spname);
2395 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2396 emitcode ("mov", "%s,a", spname);
2398 for (i = 0; i < ic->parmBytes; i++)
2399 emitcode ("dec", "%s", spname);
2403 /* if we hade saved some registers then unsave them */
2404 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2405 unsaveRegisters (ic);
2407 /* if register bank was saved then pop them */
2409 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2412 /*-----------------------------------------------------------------*/
2413 /* genPcall - generates a call by pointer statement */
2414 /*-----------------------------------------------------------------*/
2416 genPcall (iCode * ic)
2419 symbol *rlbl = newiTempLabel (NULL);
2420 bool restoreBank=FALSE;
2422 D (emitcode (";", "genPcall ");
2426 /* if caller saves & we have not saved then */
2430 /* if we are calling a function that is not using
2431 the same register bank then we need to save the
2432 destination registers on the stack */
2433 dtype = operandType (IC_LEFT (ic));
2434 if (dtype && !IFFUNC_ISNAKED(dtype) &&
2435 IFFUNC_ISISR (currFunc->type) &&
2436 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2437 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2441 /* push the return address on to the stack */
2442 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2443 emitcode ("push", "acc");
2444 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2445 emitcode ("push", "acc");
2447 if (options.model == MODEL_FLAT24)
2449 emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2450 emitcode ("push", "acc");
2453 /* now push the calling address */
2454 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2456 pushSide (IC_LEFT (ic), FPTRSIZE);
2458 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2460 /* if send set is not empty the assign */
2465 for (sic = setFirstItem (_G.sendSet); sic;
2466 sic = setNextItem (_G.sendSet))
2468 int size, offset = 0;
2470 // we know that dpl(hxb) is the result, so
2471 _startLazyDPSEvaluation ();
2472 size=getSize(operandType(IC_LEFT(sic)));
2474 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2476 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2480 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2481 FALSE, FALSE, TRUE);
2482 if (strcmp (l, fReturn[offset]))
2484 emitcode ("mov", "%s,%s",
2490 _endLazyDPSEvaluation ();
2491 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2496 emitcode ("ret", "");
2497 emitcode ("", "%05d$:", (rlbl->key + 100));
2500 /* if we need assign a result value */
2501 if ((IS_ITEMP (IC_RESULT (ic)) &&
2502 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2503 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2504 IS_TRUE_SYMOP (IC_RESULT (ic)))
2508 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2511 assignResultValue (IC_RESULT (ic));
2513 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2516 /* adjust the stack for parameters if
2521 if (ic->parmBytes > 3)
2523 emitcode ("mov", "a,%s", spname);
2524 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2525 emitcode ("mov", "%s,a", spname);
2528 for (i = 0; i < ic->parmBytes; i++)
2529 emitcode ("dec", "%s", spname);
2533 /* if register bank was saved then unsave them */
2535 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2537 /* if we hade saved some registers then
2539 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2540 unsaveRegisters (ic);
2544 /*-----------------------------------------------------------------*/
2545 /* resultRemat - result is rematerializable */
2546 /*-----------------------------------------------------------------*/
2548 resultRemat (iCode * ic)
2550 if (SKIP_IC (ic) || ic->op == IFX)
2553 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2555 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2556 if (sym->remat && !POINTER_SET (ic))
2563 #if defined(__BORLANDC__) || defined(_MSC_VER)
2564 #define STRCASECMP stricmp
2566 #define STRCASECMP strcasecmp
2569 /*-----------------------------------------------------------------*/
2570 /* inExcludeList - return 1 if the string is in exclude Reg list */
2571 /*-----------------------------------------------------------------*/
2573 inExcludeList (char *s)
2577 if (options.excludeRegs[i] &&
2578 STRCASECMP (options.excludeRegs[i], "none") == 0)
2581 for (i = 0; options.excludeRegs[i]; i++)
2583 if (options.excludeRegs[i] &&
2584 STRCASECMP (s, options.excludeRegs[i]) == 0)
2590 /*-----------------------------------------------------------------*/
2591 /* genFunction - generated code for function entry */
2592 /*-----------------------------------------------------------------*/
2594 genFunction (iCode * ic)
2598 bool switchedPSW = FALSE;
2600 D (emitcode (";", "genFunction "););
2603 /* create the function header */
2604 emitcode (";", "-----------------------------------------");
2605 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2606 emitcode (";", "-----------------------------------------");
2608 emitcode ("", "%s:", sym->rname);
2609 ftype = operandType (IC_LEFT (ic));
2611 if (IFFUNC_ISNAKED(ftype))
2613 emitcode(";", "naked function: no prologue.");
2617 /* if critical function then turn interrupts off */
2618 if (IFFUNC_ISCRITICAL (ftype))
2619 emitcode ("clr", "ea");
2621 /* here we need to generate the equates for the
2622 register bank if required */
2623 if (FUNC_REGBANK (ftype) != rbank)
2627 rbank = FUNC_REGBANK (ftype);
2628 for (i = 0; i < ds390_nRegs; i++)
2630 if (regs390[i].print) {
2631 if (strcmp (regs390[i].base, "0") == 0)
2632 emitcode ("", "%s = 0x%02x",
2634 8 * rbank + regs390[i].offset);
2636 emitcode ("", "%s = %s + 0x%02x",
2639 8 * rbank + regs390[i].offset);
2644 /* if this is an interrupt service routine then
2645 save acc, b, dpl, dph */
2646 if (IFFUNC_ISISR (sym->type))
2649 if (!inExcludeList ("acc"))
2650 emitcode ("push", "acc");
2651 if (!inExcludeList ("b"))
2652 emitcode ("push", "b");
2653 if (!inExcludeList ("dpl"))
2654 emitcode ("push", "dpl");
2655 if (!inExcludeList ("dph"))
2656 emitcode ("push", "dph");
2657 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2659 emitcode ("push", "dpx");
2660 /* Make sure we're using standard DPTR */
2661 emitcode ("push", "dps");
2662 emitcode ("mov", "dps, #0x00");
2663 if (options.stack10bit)
2665 /* This ISR could conceivably use DPTR2. Better save it. */
2666 emitcode ("push", "dpl1");
2667 emitcode ("push", "dph1");
2668 emitcode ("push", "dpx1");
2669 emitcode ("push", DP2_RESULT_REG);
2672 /* if this isr has no bank i.e. is going to
2673 run with bank 0 , then we need to save more
2675 if (!FUNC_REGBANK (sym->type))
2678 /* if this function does not call any other
2679 function then we can be economical and
2680 save only those registers that are used */
2681 if (!IFFUNC_HASFCALL(sym->type))
2685 /* if any registers used */
2688 /* save the registers used */
2689 for (i = 0; i < sym->regsUsed->size; i++)
2691 if (bitVectBitValue (sym->regsUsed, i) ||
2692 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2693 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2700 /* this function has a function call cannot
2701 determines register usage so we will have to push the
2703 saveRBank (0, ic, FALSE);
2708 /* This ISR uses a non-zero bank.
2710 * We assume that the bank is available for our
2713 * However, if this ISR calls a function which uses some
2714 * other bank, we must save that bank entirely.
2716 unsigned long banksToSave = 0;
2718 if (IFFUNC_HASFCALL(sym->type))
2721 #define MAX_REGISTER_BANKS 4
2726 for (i = ic; i; i = i->next)
2728 if (i->op == ENDFUNCTION)
2730 /* we got to the end OK. */
2738 dtype = operandType (IC_LEFT(i));
2740 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2742 /* Mark this bank for saving. */
2743 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2745 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2749 banksToSave |= (1 << FUNC_REGBANK(dtype));
2752 /* And note that we don't need to do it in
2760 /* This is a mess; we have no idea what
2761 * register bank the called function might
2764 * The only thing I can think of to do is
2765 * throw a warning and hope.
2767 werror(W_FUNCPTR_IN_USING_ISR);
2771 if (banksToSave && options.useXstack)
2773 /* Since we aren't passing it an ic,
2774 * saveRBank will assume r0 is available to abuse.
2776 * So switch to our (trashable) bank now, so
2777 * the caller's R0 isn't trashed.
2779 emitcode ("push", "psw");
2780 emitcode ("mov", "psw,#0x%02x",
2781 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2785 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2787 if (banksToSave & (1 << ix))
2789 saveRBank(ix, NULL, FALSE);
2793 // jwk: this needs a closer look
2794 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2799 /* if callee-save to be used for this function
2800 then save the registers being used in this function */
2801 if (IFFUNC_CALLEESAVES(sym->type))
2805 /* if any registers used */
2808 /* save the registers used */
2809 for (i = 0; i < sym->regsUsed->size; i++)
2811 if (bitVectBitValue (sym->regsUsed, i) ||
2812 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2814 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2822 /* set the register bank to the desired value */
2823 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2826 emitcode ("push", "psw");
2827 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2830 if (IFFUNC_ISREENT (sym->type) || options.stackAuto) {
2831 if (options.stack10bit) {
2832 emitcode ("push","_bpx");
2833 emitcode ("push","_bpx+1");
2834 emitcode ("mov","_bpx,%s",spname);
2835 emitcode ("mov","_bpx+1,_ESP");
2836 emitcode ("anl","_bpx+1,#3");
2838 if (options.useXstack) {
2839 emitcode ("mov", "r0,%s", spname);
2840 emitcode ("mov", "a,_bp");
2841 emitcode ("movx", "@r0,a");
2842 emitcode ("inc", "%s", spname);
2844 /* set up the stack */
2845 emitcode ("push", "_bp"); /* save the callers stack */
2847 emitcode ("mov", "_bp,%s", spname);
2851 /* adjust the stack for the function */
2854 if (options.stack10bit) {
2855 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
2856 assert (sym->recvSize <= 4);
2857 emitcode ("mov","a,sp");
2858 emitcode ("add","a,#0x%02x", ((short) sym->stack & 0xff));
2859 emitcode ("mov","sp,a");
2860 emitcode ("mov","a,_ESP");
2861 emitcode ("addc","a,0x%02x", (((short) sym->stack) >> 8) & 0xff);
2862 emitcode ("mov","_ESP,a");
2865 werror (W_STACK_OVERFLOW, sym->name);
2867 if (i > 3 && sym->recvSize < 4) {
2869 emitcode ("mov", "a,sp");
2870 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2871 emitcode ("mov", "sp,a");
2875 emitcode ("inc", "sp");
2882 emitcode ("mov", "a,_spx");
2883 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2884 emitcode ("mov", "_spx,a");
2889 /*-----------------------------------------------------------------*/
2890 /* genEndFunction - generates epilogue for functions */
2891 /*-----------------------------------------------------------------*/
2893 genEndFunction (iCode * ic)
2895 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2897 D (emitcode (";", "genEndFunction "););
2899 if (IFFUNC_ISNAKED(sym->type))
2901 emitcode(";", "naked function: no epilogue.");
2905 if (IFFUNC_ISREENT (sym->type) || options.stackAuto) {
2906 if (options.stack10bit) {
2907 emitcode ("mov", "sp,_bpx", spname);
2908 emitcode ("mov", "_ESP,_bpx+1", spname);
2910 emitcode ("mov", "%s,_bp", spname);
2914 /* if use external stack but some variables were
2915 added to the local stack then decrement the
2917 if (options.useXstack && sym->stack) {
2918 emitcode ("mov", "a,sp");
2919 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2920 emitcode ("mov", "sp,a");
2924 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto)) {
2925 if (options.useXstack) {
2926 emitcode ("mov", "r0,%s", spname);
2927 emitcode ("movx", "a,@r0");
2928 emitcode ("mov", "_bp,a");
2929 emitcode ("dec", "%s", spname);
2931 if (options.stack10bit) {
2932 emitcode ("pop", "_bpx+1");
2933 emitcode ("pop", "_bpx");
2935 emitcode ("pop", "_bp");
2940 /* restore the register bank */
2941 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2943 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
2944 || !options.useXstack)
2946 /* Special case of ISR using non-zero bank with useXstack
2949 emitcode ("pop", "psw");
2953 if (IFFUNC_ISISR (sym->type))
2956 /* now we need to restore the registers */
2957 /* if this isr has no bank i.e. is going to
2958 run with bank 0 , then we need to save more
2960 if (!FUNC_REGBANK (sym->type))
2962 /* if this function does not call any other
2963 function then we can be economical and
2964 save only those registers that are used */
2965 if (!IFFUNC_HASFCALL(sym->type))
2969 /* if any registers used */
2972 /* save the registers used */
2973 for (i = sym->regsUsed->size; i >= 0; i--)
2975 if (bitVectBitValue (sym->regsUsed, i) ||
2976 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2977 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2984 /* this function has a function call cannot
2985 determines register usage so we will have to pop the
2987 unsaveRBank (0, ic, FALSE);
2992 /* This ISR uses a non-zero bank.
2994 * Restore any register banks saved by genFunction
2997 // jwk: this needs a closer look
2998 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3001 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3003 if (savedBanks & (1 << ix))
3005 unsaveRBank(ix, NULL, FALSE);
3009 if (options.useXstack)
3011 /* Restore bank AFTER calling unsaveRBank,
3012 * since it can trash r0.
3014 emitcode ("pop", "psw");
3018 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3020 if (options.stack10bit)
3022 emitcode ("pop", DP2_RESULT_REG);
3023 emitcode ("pop", "dpx1");
3024 emitcode ("pop", "dph1");
3025 emitcode ("pop", "dpl1");
3027 emitcode ("pop", "dps");
3028 emitcode ("pop", "dpx");
3030 if (!inExcludeList ("dph"))
3031 emitcode ("pop", "dph");
3032 if (!inExcludeList ("dpl"))
3033 emitcode ("pop", "dpl");
3034 if (!inExcludeList ("b"))
3035 emitcode ("pop", "b");
3036 if (!inExcludeList ("acc"))
3037 emitcode ("pop", "acc");
3039 if (IFFUNC_ISCRITICAL (sym->type))
3040 emitcode ("setb", "ea");
3042 /* if debug then send end of function */
3043 if (options.debug && currFunc) {
3045 emitcode ("", "C$%s$%d$%d$%d ==.",
3046 FileBaseName (ic->filename), currFunc->lastLine,
3047 ic->level, ic->block);
3048 if (IS_STATIC (currFunc->etype))
3049 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3051 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3055 emitcode ("reti", "");
3059 if (IFFUNC_ISCRITICAL (sym->type))
3060 emitcode ("setb", "ea");
3062 if (IFFUNC_CALLEESAVES(sym->type))
3066 /* if any registers used */
3069 /* save the registers used */
3070 for (i = sym->regsUsed->size; i >= 0; i--)
3072 if (bitVectBitValue (sym->regsUsed, i) ||
3073 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3074 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3080 /* if debug then send end of function */
3081 if (options.debug && currFunc)
3084 emitcode ("", "C$%s$%d$%d$%d ==.",
3085 FileBaseName (ic->filename), currFunc->lastLine,
3086 ic->level, ic->block);
3087 if (IS_STATIC (currFunc->etype))
3088 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3090 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3094 emitcode ("ret", "");
3099 /*-----------------------------------------------------------------*/
3100 /* genRet - generate code for return statement */
3101 /*-----------------------------------------------------------------*/
3105 int size, offset = 0, pushed = 0;
3107 D (emitcode (";", "genRet ");
3110 /* if we have no return value then
3111 just generate the "ret" */
3115 /* we have something to return then
3116 move the return value into place */
3117 aopOp (IC_LEFT (ic), ic, FALSE,
3118 (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3119 size = AOP_SIZE (IC_LEFT (ic));
3121 _startLazyDPSEvaluation ();
3125 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3127 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3128 FALSE, TRUE, FALSE);
3129 emitcode ("push", "%s", l);
3134 /* Since A is the last element of fReturn,
3135 * is is OK to clobber it in the aopGet.
3137 l = aopGet (AOP (IC_LEFT (ic)), offset,
3138 FALSE, FALSE, TRUE);
3139 if (strcmp (fReturn[offset], l))
3140 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3143 _endLazyDPSEvaluation ();
3150 if (strcmp (fReturn[pushed], "a"))
3151 emitcode ("pop", fReturn[pushed]);
3153 emitcode ("pop", "acc");
3156 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3159 /* generate a jump to the return label
3160 if the next is not the return statement */
3161 if (!(ic->next && ic->next->op == LABEL &&
3162 IC_LABEL (ic->next) == returnLabel))
3164 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3168 /*-----------------------------------------------------------------*/
3169 /* genLabel - generates a label */
3170 /*-----------------------------------------------------------------*/
3172 genLabel (iCode * ic)
3174 /* special case never generate */
3175 if (IC_LABEL (ic) == entryLabel)
3178 D (emitcode (";", "genLabel ");
3181 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3184 /*-----------------------------------------------------------------*/
3185 /* genGoto - generates a ljmp */
3186 /*-----------------------------------------------------------------*/
3188 genGoto (iCode * ic)
3190 D (emitcode (";", "genGoto ");
3192 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3195 /*-----------------------------------------------------------------*/
3196 /* findLabelBackwards: walks back through the iCode chain looking */
3197 /* for the given label. Returns number of iCode instructions */
3198 /* between that label and given ic. */
3199 /* Returns zero if label not found. */
3200 /*-----------------------------------------------------------------*/
3202 findLabelBackwards (iCode * ic, int key)
3211 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3213 /* printf("findLabelBackwards = %d\n", count); */
3221 /*-----------------------------------------------------------------*/
3222 /* genPlusIncr :- does addition with increment if possible */
3223 /*-----------------------------------------------------------------*/
3225 genPlusIncr (iCode * ic)
3227 unsigned int icount;
3228 unsigned int size = getDataSize (IC_RESULT (ic));
3230 /* will try to generate an increment */
3231 /* if the right side is not a literal
3233 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3236 /* if the literal value of the right hand side
3237 is greater than 4 then it is not worth it */
3238 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3241 /* if increment 16 bits in register */
3243 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3244 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3245 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3253 /* If the next instruction is a goto and the goto target
3254 * is <= 5 instructions previous to this, we can generate
3255 * jumps straight to that target.
3257 if (ic->next && ic->next->op == GOTO
3258 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3261 emitcode (";", "tail increment optimized (range %d)", labelRange);
3262 tlbl = IC_LABEL (ic->next);
3267 tlbl = newiTempLabel (NULL);
3270 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3271 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3272 IS_AOP_PREG (IC_RESULT (ic)))
3273 emitcode ("cjne", "%s,#0x00,%05d$"
3274 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3278 emitcode ("clr", "a");
3279 emitcode ("cjne", "a,%s,%05d$"
3280 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3284 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3287 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3288 IS_AOP_PREG (IC_RESULT (ic)))
3289 emitcode ("cjne", "%s,#0x00,%05d$"
3290 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3293 emitcode ("cjne", "a,%s,%05d$"
3294 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3297 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3301 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3302 IS_AOP_PREG (IC_RESULT (ic)))
3303 emitcode ("cjne", "%s,#0x00,%05d$"
3304 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3308 emitcode ("cjne", "a,%s,%05d$"
3309 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3312 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3317 emitcode ("", "%05d$:", tlbl->key + 100);
3322 /* if the sizes are greater than 1 then we cannot */
3323 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3324 AOP_SIZE (IC_LEFT (ic)) > 1)
3327 /* we can if the aops of the left & result match or
3328 if they are in registers and the registers are the
3331 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3332 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3333 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3338 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3339 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3340 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3345 _startLazyDPSEvaluation ();
3348 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3350 _endLazyDPSEvaluation ();
3359 /*-----------------------------------------------------------------*/
3360 /* outBitAcc - output a bit in acc */
3361 /*-----------------------------------------------------------------*/
3363 outBitAcc (operand * result)
3365 symbol *tlbl = newiTempLabel (NULL);
3366 /* if the result is a bit */
3367 if (AOP_TYPE (result) == AOP_CRY)
3369 aopPut (AOP (result), "a", 0);
3373 emitcode ("jz", "%05d$", tlbl->key + 100);
3374 emitcode ("mov", "a,%s", one);
3375 emitcode ("", "%05d$:", tlbl->key + 100);
3380 /*-----------------------------------------------------------------*/
3381 /* genPlusBits - generates code for addition of two bits */
3382 /*-----------------------------------------------------------------*/
3384 genPlusBits (iCode * ic)
3386 D (emitcode (";", "genPlusBits ");
3388 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3390 symbol *lbl = newiTempLabel (NULL);
3391 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3392 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3393 emitcode ("cpl", "c");
3394 emitcode ("", "%05d$:", (lbl->key + 100));
3395 outBitC (IC_RESULT (ic));
3399 emitcode ("clr", "a");
3400 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3401 emitcode ("rlc", "a");
3402 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3403 emitcode ("addc", "a,#0x00");
3404 outAcc (IC_RESULT (ic));
3409 adjustArithmeticResult (iCode * ic)
3411 if (opIsGptr (IC_RESULT (ic)) &&
3412 opIsGptr (IC_LEFT (ic)) &&
3413 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3415 aopPut (AOP (IC_RESULT (ic)),
3416 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3420 if (opIsGptr (IC_RESULT (ic)) &&
3421 opIsGptr (IC_RIGHT (ic)) &&
3422 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3424 aopPut (AOP (IC_RESULT (ic)),
3425 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3429 if (opIsGptr (IC_RESULT (ic)) &&
3430 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3431 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3432 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3433 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3436 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3437 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3441 #if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
3442 // Please don't bring it back without a really good reason.
3443 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3444 // (because all three operands are in far space).
3445 #define AOP_OP_3(ic) \
3446 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3447 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3448 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3449 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3450 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3451 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3453 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3455 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3459 // Macro to aopOp all three operands of an ic. If this cannot be done,
3460 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3461 // will be set TRUE. The caller must then handle the case specially, noting
3462 // that the IC_RESULT operand is not aopOp'd.
3463 #define AOP_OP_3_NOFATAL(ic, rc) \
3464 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3465 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR) || \
3466 (OP_SYMBOL(IC_RESULT(ic))->ruonly)); \
3467 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3468 (isOperandInFarSpace(IC_RESULT(ic)) || OP_SYMBOL(IC_RESULT(ic))->ruonly )) \
3470 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3475 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3476 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3478 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3479 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3481 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3483 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3487 // aopOp the left & right operands of an ic.
3488 #define AOP_OP_2(ic) \
3489 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3490 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3492 // convienience macro.
3493 #define AOP_SET_LOCALS(ic) \
3494 left = IC_LEFT(ic); \
3495 right = IC_RIGHT(ic); \
3496 result = IC_RESULT(ic);
3499 // Given an integer value of pushedSize bytes on the stack,
3500 // adjust it to be resultSize bytes, either by discarding
3501 // the most significant bytes or by zero-padding.
3503 // On exit from this macro, pushedSize will have been adjusted to
3504 // equal resultSize, and ACC may be trashed.
3505 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3506 /* If the pushed data is bigger than the result, \
3507 * simply discard unused bytes. Icky, but works. \
3509 while (pushedSize > resultSize) \
3511 D (emitcode (";", "discarding unused result byte."););\
3512 emitcode ("pop", "acc"); \
3515 if (pushedSize < resultSize) \
3517 emitcode ("clr", "a"); \
3518 /* Conversly, we haven't pushed enough here. \
3519 * just zero-pad, and all is well. \
3521 while (pushedSize < resultSize) \
3523 emitcode("push", "acc"); \
3527 assert(pushedSize == resultSize);
3529 /*-----------------------------------------------------------------*/
3530 /* genPlus - generates code for addition */
3531 /*-----------------------------------------------------------------*/
3533 genPlus (iCode * ic)
3535 int size, offset = 0;
3536 bool pushResult = FALSE;
3539 D (emitcode (";", "genPlus "););
3541 /* special cases :- */
3542 if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) &&
3543 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3544 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3545 size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3546 while (size--) emitcode ("inc","dptr");
3547 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3550 if ( IS_SYMOP(IC_LEFT(ic)) &&
3551 OP_SYMBOL(IC_LEFT(ic))->remat &&
3552 isOperandInFarSpace(IC_RIGHT(ic))) {
3553 operand *op = IC_RIGHT(ic);
3554 IC_RIGHT(ic) = IC_LEFT(ic);
3558 AOP_OP_3_NOFATAL (ic, pushResult);
3561 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3566 /* if literal, literal on the right or
3567 if left requires ACC or right is already
3569 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3570 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3571 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3573 operand *t = IC_RIGHT (ic);
3574 IC_RIGHT (ic) = IC_LEFT (ic);
3576 emitcode (";", "Swapped plus args.");
3579 /* if both left & right are in bit
3581 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3582 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3588 /* if left in bit space & right literal */
3589 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3590 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3592 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3593 /* if result in bit space */
3594 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3596 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3597 emitcode ("cpl", "c");
3598 outBitC (IC_RESULT (ic));
3602 size = getDataSize (IC_RESULT (ic));
3603 _startLazyDPSEvaluation ();
3606 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3607 emitcode ("addc", "a,#00");
3608 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3610 _endLazyDPSEvaluation ();
3615 /* if I can do an increment instead
3616 of add then GOOD for ME */
3617 if (genPlusIncr (ic) == TRUE)
3619 emitcode (";", "did genPlusIncr");
3624 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3626 _startLazyDPSEvaluation ();
3629 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3631 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3633 emitcode ("add", "a,%s",
3634 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3636 emitcode ("addc", "a,%s",
3637 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3641 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3643 /* right is going to use ACC or we would have taken the
3646 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3648 D(emitcode(";", "+ AOP_ACC special case."););
3649 emitcode("xch", "a, %s", DP2_RESULT_REG);
3651 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3654 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3657 emitcode("add", "a, %s", DP2_RESULT_REG);
3661 emitcode ("add", "a,%s",
3662 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3667 emitcode ("addc", "a,%s",
3668 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3673 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3677 emitcode ("push", "acc");
3681 _endLazyDPSEvaluation ();
3685 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3687 size = getDataSize (IC_LEFT (ic));
3688 rSize = getDataSize (IC_RESULT (ic));
3690 ADJUST_PUSHED_RESULT(size, rSize);
3692 _startLazyDPSEvaluation ();
3695 emitcode ("pop", "acc");
3696 aopPut (AOP (IC_RESULT (ic)), "a", size);
3698 _endLazyDPSEvaluation ();
3701 adjustArithmeticResult (ic);
3704 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3705 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3706 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3709 /*-----------------------------------------------------------------*/
3710 /* genMinusDec :- does subtraction with deccrement if possible */
3711 /*-----------------------------------------------------------------*/
3713 genMinusDec (iCode * ic)
3715 unsigned int icount;
3716 unsigned int size = getDataSize (IC_RESULT (ic));
3718 /* will try to generate an increment */
3719 /* if the right side is not a literal
3721 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3724 /* if the literal value of the right hand side
3725 is greater than 4 then it is not worth it */
3726 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3729 /* if decrement 16 bits in register */
3730 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3731 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3732 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3740 /* If the next instruction is a goto and the goto target
3741 * is <= 5 instructions previous to this, we can generate
3742 * jumps straight to that target.
3744 if (ic->next && ic->next->op == GOTO
3745 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3748 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3749 tlbl = IC_LABEL (ic->next);
3754 tlbl = newiTempLabel (NULL);
3758 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3759 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3760 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3761 IS_AOP_PREG (IC_RESULT (ic)))
3762 emitcode ("cjne", "%s,#0xff,%05d$"
3763 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3767 emitcode ("mov", "a,#0xff");
3768 emitcode ("cjne", "a,%s,%05d$"
3769 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3772 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3775 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3776 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3777 IS_AOP_PREG (IC_RESULT (ic)))
3778 emitcode ("cjne", "%s,#0xff,%05d$"
3779 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3783 emitcode ("cjne", "a,%s,%05d$"
3784 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3787 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3791 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3792 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3793 IS_AOP_PREG (IC_RESULT (ic)))
3794 emitcode ("cjne", "%s,#0xff,%05d$"
3795 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3799 emitcode ("cjne", "a,%s,%05d$"
3800 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3803 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3807 emitcode ("", "%05d$:", tlbl->key + 100);
3812 /* if the sizes are greater than 1 then we cannot */
3813 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3814 AOP_SIZE (IC_LEFT (ic)) > 1)
3817 /* we can if the aops of the left & result match or
3818 if they are in registers and the registers are the
3821 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3822 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3823 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3826 _startLazyDPSEvaluation ();
3829 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3831 _endLazyDPSEvaluation ();
3839 /*-----------------------------------------------------------------*/
3840 /* addSign - complete with sign */
3841 /*-----------------------------------------------------------------*/
3843 addSign (operand * result, int offset, int sign)
3845 int size = (getDataSize (result) - offset);
3848 _startLazyDPSEvaluation();
3851 emitcode ("rlc", "a");
3852 emitcode ("subb", "a,acc");
3855 aopPut (AOP (result), "a", offset++);
3862 aopPut (AOP (result), zero, offset++);
3865 _endLazyDPSEvaluation();
3869 /*-----------------------------------------------------------------*/
3870 /* genMinusBits - generates code for subtraction of two bits */
3871 /*-----------------------------------------------------------------*/
3873 genMinusBits (iCode * ic)
3875 symbol *lbl = newiTempLabel (NULL);
3877 D (emitcode (";", "genMinusBits "););
3879 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3881 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3882 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3883 emitcode ("cpl", "c");
3884 emitcode ("", "%05d$:", (lbl->key + 100));
3885 outBitC (IC_RESULT (ic));
3889 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3890 emitcode ("subb", "a,acc");
3891 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3892 emitcode ("inc", "a");
3893 emitcode ("", "%05d$:", (lbl->key + 100));
3894 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3895 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3899 /*-----------------------------------------------------------------*/
3900 /* genMinus - generates code for subtraction */
3901 /*-----------------------------------------------------------------*/
3903 genMinus (iCode * ic)
3905 int size, offset = 0;
3907 unsigned long lit = 0L;
3908 bool pushResult = FALSE;
3910 D (emitcode (";", "genMinus "););
3912 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3913 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3914 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3915 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3921 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3923 /* special cases :- */
3924 /* if both left & right are in bit space */
3925 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3926 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3932 /* if I can do an decrement instead
3933 of subtract then GOOD for ME */
3934 if (genMinusDec (ic) == TRUE)
3939 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3941 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3947 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3952 /* if literal, add a,#-lit, else normal subb */
3953 _startLazyDPSEvaluation ();
3956 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3957 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3958 emitcode ("subb", "a,%s",
3959 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3962 /* first add without previous c */
3964 if (!size && lit==-1) {
3965 emitcode ("dec", "a");
3967 emitcode ("add", "a,#0x%02x",
3968 (unsigned int) (lit & 0x0FFL));
3971 emitcode ("addc", "a,#0x%02x",
3972 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3978 emitcode ("push", "acc");
3982 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3986 _endLazyDPSEvaluation ();
3990 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3992 size = getDataSize (IC_LEFT (ic));
3993 rSize = getDataSize (IC_RESULT (ic));
3995 ADJUST_PUSHED_RESULT(size, rSize);
3997 _startLazyDPSEvaluation ();
4000 emitcode ("pop", "acc");
4001 aopPut (AOP (IC_RESULT (ic)), "a", size);
4003 _endLazyDPSEvaluation ();
4006 adjustArithmeticResult (ic);
4009 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4010 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4011 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4015 /*-----------------------------------------------------------------*/
4016 /* genMultbits :- multiplication of bits */
4017 /*-----------------------------------------------------------------*/
4019 genMultbits (operand * left,
4024 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4025 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4026 aopOp(result, ic, TRUE, FALSE);
4031 /*-----------------------------------------------------------------*/
4032 /* genMultOneByte : 8*8=8/16 bit multiplication */
4033 /*-----------------------------------------------------------------*/
4035 genMultOneByte (operand * left,
4040 sym_link *opetype = operandType (result);
4044 /* (if two literals: the value is computed before) */
4045 /* if one literal, literal on the right */
4046 if (AOP_TYPE (left) == AOP_LIT)
4051 emitcode (";", "swapped left and right");
4054 if (SPEC_USIGN(opetype)
4055 // ignore the sign of left and right, what else can we do?
4056 || (SPEC_USIGN(operandType(left)) &&
4057 SPEC_USIGN(operandType(right)))) {
4058 // just an unsigned 8*8=8/16 multiply
4059 //emitcode (";","unsigned");
4060 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4061 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4062 emitcode ("mul", "ab");
4065 aopOp(result, ic, TRUE, FALSE);
4067 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4069 // this should never happen
4070 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4071 AOP_SIZE(result), __FILE__, lineno);
4075 aopPut (AOP (result), "a", 0);
4077 if (AOP_SIZE(result)==2)
4079 aopPut (AOP (result), "b", 1);
4084 // we have to do a signed multiply
4086 emitcode (";", "signed");
4087 emitcode ("clr", "F0"); // reset sign flag
4088 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4090 lbl=newiTempLabel(NULL);
4091 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
4092 // left side is negative, 8-bit two's complement, this fails for -128
4093 emitcode ("setb", "F0"); // set sign flag
4094 emitcode ("cpl", "a");
4095 emitcode ("inc", "a");
4097 emitcode ("", "%05d$:", lbl->key+100);
4100 if (AOP_TYPE(right)==AOP_LIT) {
4101 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4102 /* AND literal negative */
4103 if ((int) val < 0) {
4104 emitcode ("cpl", "F0"); // complement sign flag
4105 emitcode ("mov", "b,#0x%02x", -val);
4107 emitcode ("mov", "b,#0x%02x", val);
4110 lbl=newiTempLabel(NULL);
4111 emitcode ("mov", "b,a");
4112 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4113 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
4114 // right side is negative, 8-bit two's complement
4115 emitcode ("cpl", "F0"); // complement sign flag
4116 emitcode ("cpl", "a");
4117 emitcode ("inc", "a");
4118 emitcode ("", "%05d$:", lbl->key+100);
4120 emitcode ("mul", "ab");
4123 aopOp(result, ic, TRUE, FALSE);
4125 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4127 // this should never happen
4128 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4129 AOP_SIZE(result), __FILE__, lineno);
4133 lbl=newiTempLabel(NULL);
4134 emitcode ("jnb", "F0,%05d$", lbl->key+100);
4135 // only ONE op was negative, we have to do a 8/16-bit two's complement
4136 emitcode ("cpl", "a"); // lsb
4137 if (AOP_SIZE(result)==1) {
4138 emitcode ("inc", "a");
4140 emitcode ("add", "a,#1");
4141 emitcode ("xch", "a,b");
4142 emitcode ("cpl", "a"); // msb
4143 emitcode ("addc", "a,#0");
4144 emitcode ("xch", "a,b");
4147 emitcode ("", "%05d$:", lbl->key+100);
4148 aopPut (AOP (result), "a", 0);
4150 if (AOP_SIZE(result)==2) {
4151 aopPut (AOP (result), "b", 1);
4155 /*-----------------------------------------------------------------*/
4156 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4157 /*-----------------------------------------------------------------*/
4158 static void genMultTwoByte (operand *left, operand *right,
4159 operand *result, iCode *ic)
4161 sym_link *retype = getSpec(operandType(right));
4162 sym_link *letype = getSpec(operandType(left));
4163 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4166 if (AOP_TYPE (left) == AOP_LIT) {
4171 /* save EA bit in F1 */
4172 lbl = newiTempLabel(NULL);
4173 emitcode ("setb","F1");
4174 emitcode ("jbc","EA,%05d$",lbl->key+100);
4175 emitcode ("clr","F1");
4176 emitcode("","%05d$:",lbl->key+100);
4178 /* load up MB with right */
4180 emitcode("clr","F0");
4181 if (AOP_TYPE(right) == AOP_LIT) {
4182 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4184 emitcode("setb","F0");
4187 emitcode ("mov","mb,#0x%02x",val & 0xff);
4188 emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4190 lbl = newiTempLabel(NULL);
4191 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4192 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4193 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4194 emitcode ("xch", "a,b");
4195 emitcode ("cpl","a");
4196 emitcode ("add", "a,#1");
4197 emitcode ("xch", "a,b");
4198 emitcode ("cpl", "a"); // msb
4199 emitcode ("addc", "a,#0");
4200 emitcode ("setb","F0");
4201 emitcode ("","%05d$:",lbl->key+100);
4202 emitcode ("mov","mb,b");
4203 emitcode ("mov","mb,a");
4206 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4207 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4209 /* load up MA with left */
4211 lbl = newiTempLabel(NULL);
4212 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4213 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4214 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4215 emitcode ("xch", "a,b");
4216 emitcode ("cpl","a");
4217 emitcode ("add", "a,#1");
4218 emitcode ("xch", "a,b");
4219 emitcode ("cpl", "a"); // msb
4220 emitcode ("addc","a,#0");
4221 emitcode ("jbc","F0,%05d$",lbl->key+100);
4222 emitcode ("setb","F0");
4223 emitcode ("","%05d$:",lbl->key+100);
4224 emitcode ("mov","ma,b");
4225 emitcode ("mov","ma,a");
4227 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4228 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4230 /* wait for multiplication to finish */
4231 lbl = newiTempLabel(NULL);
4232 emitcode("","%05d$:", lbl->key+100);
4233 emitcode("mov","a,mcnt1");
4234 emitcode("anl","a,#0x80");
4235 emitcode("jnz","%05d$",lbl->key+100);
4237 freeAsmop (left, NULL, ic, TRUE);
4238 freeAsmop (right, NULL, ic,TRUE);
4239 aopOp(result, ic, TRUE, FALSE);
4241 /* if unsigned then simple */
4243 emitcode ("mov","a,ma");
4244 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4245 emitcode ("mov","a,ma");
4246 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4247 aopPut(AOP(result),"ma",1);
4248 aopPut(AOP(result),"ma",0);
4250 emitcode("push","ma");
4251 emitcode("push","ma");
4252 emitcode("push","ma");
4254 /* negate result if needed */
4255 lbl = newiTempLabel(NULL);
4256 emitcode("jnb","F0,%05d$",lbl->key+100);
4257 emitcode("cpl","a");
4258 emitcode("add","a,#1");
4259 emitcode("","%05d$:", lbl->key+100);
4260 if (AOP_TYPE(result) == AOP_ACC)
4262 D(emitcode(";", "ACC special case."););
4263 /* We know result is the only live aop, and
4264 * it's obviously not a DPTR2, so AP is available.
4266 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4270 aopPut(AOP(result),"a",0);
4273 emitcode("pop","acc");
4274 lbl = newiTempLabel(NULL);
4275 emitcode("jnb","F0,%05d$",lbl->key+100);
4276 emitcode("cpl","a");
4277 emitcode("addc","a,#0");
4278 emitcode("","%05d$:", lbl->key+100);
4279 aopPut(AOP(result),"a",1);
4280 emitcode("pop","acc");
4281 if (AOP_SIZE(result) >= 3) {
4282 lbl = newiTempLabel(NULL);
4283 emitcode("jnb","F0,%05d$",lbl->key+100);
4284 emitcode("cpl","a");
4285 emitcode("addc","a,#0");
4286 emitcode("","%05d$:", lbl->key+100);
4287 aopPut(AOP(result),"a",2);
4289 emitcode("pop","acc");
4290 if (AOP_SIZE(result) >= 4) {
4291 lbl = newiTempLabel(NULL);
4292 emitcode("jnb","F0,%05d$",lbl->key+100);
4293 emitcode("cpl","a");
4294 emitcode("addc","a,#0");
4295 emitcode("","%05d$:", lbl->key+100);
4296 aopPut(AOP(result),"a",3);
4298 if (AOP_TYPE(result) == AOP_ACC)
4300 /* We stashed the result away above. */
4301 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4305 freeAsmop (result, NULL, ic, TRUE);
4307 /* restore EA bit in F1 */
4308 lbl = newiTempLabel(NULL);
4309 emitcode ("jnb","F1,%05d$",lbl->key+100);
4310 emitcode ("setb","EA");
4311 emitcode("","%05d$:",lbl->key+100);
4315 /*-----------------------------------------------------------------*/
4316 /* genMult - generates code for multiplication */
4317 /*-----------------------------------------------------------------*/
4319 genMult (iCode * ic)
4321 operand *left = IC_LEFT (ic);
4322 operand *right = IC_RIGHT (ic);
4323 operand *result = IC_RESULT (ic);
4325 D (emitcode (";", "genMult "););
4327 /* assign the amsops */
4330 /* special cases first */
4332 if (AOP_TYPE (left) == AOP_CRY &&
4333 AOP_TYPE (right) == AOP_CRY)
4335 genMultbits (left, right, result, ic);
4339 /* if both are of size == 1 */
4340 if (AOP_SIZE (left) == 1 &&
4341 AOP_SIZE (right) == 1)
4343 genMultOneByte (left, right, result, ic);
4347 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4348 /* use the ds390 ARITHMETIC accel UNIT */
4349 genMultTwoByte (left, right, result, ic);
4352 /* should have been converted to function call */
4356 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4357 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4358 freeAsmop (result, NULL, ic, TRUE);
4361 /*-----------------------------------------------------------------*/
4362 /* genDivbits :- division of bits */
4363 /*-----------------------------------------------------------------*/
4365 genDivbits (operand * left,
4373 /* the result must be bit */
4374 LOAD_AB_FOR_DIV (left, right, l);
4375 emitcode ("div", "ab");
4376 emitcode ("rrc", "a");
4377 aopOp(result, ic, TRUE, FALSE);
4379 aopPut (AOP (result), "c", 0);
4382 /*-----------------------------------------------------------------*/
4383 /* genDivOneByte : 8 bit division */
4384 /*-----------------------------------------------------------------*/
4386 genDivOneByte (operand * left,
4391 sym_link *opetype = operandType (result);
4397 /* signed or unsigned */
4398 if (SPEC_USIGN (opetype))
4400 /* unsigned is easy */
4401 LOAD_AB_FOR_DIV (left, right, l);
4402 emitcode ("div", "ab");
4405 aopOp(result, ic, TRUE, FALSE);
4406 aopPut (AOP (result), "a", 0);
4409 size = AOP_SIZE (result) - 1;
4413 aopPut (AOP (result), zero, offset++);
4418 /* signed is a little bit more difficult */
4420 /* save the signs of the operands */
4421 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4423 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4424 emitcode ("push", "acc"); /* save it on the stack */
4426 /* now sign adjust for both left & right */
4427 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4429 lbl = newiTempLabel (NULL);
4430 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4431 emitcode ("cpl", "a");
4432 emitcode ("inc", "a");
4433 emitcode ("", "%05d$:", (lbl->key + 100));
4434 emitcode ("mov", "b,a");
4436 /* sign adjust left side */
4437 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4440 lbl = newiTempLabel (NULL);
4441 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4442 emitcode ("cpl", "a");
4443 emitcode ("inc", "a");
4444 emitcode ("", "%05d$:", (lbl->key + 100));
4446 /* now the division */
4447 emitcode ("nop", "; workaround for DS80C390 div bug.");
4448 emitcode ("div", "ab");
4449 /* we are interested in the lower order
4451 emitcode ("mov", "b,a");
4452 lbl = newiTempLabel (NULL);
4453 emitcode ("pop", "acc");
4454 /* if there was an over flow we don't
4455 adjust the sign of the result */
4456 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4457 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4459 emitcode ("clr", "a");
4460 emitcode ("subb", "a,b");
4461 emitcode ("mov", "b,a");
4462 emitcode ("", "%05d$:", (lbl->key + 100));
4464 /* now we are done */
4466 aopOp(result, ic, TRUE, FALSE);
4468 aopPut (AOP (result), "b", 0);
4470 size = AOP_SIZE (result) - 1;
4474 emitcode ("mov", "c,b.7");
4475 emitcode ("subb", "a,acc");
4479 aopPut (AOP (result), "a", offset++);
4485 /*-----------------------------------------------------------------*/
4486 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4487 /*-----------------------------------------------------------------*/
4488 static void genDivTwoByte (operand *left, operand *right,
4489 operand *result, iCode *ic)
4491 sym_link *retype = getSpec(operandType(right));
4492 sym_link *letype = getSpec(operandType(left));
4493 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4496 /* save EA bit in F1 */
4497 lbl = newiTempLabel(NULL);
4498 emitcode ("setb","F1");
4499 emitcode ("jbc","EA,%05d$",lbl->key+100);
4500 emitcode ("clr","F1");
4501 emitcode("","%05d$:",lbl->key+100);
4503 /* load up MA with left */
4505 emitcode("clr","F0");
4506 lbl = newiTempLabel(NULL);
4507 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4508 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4509 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4510 emitcode ("xch", "a,b");
4511 emitcode ("cpl","a");
4512 emitcode ("add", "a,#1");
4513 emitcode ("xch", "a,b");
4514 emitcode ("cpl", "a"); // msb
4515 emitcode ("addc","a,#0");
4516 emitcode ("setb","F0");
4517 emitcode ("","%05d$:",lbl->key+100);
4518 emitcode ("mov","ma,b");
4519 emitcode ("mov","ma,a");
4521 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4522 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4525 /* load up MB with right */
4527 if (AOP_TYPE(right) == AOP_LIT) {
4528 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4530 lbl = newiTempLabel(NULL);
4531 emitcode ("jbc","F0,%05d$",lbl->key+100);
4532 emitcode("setb","F0");
4533 emitcode ("","%05d$:",lbl->key+100);
4536 emitcode ("mov","mb,#0x%02x",val & 0xff);
4537 emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4539 lbl = newiTempLabel(NULL);
4540 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4541 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4542 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4543 emitcode ("xch", "a,b");
4544 emitcode ("cpl","a");
4545 emitcode ("add", "a,#1");
4546 emitcode ("xch", "a,b");
4547 emitcode ("cpl", "a"); // msb
4548 emitcode ("addc", "a,#0");
4549 emitcode ("jbc","F0,%05d$",lbl->key+100);
4550 emitcode ("setb","F0");
4551 emitcode ("","%05d$:",lbl->key+100);
4552 emitcode ("mov","mb,b");
4553 emitcode ("mov","mb,a");
4556 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4557 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4560 /* wait for multiplication to finish */
4561 lbl = newiTempLabel(NULL);
4562 emitcode("","%05d$:", lbl->key+100);
4563 emitcode("mov","a,mcnt1");
4564 emitcode("anl","a,#0x80");
4565 emitcode("jnz","%05d$",lbl->key+100);
4567 freeAsmop (left, NULL, ic, TRUE);
4568 freeAsmop (right, NULL, ic,TRUE);
4569 aopOp(result, ic, TRUE, FALSE);
4571 /* if unsigned then simple */
4573 aopPut(AOP(result),"ma",1);
4574 aopPut(AOP(result),"ma",0);
4576 emitcode("push","ma");
4578 /* negate result if needed */
4579 lbl = newiTempLabel(NULL);
4580 emitcode("jnb","F0,%05d$",lbl->key+100);
4581 emitcode("cpl","a");
4582 emitcode("add","a,#1");
4583 emitcode("","%05d$:", lbl->key+100);
4584 aopPut(AOP(result),"a",0);
4585 emitcode("pop","acc");
4586 lbl = newiTempLabel(NULL);
4587 emitcode("jnb","F0,%05d$",lbl->key+100);
4588 emitcode("cpl","a");
4589 emitcode("addc","a,#0");
4590 emitcode("","%05d$:", lbl->key+100);
4591 aopPut(AOP(result),"a",1);
4593 freeAsmop (result, NULL, ic, TRUE);
4594 /* restore EA bit in F1 */
4595 lbl = newiTempLabel(NULL);
4596 emitcode ("jnb","F1,%05d$",lbl->key+100);
4597 emitcode ("setb","EA");
4598 emitcode("","%05d$:",lbl->key+100);
4602 /*-----------------------------------------------------------------*/
4603 /* genDiv - generates code for division */
4604 /*-----------------------------------------------------------------*/
4608 operand *left = IC_LEFT (ic);
4609 operand *right = IC_RIGHT (ic);
4610 operand *result = IC_RESULT (ic);
4612 D (emitcode (";", "genDiv "););
4614 /* assign the amsops */
4617 /* special cases first */
4619 if (AOP_TYPE (left) == AOP_CRY &&
4620 AOP_TYPE (right) == AOP_CRY)
4622 genDivbits (left, right, result, ic);
4626 /* if both are of size == 1 */
4627 if (AOP_SIZE (left) == 1 &&
4628 AOP_SIZE (right) == 1)
4630 genDivOneByte (left, right, result, ic);
4634 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4635 /* use the ds390 ARITHMETIC accel UNIT */
4636 genDivTwoByte (left, right, result, ic);
4639 /* should have been converted to function call */
4642 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4643 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4644 freeAsmop (result, NULL, ic, TRUE);
4647 /*-----------------------------------------------------------------*/
4648 /* genModbits :- modulus of bits */
4649 /*-----------------------------------------------------------------*/
4651 genModbits (operand * left,
4659 /* the result must be bit */
4660 LOAD_AB_FOR_DIV (left, right, l);
4661 emitcode ("div", "ab");
4662 emitcode ("mov", "a,b");
4663 emitcode ("rrc", "a");
4664 aopOp(result, ic, TRUE, FALSE);
4665 aopPut (AOP (result), "c", 0);
4668 /*-----------------------------------------------------------------*/
4669 /* genModOneByte : 8 bit modulus */
4670 /*-----------------------------------------------------------------*/
4672 genModOneByte (operand * left,
4677 sym_link *opetype = operandType (result);
4681 /* signed or unsigned */
4682 if (SPEC_USIGN (opetype))
4684 /* unsigned is easy */
4685 LOAD_AB_FOR_DIV (left, right, l);
4686 emitcode ("div", "ab");
4687 aopOp(result, ic, TRUE, FALSE);
4688 aopPut (AOP (result), "b", 0);
4692 /* signed is a little bit more difficult */
4694 /* save the signs of the operands */
4695 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4698 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4699 emitcode ("push", "acc"); /* save it on the stack */
4701 /* now sign adjust for both left & right */
4702 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4705 lbl = newiTempLabel (NULL);
4706 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4707 emitcode ("cpl", "a");
4708 emitcode ("inc", "a");
4709 emitcode ("", "%05d$:", (lbl->key + 100));
4710 emitcode ("mov", "b,a");
4712 /* sign adjust left side */
4713 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4716 lbl = newiTempLabel (NULL);
4717 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4718 emitcode ("cpl", "a");
4719 emitcode ("inc", "a");
4720 emitcode ("", "%05d$:", (lbl->key + 100));
4722 /* now the multiplication */
4723 emitcode ("nop", "; workaround for DS80C390 div bug.");
4724 emitcode ("div", "ab");
4725 /* we are interested in the lower order
4727 lbl = newiTempLabel (NULL);
4728 emitcode ("pop", "acc");
4729 /* if there was an over flow we don't
4730 adjust the sign of the result */
4731 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4732 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4734 emitcode ("clr", "a");
4735 emitcode ("subb", "a,b");
4736 emitcode ("mov", "b,a");
4737 emitcode ("", "%05d$:", (lbl->key + 100));
4739 /* now we are done */
4740 aopOp(result, ic, TRUE, FALSE);
4741 aopPut (AOP (result), "b", 0);
4745 /*-----------------------------------------------------------------*/
4746 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
4747 /*-----------------------------------------------------------------*/
4748 static void genModTwoByte (operand *left, operand *right,
4749 operand *result, iCode *ic)
4751 sym_link *retype = getSpec(operandType(right));
4752 sym_link *letype = getSpec(operandType(left));
4753 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4756 /* load up MA with left */
4757 /* save EA bit in F1 */
4758 lbl = newiTempLabel(NULL);
4759 emitcode ("setb","F1");
4760 emitcode ("jbc","EA,%05d$",lbl->key+100);
4761 emitcode ("clr","F1");
4762 emitcode("","%05d$:",lbl->key+100);
4765 lbl = newiTempLabel(NULL);
4766 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4767 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4768 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4769 emitcode ("xch", "a,b");
4770 emitcode ("cpl","a");
4771 emitcode ("add", "a,#1");
4772 emitcode ("xch", "a,b");
4773 emitcode ("cpl", "a"); // msb
4774 emitcode ("addc","a,#0");
4775 emitcode ("","%05d$:",lbl->key+100);
4776 emitcode ("mov","ma,b");
4777 emitcode ("mov","ma,a");
4779 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4780 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4783 /* load up MB with right */
4785 if (AOP_TYPE(right) == AOP_LIT) {
4786 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4790 emitcode ("mov","mb,#0x%02x",val & 0xff);
4791 emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4793 lbl = newiTempLabel(NULL);
4794 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4795 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4796 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4797 emitcode ("xch", "a,b");
4798 emitcode ("cpl","a");
4799 emitcode ("add", "a,#1");
4800 emitcode ("xch", "a,b");
4801 emitcode ("cpl", "a"); // msb
4802 emitcode ("addc", "a,#0");
4803 emitcode ("","%05d$:",lbl->key+100);
4804 emitcode ("mov","mb,b");
4805 emitcode ("mov","mb,a");
4808 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4809 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4812 /* wait for multiplication to finish */
4813 lbl = newiTempLabel(NULL);
4814 emitcode("","%05d$:", lbl->key+100);
4815 emitcode("mov","a,mcnt1");
4816 emitcode("anl","a,#0x80");
4817 emitcode("jnz","%05d$",lbl->key+100);
4819 freeAsmop (left, NULL, ic, TRUE);
4820 freeAsmop (right, NULL, ic,TRUE);
4821 aopOp(result, ic, TRUE, FALSE);
4823 aopPut(AOP(result),"mb",1);
4824 aopPut(AOP(result),"mb",0);
4825 freeAsmop (result, NULL, ic, TRUE);
4827 /* restore EA bit in F1 */
4828 lbl = newiTempLabel(NULL);
4829 emitcode ("jnb","F1,%05d$",lbl->key+100);
4830 emitcode ("setb","EA");
4831 emitcode("","%05d$:",lbl->key+100);
4835 /*-----------------------------------------------------------------*/
4836 /* genMod - generates code for division */
4837 /*-----------------------------------------------------------------*/
4841 operand *left = IC_LEFT (ic);
4842 operand *right = IC_RIGHT (ic);
4843 operand *result = IC_RESULT (ic);
4845 D (emitcode (";", "genMod "); );
4847 /* assign the amsops */
4850 /* special cases first */
4852 if (AOP_TYPE (left) == AOP_CRY &&
4853 AOP_TYPE (right) == AOP_CRY)
4855 genModbits (left, right, result, ic);
4859 /* if both are of size == 1 */
4860 if (AOP_SIZE (left) == 1 &&
4861 AOP_SIZE (right) == 1)
4863 genModOneByte (left, right, result, ic);
4867 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4868 /* use the ds390 ARITHMETIC accel UNIT */
4869 genModTwoByte (left, right, result, ic);
4873 /* should have been converted to function call */
4877 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4878 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4879 freeAsmop (result, NULL, ic, TRUE);
4882 /*-----------------------------------------------------------------*/
4883 /* genIfxJump :- will create a jump depending on the ifx */
4884 /*-----------------------------------------------------------------*/
4886 genIfxJump (iCode * ic, char *jval)
4889 symbol *tlbl = newiTempLabel (NULL);
4892 D (emitcode (";", "genIfxJump ");
4895 /* if true label then we jump if condition
4899 jlbl = IC_TRUE (ic);
4900 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4901 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4905 /* false label is present */
4906 jlbl = IC_FALSE (ic);
4907 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4908 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4910 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4911 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4913 emitcode (inst, "%05d$", tlbl->key + 100);
4914 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4915 emitcode ("", "%05d$:", tlbl->key + 100);
4917 /* mark the icode as generated */
4921 /*-----------------------------------------------------------------*/
4922 /* genCmp :- greater or less than comparison */
4923 /*-----------------------------------------------------------------*/
4925 genCmp (operand * left, operand * right,
4926 iCode * ic, iCode * ifx, int sign)
4928 int size, offset = 0;
4929 unsigned long lit = 0L;
4932 D (emitcode (";", "genCmp");
4935 result = IC_RESULT (ic);
4937 /* if left & right are bit variables */
4938 if (AOP_TYPE (left) == AOP_CRY &&
4939 AOP_TYPE (right) == AOP_CRY)
4941 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4942 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4946 /* subtract right from left if at the
4947 end the carry flag is set then we know that
4948 left is greater than right */
4949 size = max (AOP_SIZE (left), AOP_SIZE (right));
4951 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4952 if ((size == 1) && !sign &&
4953 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4955 symbol *lbl = newiTempLabel (NULL);
4956 emitcode ("cjne", "%s,%s,%05d$",
4957 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4958 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4960 emitcode ("", "%05d$:", lbl->key + 100);
4964 if (AOP_TYPE (right) == AOP_LIT)
4966 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4967 /* optimize if(x < 0) or if(x >= 0) */
4976 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4978 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4979 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4981 aopOp (result, ic, FALSE, FALSE);
4983 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4985 freeAsmop (result, NULL, ic, TRUE);
4986 genIfxJump (ifx, "acc.7");
4991 emitcode ("rlc", "a");
4993 goto release_freedLR;
5001 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5002 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5003 emitcode (";", "genCmp #2");
5004 if (sign && (size == 0))
5006 emitcode (";", "genCmp #3");
5007 emitcode ("xrl", "a,#0x80");
5008 if (AOP_TYPE (right) == AOP_LIT)
5010 unsigned long lit = (unsigned long)
5011 floatFromVal (AOP (right)->aopu.aop_lit);
5012 emitcode (";", "genCmp #3.1");
5013 emitcode ("subb", "a,#0x%02x",
5014 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5018 emitcode (";", "genCmp #3.2");
5019 if (AOP_NEEDSACC (right))
5021 emitcode ("push", "acc");
5023 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
5024 FALSE, FALSE, FALSE));
5025 emitcode ("xrl", "b,#0x80");
5026 if (AOP_NEEDSACC (right))
5028 emitcode ("pop", "acc");
5030 emitcode ("subb", "a,b");
5037 emitcode (";", "genCmp #4");
5038 if (AOP_NEEDSACC (right))
5041 emitcode (";", "genCmp #4.1");
5042 emitcode ("xch", "a, b");
5043 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
5044 emitcode ("xch", "a, b");
5049 emitcode (";", "genCmp #4.2");
5050 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
5053 emitcode ("subb", "a,%s", s);
5060 /* Don't need the left & right operands any more; do need the result. */
5061 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5062 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5064 aopOp (result, ic, FALSE, FALSE);
5068 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5074 /* if the result is used in the next
5075 ifx conditional branch then generate
5076 code a little differently */
5079 genIfxJump (ifx, "c");
5085 /* leave the result in acc */
5087 freeAsmop (result, NULL, ic, TRUE);
5090 /*-----------------------------------------------------------------*/
5091 /* genCmpGt :- greater than comparison */
5092 /*-----------------------------------------------------------------*/
5094 genCmpGt (iCode * ic, iCode * ifx)
5096 operand *left, *right;
5097 sym_link *letype, *retype;
5100 D (emitcode (";", "genCmpGt ");
5103 left = IC_LEFT (ic);
5104 right = IC_RIGHT (ic);
5106 letype = getSpec (operandType (left));
5107 retype = getSpec (operandType (right));
5108 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5110 /* assign the left & right amsops */
5113 genCmp (right, left, ic, ifx, sign);
5116 /*-----------------------------------------------------------------*/
5117 /* genCmpLt - less than comparisons */
5118 /*-----------------------------------------------------------------*/
5120 genCmpLt (iCode * ic, iCode * ifx)
5122 operand *left, *right;
5123 sym_link *letype, *retype;
5126 D (emitcode (";", "genCmpLt "););
5128 left = IC_LEFT (ic);
5129 right = IC_RIGHT (ic);
5131 letype = getSpec (operandType (left));
5132 retype = getSpec (operandType (right));
5133 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5135 /* assign the left & right amsops */
5138 genCmp (left, right, ic, ifx, sign);
5141 /*-----------------------------------------------------------------*/
5142 /* gencjneshort - compare and jump if not equal */
5143 /*-----------------------------------------------------------------*/
5145 gencjneshort (operand * left, operand * right, symbol * lbl)
5147 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5149 unsigned long lit = 0L;
5151 D (emitcode (";", "gencjneshort");
5154 /* if the left side is a literal or
5155 if the right is in a pointer register and left
5157 if ((AOP_TYPE (left) == AOP_LIT) ||
5158 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5165 if (AOP_TYPE (right) == AOP_LIT)
5166 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5168 if (opIsGptr (left) || opIsGptr (right))
5170 /* We are comparing a generic pointer to something.
5171 * Exclude the generic type byte from the comparison.
5174 D (emitcode (";", "cjneshort: generic ptr special case.");
5179 /* if the right side is a literal then anything goes */
5180 if (AOP_TYPE (right) == AOP_LIT &&
5181 AOP_TYPE (left) != AOP_DIR)
5185 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5187 emitcode ("cjne", "a,%s,%05d$",
5188 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5194 /* if the right side is in a register or in direct space or
5195 if the left is a pointer register & right is not */
5196 else if (AOP_TYPE (right) == AOP_REG ||
5197 AOP_TYPE (right) == AOP_DIR ||
5198 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5199 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5203 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5204 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5205 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5206 emitcode ("jnz", "%05d$", lbl->key + 100);
5208 emitcode ("cjne", "a,%s,%05d$",
5209 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5216 /* right is a pointer reg need both a & b */
5219 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5220 if (strcmp (l, "b"))
5221 emitcode ("mov", "b,%s", l);
5222 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5223 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5229 /*-----------------------------------------------------------------*/
5230 /* gencjne - compare and jump if not equal */
5231 /*-----------------------------------------------------------------*/
5233 gencjne (operand * left, operand * right, symbol * lbl)
5235 symbol *tlbl = newiTempLabel (NULL);
5237 D (emitcode (";", "gencjne");
5240 gencjneshort (left, right, lbl);
5242 emitcode ("mov", "a,%s", one);
5243 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5244 emitcode ("", "%05d$:", lbl->key + 100);
5245 emitcode ("clr", "a");
5246 emitcode ("", "%05d$:", tlbl->key + 100);
5249 /*-----------------------------------------------------------------*/
5250 /* genCmpEq - generates code for equal to */
5251 /*-----------------------------------------------------------------*/
5253 genCmpEq (iCode * ic, iCode * ifx)
5255 operand *left, *right, *result;
5257 D (emitcode (";", "genCmpEq ");
5261 AOP_SET_LOCALS (ic);
5263 /* if literal, literal on the right or
5264 if the right is in a pointer register and left
5266 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5267 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5269 operand *t = IC_RIGHT (ic);
5270 IC_RIGHT (ic) = IC_LEFT (ic);
5274 if (ifx && /* !AOP_SIZE(result) */
5275 OP_SYMBOL (result) &&
5276 OP_SYMBOL (result)->regType == REG_CND)
5279 /* if they are both bit variables */
5280 if (AOP_TYPE (left) == AOP_CRY &&
5281 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5283 if (AOP_TYPE (right) == AOP_LIT)
5285 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5288 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5289 emitcode ("cpl", "c");
5293 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5297 emitcode ("clr", "c");
5299 /* AOP_TYPE(right) == AOP_CRY */
5303 symbol *lbl = newiTempLabel (NULL);
5304 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5305 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5306 emitcode ("cpl", "c");
5307 emitcode ("", "%05d$:", (lbl->key + 100));
5309 /* if true label then we jump if condition
5311 tlbl = newiTempLabel (NULL);
5314 emitcode ("jnc", "%05d$", tlbl->key + 100);
5315 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5319 emitcode ("jc", "%05d$", tlbl->key + 100);
5320 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5322 emitcode ("", "%05d$:", tlbl->key + 100);
5326 tlbl = newiTempLabel (NULL);
5327 gencjneshort (left, right, tlbl);
5330 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5331 emitcode ("", "%05d$:", tlbl->key + 100);
5335 symbol *lbl = newiTempLabel (NULL);
5336 emitcode ("sjmp", "%05d$", lbl->key + 100);
5337 emitcode ("", "%05d$:", tlbl->key + 100);
5338 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5339 emitcode ("", "%05d$:", lbl->key + 100);
5342 /* mark the icode as generated */
5345 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5346 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5350 /* if they are both bit variables */
5351 if (AOP_TYPE (left) == AOP_CRY &&
5352 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5354 if (AOP_TYPE (right) == AOP_LIT)
5356 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5359 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5360 emitcode ("cpl", "c");
5364 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5368 emitcode ("clr", "c");
5370 /* AOP_TYPE(right) == AOP_CRY */
5374 symbol *lbl = newiTempLabel (NULL);
5375 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5376 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5377 emitcode ("cpl", "c");
5378 emitcode ("", "%05d$:", (lbl->key + 100));
5381 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5382 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5384 aopOp (result, ic, TRUE, FALSE);
5387 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5394 genIfxJump (ifx, "c");
5397 /* if the result is used in an arithmetic operation
5398 then put the result in place */
5403 gencjne (left, right, newiTempLabel (NULL));
5405 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5406 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5408 aopOp (result, ic, TRUE, FALSE);
5410 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5412 aopPut (AOP (result), "a", 0);
5417 genIfxJump (ifx, "a");
5420 /* if the result is used in an arithmetic operation
5421 then put the result in place */
5422 if (AOP_TYPE (result) != AOP_CRY)
5424 /* leave the result in acc */
5428 freeAsmop (result, NULL, ic, TRUE);
5431 /*-----------------------------------------------------------------*/
5432 /* ifxForOp - returns the icode containing the ifx for operand */
5433 /*-----------------------------------------------------------------*/
5435 ifxForOp (operand * op, iCode * ic)
5437 /* if true symbol then needs to be assigned */
5438 if (IS_TRUE_SYMOP (op))
5441 /* if this has register type condition and
5442 the next instruction is ifx with the same operand
5443 and live to of the operand is upto the ifx only then */
5445 ic->next->op == IFX &&
5446 IC_COND (ic->next)->key == op->key &&
5447 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5452 /*-----------------------------------------------------------------*/
5453 /* hasInc - operand is incremented before any other use */
5454 /*-----------------------------------------------------------------*/
5456 hasInc (operand *op, iCode *ic)
5458 sym_link *type = operandType(op);
5459 sym_link *retype = getSpec (type);
5460 iCode *lic = ic->next;
5463 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5464 if (!IS_SYMOP(op)) return NULL;
5466 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5467 isize = getSize(type->next);
5469 /* if operand of the form op = op + <sizeof *op> */
5470 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5471 isOperandEqual(IC_RESULT(lic),op) &&
5472 isOperandLiteral(IC_RIGHT(lic)) &&
5473 operandLitValue(IC_RIGHT(lic)) == isize) {
5476 /* if the operand used or deffed */
5477 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5480 /* if GOTO or IFX */
5481 if (lic->op == IFX || lic->op == GOTO) break;
5487 /*-----------------------------------------------------------------*/
5488 /* genAndOp - for && operation */
5489 /*-----------------------------------------------------------------*/
5491 genAndOp (iCode * ic)
5493 operand *left, *right, *result;
5496 D (emitcode (";", "genAndOp "););
5498 /* note here that && operations that are in an
5499 if statement are taken away by backPatchLabels
5500 only those used in arthmetic operations remain */
5502 AOP_SET_LOCALS (ic);
5504 /* if both are bit variables */
5505 if (AOP_TYPE (left) == AOP_CRY &&
5506 AOP_TYPE (right) == AOP_CRY)
5508 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5509 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5510 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5511 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5513 aopOp (result,ic,FALSE, FALSE);
5518 tlbl = newiTempLabel (NULL);
5520 emitcode ("jz", "%05d$", tlbl->key + 100);
5522 emitcode ("", "%05d$:", tlbl->key + 100);
5523 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5524 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5526 aopOp (result,ic,FALSE, FALSE);
5529 freeAsmop (result, NULL, ic, TRUE);
5533 /*-----------------------------------------------------------------*/
5534 /* genOrOp - for || operation */
5535 /*-----------------------------------------------------------------*/
5537 genOrOp (iCode * ic)
5539 operand *left, *right, *result;
5542 D (emitcode (";", "genOrOp "););
5544 /* note here that || operations that are in an
5545 if statement are taken away by backPatchLabels
5546 only those used in arthmetic operations remain */
5548 AOP_SET_LOCALS (ic);
5550 /* if both are bit variables */
5551 if (AOP_TYPE (left) == AOP_CRY &&
5552 AOP_TYPE (right) == AOP_CRY)
5554 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5555 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5556 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5557 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5559 aopOp (result,ic,FALSE, FALSE);
5565 tlbl = newiTempLabel (NULL);
5567 emitcode ("jnz", "%05d$", tlbl->key + 100);
5569 emitcode ("", "%05d$:", tlbl->key + 100);
5570 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5571 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5573 aopOp (result,ic,FALSE, FALSE);
5578 freeAsmop (result, NULL, ic, TRUE);
5581 /*-----------------------------------------------------------------*/
5582 /* isLiteralBit - test if lit == 2^n */
5583 /*-----------------------------------------------------------------*/
5585 isLiteralBit (unsigned long lit)
5587 unsigned long pw[32] =
5588 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5589 0x100L, 0x200L, 0x400L, 0x800L,
5590 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5591 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5592 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5593 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5594 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5597 for (idx = 0; idx < 32; idx++)
5603 /*-----------------------------------------------------------------*/
5604 /* continueIfTrue - */
5605 /*-----------------------------------------------------------------*/
5607 continueIfTrue (iCode * ic)
5610 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5614 /*-----------------------------------------------------------------*/
5616 /*-----------------------------------------------------------------*/
5618 jumpIfTrue (iCode * ic)
5621 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5625 /*-----------------------------------------------------------------*/
5626 /* jmpTrueOrFalse - */
5627 /*-----------------------------------------------------------------*/
5629 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5631 // ugly but optimized by peephole
5634 symbol *nlbl = newiTempLabel (NULL);
5635 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5636 emitcode ("", "%05d$:", tlbl->key + 100);
5637 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5638 emitcode ("", "%05d$:", nlbl->key + 100);
5642 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5643 emitcode ("", "%05d$:", tlbl->key + 100);
5648 // Generate code to perform a bit-wise logic operation
5649 // on two operands in far space (assumed to already have been
5650 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5651 // in far space. This requires pushing the result on the stack
5652 // then popping it into the result.
5654 genFarFarLogicOp(iCode *ic, char *logicOp)
5656 int size, resultSize, compSize;
5660 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5661 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5662 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5664 _startLazyDPSEvaluation();
5665 for (size = compSize; (size--); offset++)
5667 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5668 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5669 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5671 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5672 emitcode ("push", "acc");
5674 _endLazyDPSEvaluation();
5676 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5677 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5678 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5680 resultSize = AOP_SIZE(IC_RESULT(ic));
5682 ADJUST_PUSHED_RESULT(compSize, resultSize);
5684 _startLazyDPSEvaluation();
5687 emitcode ("pop", "acc");
5688 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5690 _endLazyDPSEvaluation();
5691 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5695 /*-----------------------------------------------------------------*/
5696 /* genAnd - code for and */
5697 /*-----------------------------------------------------------------*/
5699 genAnd (iCode * ic, iCode * ifx)
5701 operand *left, *right, *result;
5702 int size, offset = 0;
5703 unsigned long lit = 0L;
5708 D (emitcode (";", "genAnd "););
5710 AOP_OP_3_NOFATAL (ic, pushResult);
5711 AOP_SET_LOCALS (ic);
5715 genFarFarLogicOp(ic, "anl");
5720 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5722 AOP_TYPE (left), AOP_TYPE (right));
5723 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5725 AOP_SIZE (left), AOP_SIZE (right));
5728 /* if left is a literal & right is not then exchange them */
5729 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5730 #ifdef LOGIC_OPS_BROKEN
5731 || AOP_NEEDSACC (left)
5735 operand *tmp = right;
5740 /* if result = right then exchange them */
5741 if (sameRegs (AOP (result), AOP (right)))
5743 operand *tmp = right;
5748 /* if right is bit then exchange them */
5749 if (AOP_TYPE (right) == AOP_CRY &&
5750 AOP_TYPE (left) != AOP_CRY)
5752 operand *tmp = right;
5756 if (AOP_TYPE (right) == AOP_LIT)
5757 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5759 size = AOP_SIZE (result);
5762 // result = bit & yy;
5763 if (AOP_TYPE (left) == AOP_CRY)
5765 // c = bit & literal;
5766 if (AOP_TYPE (right) == AOP_LIT)
5770 if (size && sameRegs (AOP (result), AOP (left)))
5773 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5778 if (size && (AOP_TYPE (result) == AOP_CRY))
5780 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5783 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5788 emitcode ("clr", "c");
5793 if (AOP_TYPE (right) == AOP_CRY)
5796 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5797 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5802 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5804 emitcode ("rrc", "a");
5805 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5813 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5814 genIfxJump (ifx, "c");
5818 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5819 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5820 if ((AOP_TYPE (right) == AOP_LIT) &&
5821 (AOP_TYPE (result) == AOP_CRY) &&
5822 (AOP_TYPE (left) != AOP_CRY))
5824 int posbit = isLiteralBit (lit);
5829 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5832 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5838 sprintf (buffer, "acc.%d", posbit & 0x07);
5839 genIfxJump (ifx, buffer);
5846 symbol *tlbl = newiTempLabel (NULL);
5847 int sizel = AOP_SIZE (left);
5849 emitcode ("setb", "c");
5852 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5854 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5856 if ((posbit = isLiteralBit (bytelit)) != 0)
5857 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5860 if (bytelit != 0x0FFL)
5861 emitcode ("anl", "a,%s",
5862 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5863 emitcode ("jnz", "%05d$", tlbl->key + 100);
5868 // bit = left & literal
5871 emitcode ("clr", "c");
5872 emitcode ("", "%05d$:", tlbl->key + 100);
5874 // if(left & literal)
5878 jmpTrueOrFalse (ifx, tlbl);
5886 /* if left is same as result */
5887 if (sameRegs (AOP (result), AOP (left)))
5889 for (; size--; offset++)
5891 if (AOP_TYPE (right) == AOP_LIT)
5893 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5895 else if (bytelit == 0)
5896 aopPut (AOP (result), zero, offset);
5897 else if (IS_AOP_PREG (result))
5899 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5900 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5901 aopPut (AOP (result), "a", offset);
5904 emitcode ("anl", "%s,%s",
5905 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5906 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5910 if (AOP_TYPE (left) == AOP_ACC)
5911 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5914 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5915 if (IS_AOP_PREG (result))
5917 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5918 aopPut (AOP (result), "a", offset);
5922 emitcode ("anl", "%s,a",
5923 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5930 // left & result in different registers
5931 if (AOP_TYPE (result) == AOP_CRY)
5934 // if(size), result in bit
5935 // if(!size && ifx), conditional oper: if(left & right)
5936 symbol *tlbl = newiTempLabel (NULL);
5937 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5939 emitcode ("setb", "c");
5942 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5943 emitcode ("anl", "a,%s",
5944 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5946 if (AOP_TYPE(left)==AOP_ACC) {
5947 emitcode("mov", "b,a");
5948 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5949 emitcode("anl", "a,b");
5951 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5952 emitcode ("anl", "a,%s",
5953 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5956 emitcode ("jnz", "%05d$", tlbl->key + 100);
5962 emitcode ("", "%05d$:", tlbl->key + 100);
5966 jmpTrueOrFalse (ifx, tlbl);
5970 for (; (size--); offset++)
5973 // result = left & right
5974 if (AOP_TYPE (right) == AOP_LIT)
5976 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5978 aopPut (AOP (result),
5979 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5983 else if (bytelit == 0)
5985 aopPut (AOP (result), zero, offset);
5988 D (emitcode (";", "better literal AND."););
5989 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5990 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5991 FALSE, FALSE, FALSE));
5996 // faster than result <- left, anl result,right
5997 // and better if result is SFR
5998 if (AOP_TYPE (left) == AOP_ACC)
6000 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
6001 FALSE, FALSE, FALSE));
6005 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6006 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6008 emitcode("mov", "b,a");
6012 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6013 emitcode ("anl", "a,%s", rOp);
6016 aopPut (AOP (result), "a", offset);
6022 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6023 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6024 freeAsmop (result, NULL, ic, TRUE);
6028 /*-----------------------------------------------------------------*/
6029 /* genOr - code for or */
6030 /*-----------------------------------------------------------------*/
6032 genOr (iCode * ic, iCode * ifx)
6034 operand *left, *right, *result;
6035 int size, offset = 0;
6036 unsigned long lit = 0L;
6039 D (emitcode (";", "genOr "););
6041 AOP_OP_3_NOFATAL (ic, pushResult);
6042 AOP_SET_LOCALS (ic);
6046 genFarFarLogicOp(ic, "orl");
6052 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6054 AOP_TYPE (left), AOP_TYPE (right));
6055 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6057 AOP_SIZE (left), AOP_SIZE (right));
6060 /* if left is a literal & right is not then exchange them */
6061 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6062 #ifdef LOGIC_OPS_BROKEN
6063 || AOP_NEEDSACC (left) // I think this is a net loss now.
6067 operand *tmp = right;
6072 /* if result = right then exchange them */
6073 if (sameRegs (AOP (result), AOP (right)))
6075 operand *tmp = right;
6080 /* if right is bit then exchange them */
6081 if (AOP_TYPE (right) == AOP_CRY &&
6082 AOP_TYPE (left) != AOP_CRY)
6084 operand *tmp = right;
6088 if (AOP_TYPE (right) == AOP_LIT)
6089 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6091 size = AOP_SIZE (result);
6095 if (AOP_TYPE (left) == AOP_CRY)
6097 if (AOP_TYPE (right) == AOP_LIT)
6099 // c = bit & literal;
6102 // lit != 0 => result = 1
6103 if (AOP_TYPE (result) == AOP_CRY)
6106 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6108 continueIfTrue (ifx);
6111 emitcode ("setb", "c");
6115 // lit == 0 => result = left
6116 if (size && sameRegs (AOP (result), AOP (left)))
6118 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6123 if (AOP_TYPE (right) == AOP_CRY)
6126 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6127 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6132 symbol *tlbl = newiTempLabel (NULL);
6133 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6134 emitcode ("setb", "c");
6135 emitcode ("jb", "%s,%05d$",
6136 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6138 emitcode ("jnz", "%05d$", tlbl->key + 100);
6139 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6141 jmpTrueOrFalse (ifx, tlbl);
6147 emitcode ("", "%05d$:", tlbl->key + 100);
6156 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6157 genIfxJump (ifx, "c");
6161 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6162 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6163 if ((AOP_TYPE (right) == AOP_LIT) &&
6164 (AOP_TYPE (result) == AOP_CRY) &&
6165 (AOP_TYPE (left) != AOP_CRY))
6171 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6173 continueIfTrue (ifx);
6178 // lit = 0, result = boolean(left)
6180 emitcode ("setb", "c");
6184 symbol *tlbl = newiTempLabel (NULL);
6185 emitcode ("jnz", "%05d$", tlbl->key + 100);
6187 emitcode ("", "%05d$:", tlbl->key + 100);
6191 genIfxJump (ifx, "a");
6199 /* if left is same as result */
6200 if (sameRegs (AOP (result), AOP (left)))
6202 for (; size--; offset++)
6204 if (AOP_TYPE (right) == AOP_LIT)
6206 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6212 if (IS_AOP_PREG (left))
6214 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6215 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6216 aopPut (AOP (result), "a", offset);
6220 emitcode ("orl", "%s,%s",
6221 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6222 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6228 if (AOP_TYPE (left) == AOP_ACC)
6230 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6234 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6235 if (IS_AOP_PREG (left))
6237 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6238 aopPut (AOP (result), "a", offset);
6242 emitcode ("orl", "%s,a",
6243 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6251 // left & result in different registers
6252 if (AOP_TYPE (result) == AOP_CRY)
6255 // if(size), result in bit
6256 // if(!size && ifx), conditional oper: if(left | right)
6257 symbol *tlbl = newiTempLabel (NULL);
6258 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6260 emitcode ("setb", "c");
6263 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6264 emitcode ("orl", "a,%s",
6265 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6267 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6268 emitcode ("orl", "a,%s",
6269 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6271 emitcode ("jnz", "%05d$", tlbl->key + 100);
6277 emitcode ("", "%05d$:", tlbl->key + 100);
6281 jmpTrueOrFalse (ifx, tlbl);
6285 _startLazyDPSEvaluation();
6286 for (; (size--); offset++)
6289 // result = left & right
6290 if (AOP_TYPE (right) == AOP_LIT)
6292 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6294 aopPut (AOP (result),
6295 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6299 D (emitcode (";", "better literal OR."););
6300 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6301 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6302 FALSE, FALSE, FALSE));
6307 // faster than result <- left, anl result,right
6308 // and better if result is SFR
6309 if (AOP_TYPE (left) == AOP_ACC)
6311 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6312 FALSE, FALSE, FALSE));
6316 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6318 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6320 emitcode("mov", "b,a");
6324 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6325 emitcode ("orl", "a,%s", rOp);
6328 aopPut (AOP (result), "a", offset);
6330 _endLazyDPSEvaluation();
6335 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6336 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6337 freeAsmop (result, NULL, ic, TRUE);
6340 /*-----------------------------------------------------------------*/
6341 /* genXor - code for xclusive or */
6342 /*-----------------------------------------------------------------*/
6344 genXor (iCode * ic, iCode * ifx)
6346 operand *left, *right, *result;
6347 int size, offset = 0;
6348 unsigned long lit = 0L;
6351 D (emitcode (";", "genXor "););
6353 AOP_OP_3_NOFATAL (ic, pushResult);
6354 AOP_SET_LOCALS (ic);
6358 genFarFarLogicOp(ic, "xrl");
6363 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6365 AOP_TYPE (left), AOP_TYPE (right));
6366 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6368 AOP_SIZE (left), AOP_SIZE (right));
6371 /* if left is a literal & right is not ||
6372 if left needs acc & right does not */
6373 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6374 #ifdef LOGIC_OPS_BROKEN
6375 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6379 operand *tmp = right;
6384 /* if result = right then exchange them */
6385 if (sameRegs (AOP (result), AOP (right)))
6387 operand *tmp = right;
6392 /* if right is bit then exchange them */
6393 if (AOP_TYPE (right) == AOP_CRY &&
6394 AOP_TYPE (left) != AOP_CRY)
6396 operand *tmp = right;
6400 if (AOP_TYPE (right) == AOP_LIT)
6401 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6403 size = AOP_SIZE (result);
6407 if (AOP_TYPE (left) == AOP_CRY)
6409 if (AOP_TYPE (right) == AOP_LIT)
6411 // c = bit & literal;
6414 // lit>>1 != 0 => result = 1
6415 if (AOP_TYPE (result) == AOP_CRY)
6418 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6420 continueIfTrue (ifx);
6423 emitcode ("setb", "c");
6430 // lit == 0, result = left
6431 if (size && sameRegs (AOP (result), AOP (left)))
6433 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6437 // lit == 1, result = not(left)
6438 if (size && sameRegs (AOP (result), AOP (left)))
6440 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6445 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6446 emitcode ("cpl", "c");
6455 symbol *tlbl = newiTempLabel (NULL);
6456 if (AOP_TYPE (right) == AOP_CRY)
6459 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6463 int sizer = AOP_SIZE (right);
6465 // if val>>1 != 0, result = 1
6466 emitcode ("setb", "c");
6469 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6471 // test the msb of the lsb
6472 emitcode ("anl", "a,#0xfe");
6473 emitcode ("jnz", "%05d$", tlbl->key + 100);
6477 emitcode ("rrc", "a");
6479 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6480 emitcode ("cpl", "c");
6481 emitcode ("", "%05d$:", (tlbl->key + 100));
6488 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6489 genIfxJump (ifx, "c");
6493 if (sameRegs (AOP (result), AOP (left)))
6495 /* if left is same as result */
6496 for (; size--; offset++)
6498 if (AOP_TYPE (right) == AOP_LIT)
6500 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6502 else if (IS_AOP_PREG (left))
6504 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6505 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6506 aopPut (AOP (result), "a", offset);
6509 emitcode ("xrl", "%s,%s",
6510 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6511 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6515 if (AOP_TYPE (left) == AOP_ACC)
6516 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6519 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6520 if (IS_AOP_PREG (left))
6522 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6523 aopPut (AOP (result), "a", offset);
6526 emitcode ("xrl", "%s,a",
6527 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6534 // left & result in different registers
6535 if (AOP_TYPE (result) == AOP_CRY)
6538 // if(size), result in bit
6539 // if(!size && ifx), conditional oper: if(left ^ right)
6540 symbol *tlbl = newiTempLabel (NULL);
6541 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6544 emitcode ("setb", "c");
6547 if ((AOP_TYPE (right) == AOP_LIT) &&
6548 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6550 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6554 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6555 emitcode ("xrl", "a,%s",
6556 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6558 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6559 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6561 emitcode("mov", "b,a");
6565 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6566 emitcode ("xrl", "a,%s", rOp);
6569 emitcode ("jnz", "%05d$", tlbl->key + 100);
6575 emitcode ("", "%05d$:", tlbl->key + 100);
6579 jmpTrueOrFalse (ifx, tlbl);
6583 for (; (size--); offset++)
6586 // result = left & right
6587 if (AOP_TYPE (right) == AOP_LIT)
6589 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6591 aopPut (AOP (result),
6592 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6596 D (emitcode (";", "better literal XOR."););
6597 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6598 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6599 FALSE, FALSE, FALSE));
6603 // faster than result <- left, anl result,right
6604 // and better if result is SFR
6605 if (AOP_TYPE (left) == AOP_ACC)
6607 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6608 FALSE, FALSE, FALSE));
6612 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6613 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6615 emitcode("mov", "b,a");
6619 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6620 emitcode ("xrl", "a,%s", rOp);
6623 aopPut (AOP (result), "a", offset);
6630 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6631 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6632 freeAsmop (result, NULL, ic, TRUE);
6635 /*-----------------------------------------------------------------*/
6636 /* genInline - write the inline code out */
6637 /*-----------------------------------------------------------------*/
6639 genInline (iCode * ic)
6641 char *buffer, *bp, *bp1;
6643 D (emitcode (";", "genInline ");
6646 _G.inLine += (!options.asmpeep);
6648 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6649 strcpy (buffer, IC_INLINE (ic));
6651 /* emit each line as a code */
6676 /* emitcode("",buffer); */
6677 _G.inLine -= (!options.asmpeep);
6680 /*-----------------------------------------------------------------*/
6681 /* genRRC - rotate right with carry */
6682 /*-----------------------------------------------------------------*/
6686 operand *left, *result;
6687 int size, offset = 0;
6690 D (emitcode (";", "genRRC ");
6693 /* rotate right with carry */
6694 left = IC_LEFT (ic);
6695 result = IC_RESULT (ic);
6696 aopOp (left, ic, FALSE, FALSE);
6697 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6699 /* move it to the result */
6700 size = AOP_SIZE (result);
6704 _startLazyDPSEvaluation ();
6707 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6709 emitcode ("rrc", "a");
6710 if (AOP_SIZE (result) > 1)
6711 aopPut (AOP (result), "a", offset--);
6713 _endLazyDPSEvaluation ();
6715 /* now we need to put the carry into the
6716 highest order byte of the result */
6717 if (AOP_SIZE (result) > 1)
6719 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6722 emitcode ("mov", "acc.7,c");
6723 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6724 freeAsmop (left, NULL, ic, TRUE);
6725 freeAsmop (result, NULL, ic, TRUE);
6728 /*-----------------------------------------------------------------*/
6729 /* genRLC - generate code for rotate left with carry */
6730 /*-----------------------------------------------------------------*/
6734 operand *left, *result;
6735 int size, offset = 0;
6738 D (emitcode (";", "genRLC ");
6741 /* rotate right with carry */
6742 left = IC_LEFT (ic);
6743 result = IC_RESULT (ic);
6744 aopOp (left, ic, FALSE, FALSE);
6745 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6747 /* move it to the result */
6748 size = AOP_SIZE (result);
6752 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6754 emitcode ("add", "a,acc");
6755 if (AOP_SIZE (result) > 1)
6757 aopPut (AOP (result), "a", offset++);
6760 _startLazyDPSEvaluation ();
6763 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6765 emitcode ("rlc", "a");
6766 if (AOP_SIZE (result) > 1)
6767 aopPut (AOP (result), "a", offset++);
6769 _endLazyDPSEvaluation ();
6771 /* now we need to put the carry into the
6772 highest order byte of the result */
6773 if (AOP_SIZE (result) > 1)
6775 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6778 emitcode ("mov", "acc.0,c");
6779 aopPut (AOP (result), "a", 0);
6780 freeAsmop (left, NULL, ic, TRUE);
6781 freeAsmop (result, NULL, ic, TRUE);
6784 /*-----------------------------------------------------------------*/
6785 /* genGetHbit - generates code get highest order bit */
6786 /*-----------------------------------------------------------------*/
6788 genGetHbit (iCode * ic)
6790 operand *left, *result;
6791 left = IC_LEFT (ic);
6792 result = IC_RESULT (ic);
6793 aopOp (left, ic, FALSE, FALSE);
6794 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6796 D (emitcode (";", "genGetHbit ");
6799 /* get the highest order byte into a */
6800 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6801 if (AOP_TYPE (result) == AOP_CRY)
6803 emitcode ("rlc", "a");
6808 emitcode ("rl", "a");
6809 emitcode ("anl", "a,#0x01");
6814 freeAsmop (left, NULL, ic, TRUE);
6815 freeAsmop (result, NULL, ic, TRUE);
6818 /*-----------------------------------------------------------------*/
6819 /* AccRol - rotate left accumulator by known count */
6820 /*-----------------------------------------------------------------*/
6822 AccRol (int shCount)
6824 shCount &= 0x0007; // shCount : 0..7
6831 emitcode ("rl", "a");
6834 emitcode ("rl", "a");
6835 emitcode ("rl", "a");
6838 emitcode ("swap", "a");
6839 emitcode ("rr", "a");
6842 emitcode ("swap", "a");
6845 emitcode ("swap", "a");
6846 emitcode ("rl", "a");
6849 emitcode ("rr", "a");
6850 emitcode ("rr", "a");
6853 emitcode ("rr", "a");
6858 /*-----------------------------------------------------------------*/
6859 /* AccLsh - left shift accumulator by known count */
6860 /*-----------------------------------------------------------------*/
6862 AccLsh (int shCount)
6867 emitcode ("add", "a,acc");
6868 else if (shCount == 2)
6870 emitcode ("add", "a,acc");
6871 emitcode ("add", "a,acc");
6875 /* rotate left accumulator */
6877 /* and kill the lower order bits */
6878 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6883 /*-----------------------------------------------------------------*/
6884 /* AccRsh - right shift accumulator by known count */
6885 /*-----------------------------------------------------------------*/
6887 AccRsh (int shCount)
6894 emitcode ("rrc", "a");
6898 /* rotate right accumulator */
6899 AccRol (8 - shCount);
6900 /* and kill the higher order bits */
6901 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6906 #ifdef BETTER_LITERAL_SHIFT
6907 /*-----------------------------------------------------------------*/
6908 /* AccSRsh - signed right shift accumulator by known count */
6909 /*-----------------------------------------------------------------*/
6911 AccSRsh (int shCount)
6918 emitcode ("mov", "c,acc.7");
6919 emitcode ("rrc", "a");
6921 else if (shCount == 2)
6923 emitcode ("mov", "c,acc.7");
6924 emitcode ("rrc", "a");
6925 emitcode ("mov", "c,acc.7");
6926 emitcode ("rrc", "a");
6930 tlbl = newiTempLabel (NULL);
6931 /* rotate right accumulator */
6932 AccRol (8 - shCount);
6933 /* and kill the higher order bits */
6934 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6935 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6936 emitcode ("orl", "a,#0x%02x",
6937 (unsigned char) ~SRMask[shCount]);
6938 emitcode ("", "%05d$:", tlbl->key + 100);
6944 #ifdef BETTER_LITERAL_SHIFT
6945 /*-----------------------------------------------------------------*/
6946 /* shiftR1Left2Result - shift right one byte from left to result */
6947 /*-----------------------------------------------------------------*/
6949 shiftR1Left2Result (operand * left, int offl,
6950 operand * result, int offr,
6951 int shCount, int sign)
6953 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6954 /* shift right accumulator */
6959 aopPut (AOP (result), "a", offr);
6963 #ifdef BETTER_LITERAL_SHIFT
6964 /*-----------------------------------------------------------------*/
6965 /* shiftL1Left2Result - shift left one byte from left to result */
6966 /*-----------------------------------------------------------------*/
6968 shiftL1Left2Result (operand * left, int offl,
6969 operand * result, int offr, int shCount)
6971 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6972 /* shift left accumulator */
6974 aopPut (AOP (result), "a", offr);
6978 #ifdef BETTER_LITERAL_SHIFT
6979 /*-----------------------------------------------------------------*/
6980 /* movLeft2Result - move byte from left to result */
6981 /*-----------------------------------------------------------------*/
6983 movLeft2Result (operand * left, int offl,
6984 operand * result, int offr, int sign)
6987 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6989 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6991 if (*l == '@' && (IS_AOP_PREG (result)))
6993 emitcode ("mov", "a,%s", l);
6994 aopPut (AOP (result), "a", offr);
7000 aopPut (AOP (result), l, offr);
7004 /* MSB sign in acc.7 ! */
7005 if (getDataSize (left) == offl + 1)
7007 emitcode ("mov", "a,%s", l);
7008 aopPut (AOP (result), "a", offr);
7016 #ifdef BETTER_LITERAL_SHIFT
7017 /*-----------------------------------------------------------------*/
7018 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7019 /*-----------------------------------------------------------------*/
7023 emitcode ("rrc", "a");
7024 emitcode ("xch", "a,%s", x);
7025 emitcode ("rrc", "a");
7026 emitcode ("xch", "a,%s", x);
7030 #ifdef BETTER_LITERAL_SHIFT
7032 /*-----------------------------------------------------------------*/
7033 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7034 /*-----------------------------------------------------------------*/
7038 emitcode ("xch", "a,%s", x);
7039 emitcode ("rlc", "a");
7040 emitcode ("xch", "a,%s", x);
7041 emitcode ("rlc", "a");
7045 #ifdef BETTER_LITERAL_SHIFT
7046 /*-----------------------------------------------------------------*/
7047 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7048 /*-----------------------------------------------------------------*/
7052 emitcode ("xch", "a,%s", x);
7053 emitcode ("add", "a,acc");
7054 emitcode ("xch", "a,%s", x);
7055 emitcode ("rlc", "a");
7059 #ifdef BETTER_LITERAL_SHIFT
7060 /*-----------------------------------------------------------------*/
7061 /* AccAXLsh - left shift a:x by known count (0..7) */
7062 /*-----------------------------------------------------------------*/
7064 AccAXLsh (char *x, int shCount)
7079 case 5: // AAAAABBB:CCCCCDDD
7081 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7083 emitcode ("anl", "a,#0x%02x",
7084 SLMask[shCount]); // BBB00000:CCCCCDDD
7086 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7088 AccRol (shCount); // DDDCCCCC:BBB00000
7090 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7092 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7094 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7096 emitcode ("anl", "a,#0x%02x",
7097 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7099 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7101 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7104 case 6: // AAAAAABB:CCCCCCDD
7105 emitcode ("anl", "a,#0x%02x",
7106 SRMask[shCount]); // 000000BB:CCCCCCDD
7107 emitcode ("mov", "c,acc.0"); // c = B
7108 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7110 AccAXRrl1 (x); // BCCCCCCD:D000000B
7111 AccAXRrl1 (x); // BBCCCCCC:DD000000
7113 emitcode("rrc","a");
7114 emitcode("xch","a,%s", x);
7115 emitcode("rrc","a");
7116 emitcode("mov","c,acc.0"); //<< get correct bit
7117 emitcode("xch","a,%s", x);
7119 emitcode("rrc","a");
7120 emitcode("xch","a,%s", x);
7121 emitcode("rrc","a");
7122 emitcode("xch","a,%s", x);
7125 case 7: // a:x <<= 7
7127 emitcode ("anl", "a,#0x%02x",
7128 SRMask[shCount]); // 0000000B:CCCCCCCD
7130 emitcode ("mov", "c,acc.0"); // c = B
7132 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7134 AccAXRrl1 (x); // BCCCCCCC:D0000000
7143 #ifdef BETTER_LITERAL_SHIFT
7145 /*-----------------------------------------------------------------*/
7146 /* AccAXRsh - right shift a:x known count (0..7) */
7147 /*-----------------------------------------------------------------*/
7149 AccAXRsh (char *x, int shCount)
7157 AccAXRrl1 (x); // 0->a:x
7162 AccAXRrl1 (x); // 0->a:x
7165 AccAXRrl1 (x); // 0->a:x
7170 case 5: // AAAAABBB:CCCCCDDD = a:x
7172 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7174 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7176 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7178 emitcode ("anl", "a,#0x%02x",
7179 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7181 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7183 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7185 emitcode ("anl", "a,#0x%02x",
7186 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7188 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7190 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7192 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7195 case 6: // AABBBBBB:CCDDDDDD
7197 emitcode ("mov", "c,acc.7");
7198 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7200 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7202 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7204 emitcode ("anl", "a,#0x%02x",
7205 SRMask[shCount]); // 000000AA:BBBBBBCC
7208 case 7: // ABBBBBBB:CDDDDDDD
7210 emitcode ("mov", "c,acc.7"); // c = A
7212 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7214 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7216 emitcode ("anl", "a,#0x%02x",
7217 SRMask[shCount]); // 0000000A:BBBBBBBC
7226 #ifdef BETTER_LITERAL_SHIFT
7227 /*-----------------------------------------------------------------*/
7228 /* AccAXRshS - right shift signed a:x known count (0..7) */
7229 /*-----------------------------------------------------------------*/
7231 AccAXRshS (char *x, int shCount)
7239 emitcode ("mov", "c,acc.7");
7240 AccAXRrl1 (x); // s->a:x
7244 emitcode ("mov", "c,acc.7");
7245 AccAXRrl1 (x); // s->a:x
7247 emitcode ("mov", "c,acc.7");
7248 AccAXRrl1 (x); // s->a:x
7253 case 5: // AAAAABBB:CCCCCDDD = a:x
7255 tlbl = newiTempLabel (NULL);
7256 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7258 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7260 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7262 emitcode ("anl", "a,#0x%02x",
7263 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7265 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7267 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7269 emitcode ("anl", "a,#0x%02x",
7270 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7272 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7274 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7276 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7278 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7279 emitcode ("orl", "a,#0x%02x",
7280 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7282 emitcode ("", "%05d$:", tlbl->key + 100);
7283 break; // SSSSAAAA:BBBCCCCC
7285 case 6: // AABBBBBB:CCDDDDDD
7287 tlbl = newiTempLabel (NULL);
7288 emitcode ("mov", "c,acc.7");
7289 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7291 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7293 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7295 emitcode ("anl", "a,#0x%02x",
7296 SRMask[shCount]); // 000000AA:BBBBBBCC
7298 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7299 emitcode ("orl", "a,#0x%02x",
7300 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7302 emitcode ("", "%05d$:", tlbl->key + 100);
7304 case 7: // ABBBBBBB:CDDDDDDD
7306 tlbl = newiTempLabel (NULL);
7307 emitcode ("mov", "c,acc.7"); // c = A
7309 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7311 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7313 emitcode ("anl", "a,#0x%02x",
7314 SRMask[shCount]); // 0000000A:BBBBBBBC
7316 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7317 emitcode ("orl", "a,#0x%02x",
7318 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7320 emitcode ("", "%05d$:", tlbl->key + 100);
7328 #ifdef BETTER_LITERAL_SHIFT
7330 _loadLeftIntoAx(char **lsb,
7336 // Get the initial value from left into a pair of registers.
7337 // MSB must be in A, LSB can be any register.
7339 // If the result is held in registers, it is an optimization
7340 // if the LSB can be held in the register which will hold the,
7341 // result LSB since this saves us from having to copy it into
7342 // the result following AccAXLsh.
7344 // If the result is addressed indirectly, this is not a gain.
7345 if (AOP_NEEDSACC(result))
7349 _startLazyDPSEvaluation();
7350 if (AOP_TYPE(left) == AOP_DPTR2)
7353 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7354 // get LSB in DP2_RESULT_REG.
7355 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7356 assert(!strcmp(leftByte, DP2_RESULT_REG));
7360 // get LSB into DP2_RESULT_REG
7361 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7362 if (strcmp(leftByte, DP2_RESULT_REG))
7365 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7368 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7369 assert(strcmp(leftByte, DP2_RESULT_REG));
7372 _endLazyDPSEvaluation();
7373 *lsb = DP2_RESULT_REG;
7377 if (sameRegs (AOP (result), AOP (left)) &&
7378 ((offl + MSB16) == offr))
7380 /* don't crash result[offr] */
7381 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7382 emitcode ("xch", "a,%s",
7383 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7387 movLeft2Result (left, offl, result, offr, 0);
7388 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7390 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7391 assert(strcmp(*lsb,"a"));
7396 _storeAxResults(char *lsb,
7400 _startLazyDPSEvaluation();
7401 if (AOP_NEEDSACC(result))
7403 /* We have to explicitly update the result LSB.
7405 emitcode("xch","a,%s", lsb);
7406 aopPut(AOP(result), "a", offr);
7407 emitcode("mov","a,%s", lsb);
7409 if (getDataSize (result) > 1)
7411 aopPut (AOP (result), "a", offr + MSB16);
7413 _endLazyDPSEvaluation();
7416 /*-----------------------------------------------------------------*/
7417 /* shiftL2Left2Result - shift left two bytes from left to result */
7418 /*-----------------------------------------------------------------*/
7420 shiftL2Left2Result (operand * left, int offl,
7421 operand * result, int offr, int shCount)
7425 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7427 AccAXLsh (lsb, shCount);
7429 _storeAxResults(lsb, result, offr);
7433 #ifdef BETTER_LITERAL_SHIFT
7434 /*-----------------------------------------------------------------*/
7435 /* shiftR2Left2Result - shift right two bytes from left to result */
7436 /*-----------------------------------------------------------------*/
7438 shiftR2Left2Result (operand * left, int offl,
7439 operand * result, int offr,
7440 int shCount, int sign)
7444 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7446 /* a:x >> shCount (x = lsb(result)) */
7449 AccAXRshS(lsb, shCount);
7453 AccAXRsh(lsb, shCount);
7456 _storeAxResults(lsb, result, offr);
7462 /*-----------------------------------------------------------------*/
7463 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7464 /*-----------------------------------------------------------------*/
7466 shiftLLeftOrResult (operand * left, int offl,
7467 operand * result, int offr, int shCount)
7469 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7470 /* shift left accumulator */
7472 /* or with result */
7473 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7474 /* back to result */
7475 aopPut (AOP (result), "a", offr);
7481 /*-----------------------------------------------------------------*/
7482 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7483 /*-----------------------------------------------------------------*/
7485 shiftRLeftOrResult (operand * left, int offl,
7486 operand * result, int offr, int shCount)
7488 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7489 /* shift right accumulator */
7491 /* or with result */
7492 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7493 /* back to result */
7494 aopPut (AOP (result), "a", offr);
7498 #ifdef BETTER_LITERAL_SHIFT
7499 /*-----------------------------------------------------------------*/
7500 /* genlshOne - left shift a one byte quantity by known count */
7501 /*-----------------------------------------------------------------*/
7503 genlshOne (operand * result, operand * left, int shCount)
7505 D (emitcode (";", "genlshOne "););
7506 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7510 #ifdef BETTER_LITERAL_SHIFT
7511 /*-----------------------------------------------------------------*/
7512 /* genlshTwo - left shift two bytes by known amount != 0 */
7513 /*-----------------------------------------------------------------*/
7515 genlshTwo (operand * result, operand * left, int shCount)
7519 D (emitcode (";", "genlshTwo "););
7521 size = getDataSize (result);
7523 /* if shCount >= 8 */
7528 _startLazyDPSEvaluation();
7534 _endLazyDPSEvaluation();
7535 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7536 aopPut (AOP (result), zero, LSB);
7540 movLeft2Result (left, LSB, result, MSB16, 0);
7541 aopPut (AOP (result), zero, LSB);
7542 _endLazyDPSEvaluation();
7547 aopPut (AOP (result), zero, LSB);
7548 _endLazyDPSEvaluation();
7552 /* 1 <= shCount <= 7 */
7557 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7561 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7569 /*-----------------------------------------------------------------*/
7570 /* shiftLLong - shift left one long from left to result */
7571 /* offl = LSB or MSB16 */
7572 /*-----------------------------------------------------------------*/
7574 shiftLLong (operand * left, operand * result, int offr)
7577 int size = AOP_SIZE (result);
7579 if (size >= LSB + offr)
7581 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7583 emitcode ("add", "a,acc");
7584 if (sameRegs (AOP (left), AOP (result)) &&
7585 size >= MSB16 + offr && offr != LSB)
7586 emitcode ("xch", "a,%s",
7587 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7589 aopPut (AOP (result), "a", LSB + offr);
7592 if (size >= MSB16 + offr)
7594 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7596 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7599 emitcode ("rlc", "a");
7600 if (sameRegs (AOP (left), AOP (result)) &&
7601 size >= MSB24 + offr && offr != LSB)
7602 emitcode ("xch", "a,%s",
7603 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7605 aopPut (AOP (result), "a", MSB16 + offr);
7608 if (size >= MSB24 + offr)
7610 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7612 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7615 emitcode ("rlc", "a");
7616 if (sameRegs (AOP (left), AOP (result)) &&
7617 size >= MSB32 + offr && offr != LSB)
7618 emitcode ("xch", "a,%s",
7619 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7621 aopPut (AOP (result), "a", MSB24 + offr);
7624 if (size > MSB32 + offr)
7626 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7628 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7631 emitcode ("rlc", "a");
7632 aopPut (AOP (result), "a", MSB32 + offr);
7635 aopPut (AOP (result), zero, LSB);
7641 /*-----------------------------------------------------------------*/
7642 /* genlshFour - shift four byte by a known amount != 0 */
7643 /*-----------------------------------------------------------------*/
7645 genlshFour (operand * result, operand * left, int shCount)
7649 D (emitcode (";", "genlshFour ");
7652 size = AOP_SIZE (result);
7654 /* if shifting more that 3 bytes */
7659 /* lowest order of left goes to the highest
7660 order of the destination */
7661 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7663 movLeft2Result (left, LSB, result, MSB32, 0);
7664 aopPut (AOP (result), zero, LSB);
7665 aopPut (AOP (result), zero, MSB16);
7666 aopPut (AOP (result), zero, MSB24);
7670 /* more than two bytes */
7671 else if (shCount >= 16)
7673 /* lower order two bytes goes to higher order two bytes */
7675 /* if some more remaining */
7677 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7680 movLeft2Result (left, MSB16, result, MSB32, 0);
7681 movLeft2Result (left, LSB, result, MSB24, 0);
7683 aopPut (AOP (result), zero, MSB16);
7684 aopPut (AOP (result), zero, LSB);
7688 /* if more than 1 byte */
7689 else if (shCount >= 8)
7691 /* lower order three bytes goes to higher order three bytes */
7696 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7698 movLeft2Result (left, LSB, result, MSB16, 0);
7704 movLeft2Result (left, MSB24, result, MSB32, 0);
7705 movLeft2Result (left, MSB16, result, MSB24, 0);
7706 movLeft2Result (left, LSB, result, MSB16, 0);
7707 aopPut (AOP (result), zero, LSB);
7709 else if (shCount == 1)
7710 shiftLLong (left, result, MSB16);
7713 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7714 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7715 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7716 aopPut (AOP (result), zero, LSB);
7721 /* 1 <= shCount <= 7 */
7722 else if (shCount <= 2)
7724 shiftLLong (left, result, LSB);
7726 shiftLLong (result, result, LSB);
7728 /* 3 <= shCount <= 7, optimize */
7731 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7732 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7733 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7738 #ifdef BETTER_LITERAL_SHIFT
7739 /*-----------------------------------------------------------------*/
7740 /* genLeftShiftLiteral - left shifting by known count */
7741 /*-----------------------------------------------------------------*/
7743 genLeftShiftLiteral (operand * left,
7748 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7751 size = getSize (operandType (result));
7753 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7755 /* We only handle certain easy cases so far. */
7757 && (shCount < (size * 8))
7761 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7765 freeAsmop (right, NULL, ic, TRUE);
7767 aopOp(left, ic, FALSE, FALSE);
7768 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7771 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7773 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7774 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7776 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7779 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7781 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7782 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7784 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7790 emitcode ("; shift left ", "result %d, left %d", size,
7794 /* I suppose that the left size >= result size */
7797 _startLazyDPSEvaluation();
7800 movLeft2Result (left, size, result, size, 0);
7802 _endLazyDPSEvaluation();
7804 else if (shCount >= (size * 8))
7806 _startLazyDPSEvaluation();
7809 aopPut (AOP (result), zero, size);
7811 _endLazyDPSEvaluation();
7818 genlshOne (result, left, shCount);
7822 genlshTwo (result, left, shCount);
7826 genlshFour (result, left, shCount);
7830 fprintf(stderr, "*** ack! mystery literal shift!\n");
7834 freeAsmop (left, NULL, ic, TRUE);
7835 freeAsmop (result, NULL, ic, TRUE);
7840 /*-----------------------------------------------------------------*/
7841 /* genLeftShift - generates code for left shifting */
7842 /*-----------------------------------------------------------------*/
7844 genLeftShift (iCode * ic)
7846 operand *left, *right, *result;
7849 symbol *tlbl, *tlbl1;
7851 D (emitcode (";", "genLeftShift "););
7853 right = IC_RIGHT (ic);
7854 left = IC_LEFT (ic);
7855 result = IC_RESULT (ic);
7857 aopOp (right, ic, FALSE, FALSE);
7860 #ifdef BETTER_LITERAL_SHIFT
7861 /* if the shift count is known then do it
7862 as efficiently as possible */
7863 if (AOP_TYPE (right) == AOP_LIT)
7865 if (genLeftShiftLiteral (left, right, result, ic))
7872 /* shift count is unknown then we have to form
7873 a loop get the loop count in B : Note: we take
7874 only the lower order byte since shifting
7875 more that 32 bits make no sense anyway, ( the
7876 largest size of an object can be only 32 bits ) */
7878 if (AOP_TYPE (right) == AOP_LIT)
7880 /* Really should be handled by genLeftShiftLiteral,
7881 * but since I'm too lazy to fix that today, at least we can make
7882 * some small improvement.
7884 emitcode("mov", "b,#0x%02x",
7885 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7889 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7890 emitcode ("inc", "b");
7892 freeAsmop (right, NULL, ic, TRUE);
7893 aopOp (left, ic, FALSE, FALSE);
7894 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7896 /* now move the left to the result if they are not the
7898 if (!sameRegs (AOP (left), AOP (result)) &&
7899 AOP_SIZE (result) > 1)
7902 size = AOP_SIZE (result);
7904 _startLazyDPSEvaluation ();
7907 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7908 if (*l == '@' && (IS_AOP_PREG (result)))
7911 emitcode ("mov", "a,%s", l);
7912 aopPut (AOP (result), "a", offset);
7915 aopPut (AOP (result), l, offset);
7918 _endLazyDPSEvaluation ();
7921 tlbl = newiTempLabel (NULL);
7922 size = AOP_SIZE (result);
7924 tlbl1 = newiTempLabel (NULL);
7926 /* if it is only one byte then */
7929 symbol *tlbl1 = newiTempLabel (NULL);
7931 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7933 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7934 emitcode ("", "%05d$:", tlbl->key + 100);
7935 emitcode ("add", "a,acc");
7936 emitcode ("", "%05d$:", tlbl1->key + 100);
7937 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7938 aopPut (AOP (result), "a", 0);
7942 reAdjustPreg (AOP (result));
7944 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7945 emitcode ("", "%05d$:", tlbl->key + 100);
7946 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7948 emitcode ("add", "a,acc");
7949 aopPut (AOP (result), "a", offset++);
7950 _startLazyDPSEvaluation ();
7953 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7955 emitcode ("rlc", "a");
7956 aopPut (AOP (result), "a", offset++);
7958 _endLazyDPSEvaluation ();
7959 reAdjustPreg (AOP (result));
7961 emitcode ("", "%05d$:", tlbl1->key + 100);
7962 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7964 freeAsmop (left, NULL, ic, TRUE);
7965 freeAsmop (result, NULL, ic, TRUE);
7968 #ifdef BETTER_LITERAL_SHIFT
7969 /*-----------------------------------------------------------------*/
7970 /* genrshOne - right shift a one byte quantity by known count */
7971 /*-----------------------------------------------------------------*/
7973 genrshOne (operand * result, operand * left,
7974 int shCount, int sign)
7976 D (emitcode (";", "genrshOne"););
7977 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7981 #ifdef BETTER_LITERAL_SHIFT
7982 /*-----------------------------------------------------------------*/
7983 /* genrshTwo - right shift two bytes by known amount != 0 */
7984 /*-----------------------------------------------------------------*/
7986 genrshTwo (operand * result, operand * left,
7987 int shCount, int sign)
7989 D (emitcode (";", "genrshTwo"););
7991 /* if shCount >= 8 */
7995 _startLazyDPSEvaluation();
7998 shiftR1Left2Result (left, MSB16, result, LSB,
8003 movLeft2Result (left, MSB16, result, LSB, sign);
8005 addSign (result, MSB16, sign);
8006 _endLazyDPSEvaluation();
8009 /* 1 <= shCount <= 7 */
8012 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8019 /*-----------------------------------------------------------------*/
8020 /* shiftRLong - shift right one long from left to result */
8021 /* offl = LSB or MSB16 */
8022 /*-----------------------------------------------------------------*/
8024 shiftRLong (operand * left, int offl,
8025 operand * result, int sign)
8027 int isSameRegs=sameRegs(AOP(left),AOP(result));
8029 if (isSameRegs && offl>1) {
8030 // we are in big trouble, but this shouldn't happen
8031 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8034 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
8039 emitcode ("rlc", "a");
8040 emitcode ("subb", "a,acc");
8041 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
8043 aopPut (AOP(result), zero, MSB32);
8048 emitcode ("clr", "c");
8050 emitcode ("mov", "c,acc.7");
8053 emitcode ("rrc", "a");
8055 if (isSameRegs && offl==MSB16) {
8056 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
8058 aopPut (AOP (result), "a", MSB32);
8059 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
8062 emitcode ("rrc", "a");
8063 if (isSameRegs && offl==1) {
8064 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
8066 aopPut (AOP (result), "a", MSB24);
8067 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
8069 emitcode ("rrc", "a");
8070 aopPut (AOP (result), "a", MSB16 - offl);
8074 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
8075 emitcode ("rrc", "a");
8076 aopPut (AOP (result), "a", LSB);
8083 /*-----------------------------------------------------------------*/
8084 /* genrshFour - shift four byte by a known amount != 0 */
8085 /*-----------------------------------------------------------------*/
8087 genrshFour (operand * result, operand * left,
8088 int shCount, int sign)
8090 D (emitcode (";", "genrshFour");
8093 /* if shifting more that 3 bytes */
8098 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8100 movLeft2Result (left, MSB32, result, LSB, sign);
8101 addSign (result, MSB16, sign);
8103 else if (shCount >= 16)
8107 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8110 movLeft2Result (left, MSB24, result, LSB, 0);
8111 movLeft2Result (left, MSB32, result, MSB16, sign);
8113 addSign (result, MSB24, sign);
8115 else if (shCount >= 8)
8119 shiftRLong (left, MSB16, result, sign);
8120 else if (shCount == 0)
8122 movLeft2Result (left, MSB16, result, LSB, 0);
8123 movLeft2Result (left, MSB24, result, MSB16, 0);
8124 movLeft2Result (left, MSB32, result, MSB24, sign);
8125 addSign (result, MSB32, sign);
8129 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8130 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8131 /* the last shift is signed */
8132 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8133 addSign (result, MSB32, sign);
8137 { /* 1 <= shCount <= 7 */
8140 shiftRLong (left, LSB, result, sign);
8142 shiftRLong (result, LSB, result, sign);
8146 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8147 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8148 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8154 #ifdef BETTER_LITERAL_SHIFT
8155 /*-----------------------------------------------------------------*/
8156 /* genRightShiftLiteral - right shifting by known count */
8157 /*-----------------------------------------------------------------*/
8159 genRightShiftLiteral (operand * left,
8165 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8168 size = getSize (operandType (result));
8170 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8172 /* We only handle certain easy cases so far. */
8174 && (shCount < (size * 8))
8178 D(emitcode (";", "genRightShiftLiteral wimping out"););
8182 freeAsmop (right, NULL, ic, TRUE);
8184 aopOp (left, ic, FALSE, FALSE);
8185 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8188 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8192 /* test the LEFT size !!! */
8194 /* I suppose that the left size >= result size */
8197 size = getDataSize (result);
8198 _startLazyDPSEvaluation();
8201 movLeft2Result (left, size, result, size, 0);
8203 _endLazyDPSEvaluation();
8205 else if (shCount >= (size * 8))
8209 /* get sign in acc.7 */
8210 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8212 addSign (result, LSB, sign);
8219 genrshOne (result, left, shCount, sign);
8223 genrshTwo (result, left, shCount, sign);
8227 genrshFour (result, left, shCount, sign);
8234 freeAsmop (left, NULL, ic, TRUE);
8235 freeAsmop (result, NULL, ic, TRUE);
8241 /*-----------------------------------------------------------------*/
8242 /* genSignedRightShift - right shift of signed number */
8243 /*-----------------------------------------------------------------*/
8245 genSignedRightShift (iCode * ic)
8247 operand *right, *left, *result;
8250 symbol *tlbl, *tlbl1;
8252 D (emitcode (";", "genSignedRightShift "););
8254 /* we do it the hard way put the shift count in b
8255 and loop thru preserving the sign */
8257 right = IC_RIGHT (ic);
8258 left = IC_LEFT (ic);
8259 result = IC_RESULT (ic);
8261 aopOp (right, ic, FALSE, FALSE);
8263 #ifdef BETTER_LITERAL_SHIFT
8264 if (AOP_TYPE (right) == AOP_LIT)
8266 if (genRightShiftLiteral (left, right, result, ic, 1))
8272 /* shift count is unknown then we have to form
8273 a loop get the loop count in B : Note: we take
8274 only the lower order byte since shifting
8275 more that 32 bits make no sense anyway, ( the
8276 largest size of an object can be only 32 bits ) */
8278 if (AOP_TYPE (right) == AOP_LIT)
8280 /* Really should be handled by genRightShiftLiteral,
8281 * but since I'm too lazy to fix that today, at least we can make
8282 * some small improvement.
8284 emitcode("mov", "b,#0x%02x",
8285 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8289 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8290 emitcode ("inc", "b");
8292 freeAsmop (right, NULL, ic, TRUE);
8293 aopOp (left, ic, FALSE, FALSE);
8294 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8296 /* now move the left to the result if they are not the
8298 if (!sameRegs (AOP (left), AOP (result)) &&
8299 AOP_SIZE (result) > 1)
8302 size = AOP_SIZE (result);
8304 _startLazyDPSEvaluation ();
8307 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8308 if (*l == '@' && IS_AOP_PREG (result))
8311 emitcode ("mov", "a,%s", l);
8312 aopPut (AOP (result), "a", offset);
8315 aopPut (AOP (result), l, offset);
8318 _endLazyDPSEvaluation ();
8321 /* mov the highest order bit to OVR */
8322 tlbl = newiTempLabel (NULL);
8323 tlbl1 = newiTempLabel (NULL);
8325 size = AOP_SIZE (result);
8327 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8328 emitcode ("rlc", "a");
8329 emitcode ("mov", "ov,c");
8330 /* if it is only one byte then */
8333 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8335 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8336 emitcode ("", "%05d$:", tlbl->key + 100);
8337 emitcode ("mov", "c,ov");
8338 emitcode ("rrc", "a");
8339 emitcode ("", "%05d$:", tlbl1->key + 100);
8340 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8341 aopPut (AOP (result), "a", 0);
8345 reAdjustPreg (AOP (result));
8346 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8347 emitcode ("", "%05d$:", tlbl->key + 100);
8348 emitcode ("mov", "c,ov");
8349 _startLazyDPSEvaluation ();
8352 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8354 emitcode ("rrc", "a");
8355 aopPut (AOP (result), "a", offset--);
8357 _endLazyDPSEvaluation ();
8358 reAdjustPreg (AOP (result));
8359 emitcode ("", "%05d$:", tlbl1->key + 100);
8360 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8363 freeAsmop (left, NULL, ic, TRUE);
8364 freeAsmop (result, NULL, ic, TRUE);
8367 /*-----------------------------------------------------------------*/
8368 /* genRightShift - generate code for right shifting */
8369 /*-----------------------------------------------------------------*/
8371 genRightShift (iCode * ic)
8373 operand *right, *left, *result;
8377 symbol *tlbl, *tlbl1;
8379 D (emitcode (";", "genRightShift "););
8381 /* if signed then we do it the hard way preserve the
8382 sign bit moving it inwards */
8383 retype = getSpec (operandType (IC_RESULT (ic)));
8385 if (!SPEC_USIGN (retype))
8387 genSignedRightShift (ic);
8391 /* signed & unsigned types are treated the same : i.e. the
8392 signed is NOT propagated inwards : quoting from the
8393 ANSI - standard : "for E1 >> E2, is equivalent to division
8394 by 2**E2 if unsigned or if it has a non-negative value,
8395 otherwise the result is implementation defined ", MY definition
8396 is that the sign does not get propagated */
8398 right = IC_RIGHT (ic);
8399 left = IC_LEFT (ic);
8400 result = IC_RESULT (ic);
8402 aopOp (right, ic, FALSE, FALSE);
8404 #ifdef BETTER_LITERAL_SHIFT
8405 /* if the shift count is known then do it
8406 as efficiently as possible */
8407 if (AOP_TYPE (right) == AOP_LIT)
8409 if (genRightShiftLiteral (left, right, result, ic, 0))
8416 /* shift count is unknown then we have to form
8417 a loop get the loop count in B : Note: we take
8418 only the lower order byte since shifting
8419 more that 32 bits make no sense anyway, ( the
8420 largest size of an object can be only 32 bits ) */
8422 if (AOP_TYPE (right) == AOP_LIT)
8424 /* Really should be handled by genRightShiftLiteral,
8425 * but since I'm too lazy to fix that today, at least we can make
8426 * some small improvement.
8428 emitcode("mov", "b,#0x%02x",
8429 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8433 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8434 emitcode ("inc", "b");
8436 freeAsmop (right, NULL, ic, TRUE);
8437 aopOp (left, ic, FALSE, FALSE);
8438 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8440 /* now move the left to the result if they are not the
8442 if (!sameRegs (AOP (left), AOP (result)) &&
8443 AOP_SIZE (result) > 1)
8446 size = AOP_SIZE (result);
8448 _startLazyDPSEvaluation ();
8451 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8452 if (*l == '@' && IS_AOP_PREG (result))
8455 emitcode ("mov", "a,%s", l);
8456 aopPut (AOP (result), "a", offset);
8459 aopPut (AOP (result), l, offset);
8462 _endLazyDPSEvaluation ();
8465 tlbl = newiTempLabel (NULL);
8466 tlbl1 = newiTempLabel (NULL);
8467 size = AOP_SIZE (result);
8470 /* if it is only one byte then */
8473 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8475 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8476 emitcode ("", "%05d$:", tlbl->key + 100);
8478 emitcode ("rrc", "a");
8479 emitcode ("", "%05d$:", tlbl1->key + 100);
8480 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8481 aopPut (AOP (result), "a", 0);
8485 reAdjustPreg (AOP (result));
8486 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8487 emitcode ("", "%05d$:", tlbl->key + 100);
8489 _startLazyDPSEvaluation ();
8492 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8494 emitcode ("rrc", "a");
8495 aopPut (AOP (result), "a", offset--);
8497 _endLazyDPSEvaluation ();
8498 reAdjustPreg (AOP (result));
8500 emitcode ("", "%05d$:", tlbl1->key + 100);
8501 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8504 freeAsmop (left, NULL, ic, TRUE);
8505 freeAsmop (result, NULL, ic, TRUE);
8508 /*-----------------------------------------------------------------*/
8509 /* genUnpackBits - generates code for unpacking bits */
8510 /*-----------------------------------------------------------------*/
8512 genUnpackBits (operand * result, char *rname, int ptype)
8519 D (emitcode (";", "genUnpackBits ");
8522 etype = getSpec (operandType (result));
8524 /* read the first byte */
8530 emitcode ("mov", "a,@%s", rname);
8534 emitcode ("movx", "a,@%s", rname);
8538 emitcode ("movx", "a,@dptr");
8542 emitcode ("clr", "a");
8543 emitcode ("movc", "a,@a+dptr");
8547 emitcode ("lcall", "__gptrget");
8551 /* if we have bitdisplacement then it fits */
8552 /* into this byte completely or if length is */
8553 /* less than a byte */
8554 if ((shCnt = SPEC_BSTR (etype)) ||
8555 (SPEC_BLEN (etype) <= 8))
8558 /* shift right acc */
8561 emitcode ("anl", "a,#0x%02x",
8562 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8563 aopPut (AOP (result), "a", offset);
8567 /* bit field did not fit in a byte */
8568 rlen = SPEC_BLEN (etype) - 8;
8569 aopPut (AOP (result), "a", offset++);
8578 emitcode ("inc", "%s", rname);
8579 emitcode ("mov", "a,@%s", rname);
8583 emitcode ("inc", "%s", rname);
8584 emitcode ("movx", "a,@%s", rname);
8588 emitcode ("inc", "dptr");
8589 emitcode ("movx", "a,@dptr");
8593 emitcode ("clr", "a");
8594 emitcode ("inc", "dptr");
8595 emitcode ("movc", "a,@a+dptr");
8599 emitcode ("inc", "dptr");
8600 emitcode ("lcall", "__gptrget");
8605 /* if we are done */
8609 aopPut (AOP (result), "a", offset++);
8615 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
8616 aopPut (AOP (result), "a", offset);
8623 /*-----------------------------------------------------------------*/
8624 /* genDataPointerGet - generates code when ptr offset is known */
8625 /*-----------------------------------------------------------------*/
8627 genDataPointerGet (operand * left,
8633 int size, offset = 0;
8634 aopOp (result, ic, TRUE, FALSE);
8636 /* get the string representation of the name */
8637 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8638 size = AOP_SIZE (result);
8639 _startLazyDPSEvaluation ();
8643 sprintf (buffer, "(%s + %d)", l + 1, offset);
8645 sprintf (buffer, "%s", l + 1);
8646 aopPut (AOP (result), buffer, offset++);
8648 _endLazyDPSEvaluation ();
8650 freeAsmop (left, NULL, ic, TRUE);
8651 freeAsmop (result, NULL, ic, TRUE);
8654 /*-----------------------------------------------------------------*/
8655 /* genNearPointerGet - emitcode for near pointer fetch */
8656 /*-----------------------------------------------------------------*/
8658 genNearPointerGet (operand * left,
8666 sym_link *rtype, *retype, *letype;
8667 sym_link *ltype = operandType (left);
8670 rtype = operandType (result);
8671 retype = getSpec (rtype);
8672 letype = getSpec (ltype);
8674 aopOp (left, ic, FALSE, FALSE);
8676 /* if left is rematerialisable and
8677 result is not bit variable type and
8678 the left is pointer to data space i.e
8679 lower 128 bytes of space */
8680 if (AOP_TYPE (left) == AOP_IMMD &&
8681 !IS_BITVAR (retype) &&
8682 !IS_BITVAR (letype) &&
8683 DCL_TYPE (ltype) == POINTER)
8685 genDataPointerGet (left, result, ic);
8689 /* if the value is already in a pointer register
8690 then don't need anything more */
8691 if (!AOP_INPREG (AOP (left)))
8693 /* otherwise get a free pointer register */
8695 preg = getFreePtr (ic, &aop, FALSE);
8696 emitcode ("mov", "%s,%s",
8698 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8702 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8704 freeAsmop (left, NULL, ic, TRUE);
8705 aopOp (result, ic, FALSE, FALSE);
8707 /* if bitfield then unpack the bits */
8708 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8709 genUnpackBits (result, rname, POINTER);
8712 /* we have can just get the values */
8713 int size = AOP_SIZE (result);
8718 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8721 emitcode ("mov", "a,@%s", rname);
8722 aopPut (AOP (result), "a", offset);
8726 sprintf (buffer, "@%s", rname);
8727 aopPut (AOP (result), buffer, offset);
8731 emitcode ("inc", "%s", rname);
8735 /* now some housekeeping stuff */
8738 /* we had to allocate for this iCode */
8739 if (pi) { /* post increment present */
8740 aopPut(AOP ( left ),rname,0);
8742 freeAsmop (NULL, aop, ic, TRUE);
8746 /* we did not allocate which means left
8747 already in a pointer register, then
8748 if size > 0 && this could be used again
8749 we have to point it back to where it
8751 if (AOP_SIZE (result) > 1 &&
8752 !OP_SYMBOL (left)->remat &&
8753 (OP_SYMBOL (left)->liveTo > ic->seq ||
8757 int size = AOP_SIZE (result) - 1;
8759 emitcode ("dec", "%s", rname);
8764 freeAsmop (result, NULL, ic, TRUE);
8765 if (pi) pi->generated = 1;
8768 /*-----------------------------------------------------------------*/
8769 /* genPagedPointerGet - emitcode for paged pointer fetch */
8770 /*-----------------------------------------------------------------*/
8772 genPagedPointerGet (operand * left,
8780 sym_link *rtype, *retype, *letype;
8782 rtype = operandType (result);
8783 retype = getSpec (rtype);
8784 letype = getSpec (operandType (left));
8785 aopOp (left, ic, FALSE, FALSE);
8787 /* if the value is already in a pointer register
8788 then don't need anything more */
8789 if (!AOP_INPREG (AOP (left)))
8791 /* otherwise get a free pointer register */
8793 preg = getFreePtr (ic, &aop, FALSE);
8794 emitcode ("mov", "%s,%s",
8796 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8800 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8802 freeAsmop (left, NULL, ic, TRUE);
8803 aopOp (result, ic, FALSE, FALSE);
8805 /* if bitfield then unpack the bits */
8806 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8807 genUnpackBits (result, rname, PPOINTER);
8810 /* we have can just get the values */
8811 int size = AOP_SIZE (result);
8817 emitcode ("movx", "a,@%s", rname);
8818 aopPut (AOP (result), "a", offset);
8823 emitcode ("inc", "%s", rname);
8827 /* now some housekeeping stuff */
8830 /* we had to allocate for this iCode */
8831 if (pi) aopPut ( AOP (left), rname, 0);
8832 freeAsmop (NULL, aop, ic, TRUE);
8836 /* we did not allocate which means left
8837 already in a pointer register, then
8838 if size > 0 && this could be used again
8839 we have to point it back to where it
8841 if (AOP_SIZE (result) > 1 &&
8842 !OP_SYMBOL (left)->remat &&
8843 (OP_SYMBOL (left)->liveTo > ic->seq ||
8847 int size = AOP_SIZE (result) - 1;
8849 emitcode ("dec", "%s", rname);
8854 freeAsmop (result, NULL, ic, TRUE);
8855 if (pi) pi->generated = 1;
8858 /*-----------------------------------------------------------------*/
8859 /* genFarPointerGet - gget value from far space */
8860 /*-----------------------------------------------------------------*/
8862 genFarPointerGet (operand * left,
8863 operand * result, iCode * ic, iCode *pi)
8866 sym_link *retype = getSpec (operandType (result));
8867 sym_link *letype = getSpec (operandType (left));
8868 D (emitcode (";", "genFarPointerGet");
8871 aopOp (left, ic, FALSE, FALSE);
8873 /* if the operand is already in dptr
8874 then we do nothing else we move the value to dptr */
8875 if (AOP_TYPE (left) != AOP_STR)
8877 /* if this is remateriazable */
8878 if (AOP_TYPE (left) == AOP_IMMD)
8880 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8884 /* we need to get it byte by byte */
8885 _startLazyDPSEvaluation ();
8886 if (AOP_TYPE (left) != AOP_DPTR)
8888 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8889 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8890 if (options.model == MODEL_FLAT24)
8891 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8895 /* We need to generate a load to DPTR indirect through DPTR. */
8896 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8898 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8899 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8900 if (options.model == MODEL_FLAT24)
8901 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8902 emitcode ("pop", "dph");
8903 emitcode ("pop", "dpl");
8905 _endLazyDPSEvaluation ();
8908 /* so dptr know contains the address */
8909 aopOp (result, ic, FALSE, TRUE);
8911 /* if bit then unpack */
8912 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8913 genUnpackBits (result, "dptr", FPOINTER);
8916 size = AOP_SIZE (result);
8919 _startLazyDPSEvaluation ();
8926 emitcode ("movx", "a,@dptr");
8927 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
8928 emitcode ("inc", "dptr");
8930 aopPut (AOP (result), "a", offset++);
8932 _endLazyDPSEvaluation ();
8934 if (pi && AOP_TYPE (left) != AOP_IMMD) {
8935 aopPut ( AOP (left), "dpl", 0);
8936 aopPut ( AOP (left), "dph", 1);
8937 if (options.model == MODEL_FLAT24)
8938 aopPut ( AOP (left), "dpx", 2);
8940 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
8941 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
8943 size = AOP_SIZE (result) - 1;
8944 while (size--) emitcode ("lcall","__decdptr");
8947 freeAsmop (left, NULL, ic, TRUE);
8948 freeAsmop (result, NULL, ic, TRUE);
8951 /*-----------------------------------------------------------------*/
8952 /* emitcodePointerGet - gget value from code space */
8953 /*-----------------------------------------------------------------*/
8955 emitcodePointerGet (operand * left,
8956 operand * result, iCode * ic, iCode *pi)
8959 sym_link *retype = getSpec (operandType (result));
8961 aopOp (left, ic, FALSE, FALSE);
8963 /* if the operand is already in dptr
8964 then we do nothing else we move the value to dptr */
8965 if (AOP_TYPE (left) != AOP_STR)
8967 /* if this is remateriazable */
8968 if (AOP_TYPE (left) == AOP_IMMD)
8970 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8973 { /* we need to get it byte by byte */
8974 _startLazyDPSEvaluation ();
8975 if (AOP_TYPE (left) != AOP_DPTR)
8977 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8978 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8979 if (options.model == MODEL_FLAT24)
8980 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8984 /* We need to generate a load to DPTR indirect through DPTR. */
8985 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8987 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8988 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8989 if (options.model == MODEL_FLAT24)
8990 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8991 emitcode ("pop", "dph");
8992 emitcode ("pop", "dpl");
8994 _endLazyDPSEvaluation ();
8997 /* so dptr know contains the address */
8998 aopOp (result, ic, FALSE, TRUE);
9000 /* if bit then unpack */
9001 if (IS_BITVAR (retype))
9002 genUnpackBits (result, "dptr", CPOINTER);
9005 size = AOP_SIZE (result);
9008 _startLazyDPSEvaluation ();
9014 emitcode ("clr", "a");
9015 emitcode ("movc", "a,@a+dptr");
9016 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9017 emitcode ("inc", "dptr");
9018 aopPut (AOP (result), "a", offset++);
9020 _endLazyDPSEvaluation ();
9022 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9023 aopPut ( AOP (left), "dpl", 0);
9024 aopPut ( AOP (left), "dph", 1);
9025 if (options.model == MODEL_FLAT24)
9026 aopPut ( AOP (left), "dpx", 2);
9028 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9029 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9031 size = AOP_SIZE (result) - 1;
9032 while (size--) emitcode ("lcall","__decdptr");
9035 freeAsmop (left, NULL, ic, TRUE);
9036 freeAsmop (result, NULL, ic, TRUE);
9039 /*-----------------------------------------------------------------*/
9040 /* genGenPointerGet - gget value from generic pointer space */
9041 /*-----------------------------------------------------------------*/
9043 genGenPointerGet (operand * left,
9044 operand * result, iCode * ic, iCode * pi)
9047 sym_link *retype = getSpec (operandType (result));
9048 sym_link *letype = getSpec (operandType (left));
9050 D (emitcode (";", "genGenPointerGet "); );
9052 aopOp (left, ic, FALSE, (OP_SYMBOL(left)->ruonly ? FALSE : TRUE));
9054 /* if the operand is already in dptr
9055 then we do nothing else we move the value to dptr */
9056 if (AOP_TYPE (left) != AOP_STR)
9058 /* if this is remateriazable */
9059 if (AOP_TYPE (left) == AOP_IMMD)
9061 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9062 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9063 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
9065 emitcode ("mov", "b,#%d", pointerCode (retype));
9068 { /* we need to get it byte by byte */
9069 _startLazyDPSEvaluation ();
9070 if (AOP(left)->type==AOP_DPTR2) {
9072 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
9075 emitcode ("mov", "dpl,%s", l);
9076 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
9079 emitcode ("mov", "dph,%s", l);
9080 if (options.model == MODEL_FLAT24) {
9081 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
9084 emitcode ("mov", "dpx,%s", l);
9085 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9087 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9090 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
9091 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
9092 if (options.model == MODEL_FLAT24) {
9093 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9094 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9096 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9099 _endLazyDPSEvaluation ();
9102 /* so dptr know contains the address */
9103 aopOp (result, ic, FALSE, TRUE);
9105 /* if bit then unpack */
9106 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9107 genUnpackBits (result, "dptr", GPOINTER);
9110 size = AOP_SIZE (result);
9115 emitcode ("lcall", "__gptrget");
9116 aopPut (AOP (result), "a", offset++);
9117 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9118 emitcode ("inc", "dptr");
9122 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9123 aopPut ( AOP (left), "dpl", 0);
9124 aopPut ( AOP (left), "dph", 1);
9125 if (options.model == MODEL_FLAT24) {
9126 aopPut ( AOP (left), "dpx", 2);
9127 aopPut ( AOP (left), "b", 3);
9128 } else aopPut ( AOP (left), "b", 2);
9130 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9131 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9133 size = AOP_SIZE (result) - 1;
9134 while (size--) emitcode ("lcall","__decdptr");
9137 freeAsmop (left, NULL, ic, TRUE);
9138 freeAsmop (result, NULL, ic, TRUE);
9141 /*-----------------------------------------------------------------*/
9142 /* genPointerGet - generate code for pointer get */
9143 /*-----------------------------------------------------------------*/
9145 genPointerGet (iCode * ic, iCode *pi)
9147 operand *left, *result;
9148 sym_link *type, *etype;
9151 D (emitcode (";", "genPointerGet ");
9154 left = IC_LEFT (ic);
9155 result = IC_RESULT (ic);
9157 /* depending on the type of pointer we need to
9158 move it to the correct pointer register */
9159 type = operandType (left);
9160 etype = getSpec (type);
9161 /* if left is of type of pointer then it is simple */
9162 if (IS_PTR (type) && !IS_FUNC (type->next))
9163 p_type = DCL_TYPE (type);
9166 /* we have to go by the storage class */
9167 p_type = PTR_TYPE (SPEC_OCLS (etype));
9169 /* special case when cast remat */
9170 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9171 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9172 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9173 type = type = operandType (left);
9174 p_type = DCL_TYPE (type);
9176 /* now that we have the pointer type we assign
9177 the pointer values */
9183 genNearPointerGet (left, result, ic, pi);
9187 genPagedPointerGet (left, result, ic, pi);
9191 genFarPointerGet (left, result, ic, pi);
9195 emitcodePointerGet (left, result, ic, pi);
9199 genGenPointerGet (left, result, ic, pi);
9205 /*-----------------------------------------------------------------*/
9206 /* genPackBits - generates code for packed bit storage */
9207 /*-----------------------------------------------------------------*/
9209 genPackBits (sym_link * etype,
9211 char *rname, int p_type)
9219 blen = SPEC_BLEN (etype);
9220 bstr = SPEC_BSTR (etype);
9222 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9225 /* if the bit lenth is less than or */
9226 /* it exactly fits a byte then */
9227 if (SPEC_BLEN (etype) <= 8)
9229 shCount = SPEC_BSTR (etype);
9231 /* shift left acc */
9234 if (SPEC_BLEN (etype) < 8)
9235 { /* if smaller than a byte */
9241 emitcode ("mov", "b,a");
9242 emitcode ("mov", "a,@%s", rname);
9246 emitcode ("mov", "b,a");
9247 emitcode ("movx", "a,@dptr");
9251 emitcode ("push", "b");
9252 emitcode ("push", "acc");
9253 emitcode ("lcall", "__gptrget");
9254 emitcode ("pop", "b");
9258 emitcode ("anl", "a,#0x%02x", (unsigned char)
9259 ((unsigned char) (0xFF << (blen + bstr)) |
9260 (unsigned char) (0xFF >> (8 - bstr))));
9261 emitcode ("orl", "a,b");
9262 if (p_type == GPOINTER)
9263 emitcode ("pop", "b");
9270 emitcode ("mov", "@%s,a", rname);
9274 emitcode ("movx", "@dptr,a");
9278 emitcode ("lcall", "__gptrput");
9283 if (SPEC_BLEN (etype) <= 8)
9286 emitcode ("inc", "%s", rname);
9287 rLen = SPEC_BLEN (etype);
9289 /* now generate for lengths greater than one byte */
9293 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9305 emitcode ("mov", "@%s,a", rname);
9308 emitcode ("mov", "@%s,%s", rname, l);
9313 emitcode ("movx", "@dptr,a");
9318 emitcode ("lcall", "__gptrput");
9321 emitcode ("inc", "%s", rname);
9326 /* last last was not complete */
9329 /* save the byte & read byte */
9333 emitcode ("mov", "b,a");
9334 emitcode ("mov", "a,@%s", rname);
9338 emitcode ("mov", "b,a");
9339 emitcode ("movx", "a,@dptr");
9343 emitcode ("push", "b");
9344 emitcode ("push", "acc");
9345 emitcode ("lcall", "__gptrget");
9346 emitcode ("pop", "b");
9350 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
9351 emitcode ("orl", "a,b");
9354 if (p_type == GPOINTER)
9355 emitcode ("pop", "b");
9361 emitcode ("mov", "@%s,a", rname);
9365 emitcode ("movx", "@dptr,a");
9369 emitcode ("lcall", "__gptrput");
9373 /*-----------------------------------------------------------------*/
9374 /* genDataPointerSet - remat pointer to data space */
9375 /*-----------------------------------------------------------------*/
9377 genDataPointerSet (operand * right,
9381 int size, offset = 0;
9382 char *l, buffer[256];
9384 aopOp (right, ic, FALSE, FALSE);
9386 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9387 size = AOP_SIZE (right);
9391 sprintf (buffer, "(%s + %d)", l + 1, offset);
9393 sprintf (buffer, "%s", l + 1);
9394 emitcode ("mov", "%s,%s", buffer,
9395 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9398 freeAsmop (right, NULL, ic, TRUE);
9399 freeAsmop (result, NULL, ic, TRUE);
9402 /*-----------------------------------------------------------------*/
9403 /* genNearPointerSet - emitcode for near pointer put */
9404 /*-----------------------------------------------------------------*/
9406 genNearPointerSet (operand * right,
9414 sym_link *retype, *letype;
9415 sym_link *ptype = operandType (result);
9417 retype = getSpec (operandType (right));
9418 letype = getSpec (ptype);
9420 aopOp (result, ic, FALSE, FALSE);
9422 /* if the result is rematerializable &
9423 in data space & not a bit variable */
9424 if (AOP_TYPE (result) == AOP_IMMD &&
9425 DCL_TYPE (ptype) == POINTER &&
9426 !IS_BITVAR (retype) &&
9427 !IS_BITVAR (letype))
9429 genDataPointerSet (right, result, ic);
9433 /* if the value is already in a pointer register
9434 then don't need anything more */
9435 if (!AOP_INPREG (AOP (result)))
9437 /* otherwise get a free pointer register */
9439 preg = getFreePtr (ic, &aop, FALSE);
9440 emitcode ("mov", "%s,%s",
9442 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9446 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9448 aopOp (right, ic, FALSE, FALSE);
9450 /* if bitfield then unpack the bits */
9451 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9452 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9455 /* we have can just get the values */
9456 int size = AOP_SIZE (right);
9461 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9465 emitcode ("mov", "@%s,a", rname);
9468 emitcode ("mov", "@%s,%s", rname, l);
9470 emitcode ("inc", "%s", rname);
9475 /* now some housekeeping stuff */
9478 /* we had to allocate for this iCode */
9479 if (pi) aopPut (AOP (result),rname,0);
9480 freeAsmop (NULL, aop, ic, TRUE);
9484 /* we did not allocate which means left
9485 already in a pointer register, then
9486 if size > 0 && this could be used again
9487 we have to point it back to where it
9489 if (AOP_SIZE (right) > 1 &&
9490 !OP_SYMBOL (result)->remat &&
9491 (OP_SYMBOL (result)->liveTo > ic->seq ||
9495 int size = AOP_SIZE (right) - 1;
9497 emitcode ("dec", "%s", rname);
9502 if (pi) pi->generated = 1;
9503 freeAsmop (result, NULL, ic, TRUE);
9504 freeAsmop (right, NULL, ic, TRUE);
9509 /*-----------------------------------------------------------------*/
9510 /* genPagedPointerSet - emitcode for Paged pointer put */
9511 /*-----------------------------------------------------------------*/
9513 genPagedPointerSet (operand * right,
9521 sym_link *retype, *letype;
9523 retype = getSpec (operandType (right));
9524 letype = getSpec (operandType (result));
9526 aopOp (result, ic, FALSE, FALSE);
9528 /* if the value is already in a pointer register
9529 then don't need anything more */
9530 if (!AOP_INPREG (AOP (result)))
9532 /* otherwise get a free pointer register */
9534 preg = getFreePtr (ic, &aop, FALSE);
9535 emitcode ("mov", "%s,%s",
9537 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9541 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9543 aopOp (right, ic, FALSE, FALSE);
9545 /* if bitfield then unpack the bits */
9546 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9547 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9550 /* we have can just get the values */
9551 int size = AOP_SIZE (right);
9556 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9559 emitcode ("movx", "@%s,a", rname);
9562 emitcode ("inc", "%s", rname);
9568 /* now some housekeeping stuff */
9571 if (pi) aopPut (AOP (result),rname,0);
9572 /* we had to allocate for this iCode */
9573 freeAsmop (NULL, aop, ic, TRUE);
9577 /* we did not allocate which means left
9578 already in a pointer register, then
9579 if size > 0 && this could be used again
9580 we have to point it back to where it
9582 if (AOP_SIZE (right) > 1 &&
9583 !OP_SYMBOL (result)->remat &&
9584 (OP_SYMBOL (result)->liveTo > ic->seq ||
9588 int size = AOP_SIZE (right) - 1;
9590 emitcode ("dec", "%s", rname);
9595 if (pi) pi->generated = 1;
9596 freeAsmop (result, NULL, ic, TRUE);
9597 freeAsmop (right, NULL, ic, TRUE);
9602 /*-----------------------------------------------------------------*/
9603 /* genFarPointerSet - set value from far space */
9604 /*-----------------------------------------------------------------*/
9606 genFarPointerSet (operand * right,
9607 operand * result, iCode * ic, iCode *pi)
9610 sym_link *retype = getSpec (operandType (right));
9611 sym_link *letype = getSpec (operandType (result));
9613 aopOp (result, ic, FALSE, FALSE);
9615 /* if the operand is already in dptr
9616 then we do nothing else we move the value to dptr */
9617 if (AOP_TYPE (result) != AOP_STR)
9619 /* if this is remateriazable */
9620 if (AOP_TYPE (result) == AOP_IMMD)
9621 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9624 /* we need to get it byte by byte */
9625 _startLazyDPSEvaluation ();
9626 if (AOP_TYPE (result) != AOP_DPTR)
9628 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9629 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9630 if (options.model == MODEL_FLAT24)
9631 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9635 /* We need to generate a load to DPTR indirect through DPTR. */
9636 D (emitcode (";", "genFarPointerSet -- indirection special case.");
9638 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9639 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9640 if (options.model == MODEL_FLAT24)
9641 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9642 emitcode ("pop", "dph");
9643 emitcode ("pop", "dpl");
9645 _endLazyDPSEvaluation ();
9648 /* so dptr know contains the address */
9649 aopOp (right, ic, FALSE, TRUE);
9651 /* if bit then unpack */
9652 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9653 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9656 size = AOP_SIZE (right);
9659 _startLazyDPSEvaluation ();
9662 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9668 emitcode ("movx", "@dptr,a");
9669 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
9670 emitcode ("inc", "dptr");
9672 _endLazyDPSEvaluation ();
9675 if (pi && AOP_TYPE (result) != AOP_IMMD) {
9676 aopPut (AOP(result),"dpl",0);
9677 aopPut (AOP(result),"dph",1);
9678 if (options.model == MODEL_FLAT24)
9679 aopPut (AOP(result),"dpx",2);
9681 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9682 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9684 size = AOP_SIZE (right) - 1;
9685 while (size--) emitcode ("lcall","__decdptr");
9687 freeAsmop (result, NULL, ic, TRUE);
9688 freeAsmop (right, NULL, ic, TRUE);
9691 /*-----------------------------------------------------------------*/
9692 /* genGenPointerSet - set value from generic pointer space */
9693 /*-----------------------------------------------------------------*/
9695 genGenPointerSet (operand * right,
9696 operand * result, iCode * ic, iCode *pi)
9699 sym_link *retype = getSpec (operandType (right));
9700 sym_link *letype = getSpec (operandType (result));
9702 aopOp (result, ic, FALSE, OP_SYMBOL(result)->ruonly ? FALSE : TRUE);
9704 /* if the operand is already in dptr
9705 then we do nothing else we move the value to dptr */
9706 if (AOP_TYPE (result) != AOP_STR)
9708 _startLazyDPSEvaluation ();
9709 /* if this is remateriazable */
9710 if (AOP_TYPE (result) == AOP_IMMD)
9712 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9713 if (AOP(result)->aopu.aop_immd.from_cast_remat)
9714 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
9716 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9719 { /* we need to get it byte by byte */
9720 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9721 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9722 if (options.model == MODEL_FLAT24) {
9723 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9724 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9726 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9729 _endLazyDPSEvaluation ();
9731 /* so dptr know contains the address */
9732 aopOp (right, ic, FALSE, TRUE);
9734 /* if bit then unpack */
9735 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9736 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9739 size = AOP_SIZE (right);
9742 _startLazyDPSEvaluation ();
9745 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9751 emitcode ("lcall", "__gptrput");
9752 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
9753 emitcode ("inc", "dptr");
9755 _endLazyDPSEvaluation ();
9758 if (pi && AOP_TYPE (result) != AOP_IMMD) {
9759 aopPut (AOP(result),"dpl",0);
9760 aopPut (AOP(result),"dph",1);
9761 if (options.model == MODEL_FLAT24) {
9762 aopPut (AOP(result),"dpx",2);
9763 aopPut (AOP(result),"b",3);
9765 aopPut (AOP(result),"b",2);
9768 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9769 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9771 size = AOP_SIZE (right) - 1;
9772 while (size--) emitcode ("lcall","__decdptr");
9774 freeAsmop (result, NULL, ic, TRUE);
9775 freeAsmop (right, NULL, ic, TRUE);
9778 /*-----------------------------------------------------------------*/
9779 /* genPointerSet - stores the value into a pointer location */
9780 /*-----------------------------------------------------------------*/
9782 genPointerSet (iCode * ic, iCode *pi)
9784 operand *right, *result;
9785 sym_link *type, *etype;
9788 D (emitcode (";", "genPointerSet ");
9791 right = IC_RIGHT (ic);
9792 result = IC_RESULT (ic);
9794 /* depending on the type of pointer we need to
9795 move it to the correct pointer register */
9796 type = operandType (result);
9797 etype = getSpec (type);
9798 /* if left is of type of pointer then it is simple */
9799 if (IS_PTR (type) && !IS_FUNC (type->next))
9801 p_type = DCL_TYPE (type);
9805 /* we have to go by the storage class */
9806 p_type = PTR_TYPE (SPEC_OCLS (etype));
9808 /* special case when cast remat */
9809 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9810 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9811 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9812 type = type = operandType (result);
9813 p_type = DCL_TYPE (type);
9816 /* now that we have the pointer type we assign
9817 the pointer values */
9823 genNearPointerSet (right, result, ic, pi);
9827 genPagedPointerSet (right, result, ic, pi);
9831 genFarPointerSet (right, result, ic, pi);
9835 genGenPointerSet (right, result, ic, pi);
9841 /*-----------------------------------------------------------------*/
9842 /* genIfx - generate code for Ifx statement */
9843 /*-----------------------------------------------------------------*/
9845 genIfx (iCode * ic, iCode * popIc)
9847 operand *cond = IC_COND (ic);
9850 D (emitcode (";", "genIfx "););
9852 aopOp (cond, ic, FALSE, FALSE);
9854 /* get the value into acc */
9855 if (AOP_TYPE (cond) != AOP_CRY)
9859 /* the result is now in the accumulator */
9860 freeAsmop (cond, NULL, ic, TRUE);
9862 /* if there was something to be popped then do it */
9866 /* if the condition is a bit variable */
9867 if (isbit && IS_ITEMP (cond) &&
9869 genIfxJump (ic, SPIL_LOC (cond)->rname);
9870 else if (isbit && !IS_ITEMP (cond))
9871 genIfxJump (ic, OP_SYMBOL (cond)->rname);
9873 genIfxJump (ic, "a");
9878 /*-----------------------------------------------------------------*/
9879 /* genAddrOf - generates code for address of */
9880 /*-----------------------------------------------------------------*/
9882 genAddrOf (iCode * ic)
9884 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9887 D (emitcode (";", "genAddrOf ");
9890 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9892 /* if the operand is on the stack then we
9893 need to get the stack offset of this
9897 /* if 10 bit stack */
9898 if (options.stack10bit) {
9899 /* if it has an offset then we need to compute it */
9901 emitcode ("mov", "a,_bpx");
9902 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9903 emitcode ("mov", "b,a");
9904 emitcode ("mov", "a,_bpx+1");
9905 emitcode ("addc","a,#0x%02x", (((short) sym->stack) >> 8) & 0xff);
9906 aopPut (AOP (IC_RESULT (ic)), "b", 0);
9907 aopPut (AOP (IC_RESULT (ic)), "a", 1);
9908 aopPut (AOP (IC_RESULT (ic)), "#0x40", 2);
9910 /* we can just move _bp */
9911 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
9912 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
9913 aopPut (AOP (IC_RESULT (ic)), "#0x40", 2);
9916 /* if it has an offset then we need to compute it */
9918 emitcode ("mov", "a,_bp");
9919 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9920 aopPut (AOP (IC_RESULT (ic)), "a", 0);
9922 /* we can just move _bp */
9923 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9925 /* fill the result with zero */
9926 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9929 if (options.stack10bit && size < (FPTRSIZE - 1)) {
9931 "*** warning: pointer to stack var truncated.\n");
9936 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9942 /* object not on stack then we need the name */
9943 size = AOP_SIZE (IC_RESULT (ic));
9948 char s[SDCC_NAME_MAX];
9950 sprintf (s, "#(%s >> %d)",
9954 sprintf (s, "#%s", sym->rname);
9955 aopPut (AOP (IC_RESULT (ic)), s, offset++);
9959 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9963 /*-----------------------------------------------------------------*/
9964 /* genArrayInit - generates code for address of */
9965 /*-----------------------------------------------------------------*/
9967 genArrayInit (iCode * ic)
9971 int elementSize = 0, eIndex;
9972 unsigned val, lastVal;
9974 operand *left=IC_LEFT(ic);
9976 D (emitcode (";", "genArrayInit "););
9978 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
9980 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
9982 // Load immediate value into DPTR.
9983 emitcode("mov", "dptr, %s",
9984 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
9986 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
9989 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9990 "Unexpected operand to genArrayInit.\n");
9993 // a regression because of SDCCcse.c:1.52
9994 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9995 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9996 if (options.model == MODEL_FLAT24)
9997 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
10001 type = operandType(IC_LEFT(ic));
10003 if (type && type->next)
10005 elementSize = getSize(type->next);
10009 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10010 "can't determine element size in genArrayInit.\n");
10014 iLoop = IC_ARRAYILIST(ic);
10019 bool firstpass = TRUE;
10021 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10022 iLoop->count, (int)iLoop->literalValue, elementSize);
10028 symbol *tlbl = NULL;
10030 count = ix > 256 ? 256 : ix;
10034 tlbl = newiTempLabel (NULL);
10035 if (firstpass || (count & 0xff))
10037 emitcode("mov", "b, #0x%x", count & 0xff);
10040 emitcode ("", "%05d$:", tlbl->key + 100);
10045 for (eIndex = 0; eIndex < elementSize; eIndex++)
10047 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10048 if (val != lastVal)
10050 emitcode("mov", "a, #0x%x", val);
10054 emitcode("movx", "@dptr, a");
10055 emitcode("inc", "dptr");
10060 emitcode("djnz", "b, %05d$", tlbl->key + 100);
10066 iLoop = iLoop->next;
10069 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10072 /*-----------------------------------------------------------------*/
10073 /* genFarFarAssign - assignment when both are in far space */
10074 /*-----------------------------------------------------------------*/
10076 genFarFarAssign (operand * result, operand * right, iCode * ic)
10078 int size = AOP_SIZE (right);
10080 symbol *rSym = NULL;
10084 /* quick & easy case. */
10085 D(emitcode(";","genFarFarAssign (1 byte case)"););
10086 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
10087 freeAsmop (right, NULL, ic, FALSE);
10088 /* now assign DPTR to result */
10090 aopOp(result, ic, FALSE, FALSE);
10092 aopPut(AOP(result), "a", 0);
10093 freeAsmop(result, NULL, ic, FALSE);
10097 /* See if we've got an underlying symbol to abuse. */
10098 if (IS_SYMOP(result) && OP_SYMBOL(result))
10100 if (IS_TRUE_SYMOP(result))
10102 rSym = OP_SYMBOL(result);
10104 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10106 rSym = OP_SYMBOL(result)->usl.spillLoc;
10110 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10112 /* We can use the '390 auto-toggle feature to good effect here. */
10114 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10115 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
10116 emitcode ("mov", "dptr,#%s", rSym->rname);
10117 /* DP2 = result, DP1 = right, DP1 is current. */
10120 emitcode("movx", "a,@dptr");
10121 emitcode("movx", "@dptr,a");
10124 emitcode("inc", "dptr");
10125 emitcode("inc", "dptr");
10128 emitcode("mov", "dps, #0");
10129 freeAsmop (right, NULL, ic, FALSE);
10131 some alternative code for processors without auto-toggle
10132 no time to test now, so later well put in...kpb
10133 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10134 emitcode("mov", "dps, #0x01"); /* Select DPTR2. */
10135 emitcode ("mov", "dptr,#%s", rSym->rname);
10136 /* DP2 = result, DP1 = right, DP1 is current. */
10140 emitcode("movx", "a,@dptr");
10142 emitcode("inc", "dptr");
10143 emitcode("inc", "dps");
10144 emitcode("movx", "@dptr,a");
10146 emitcode("inc", "dptr");
10147 emitcode("inc", "dps");
10149 emitcode("mov", "dps, #0");
10150 freeAsmop (right, NULL, ic, FALSE);
10155 D (emitcode (";", "genFarFarAssign"););
10156 aopOp (result, ic, TRUE, TRUE);
10158 _startLazyDPSEvaluation ();
10162 aopPut (AOP (result),
10163 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10166 _endLazyDPSEvaluation ();
10167 freeAsmop (result, NULL, ic, FALSE);
10168 freeAsmop (right, NULL, ic, FALSE);
10172 /*-----------------------------------------------------------------*/
10173 /* genAssign - generate code for assignment */
10174 /*-----------------------------------------------------------------*/
10176 genAssign (iCode * ic)
10178 operand *result, *right;
10180 unsigned long lit = 0L;
10182 D (emitcode (";", "genAssign ");
10185 result = IC_RESULT (ic);
10186 right = IC_RIGHT (ic);
10188 /* if they are the same */
10189 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10192 aopOp (right, ic, FALSE, FALSE);
10194 emitcode (";", "genAssign: resultIsFar = %s",
10195 isOperandInFarSpace (result) ?
10198 /* special case both in far space */
10199 if ((AOP_TYPE (right) == AOP_DPTR ||
10200 AOP_TYPE (right) == AOP_DPTR2) &&
10201 /* IS_TRUE_SYMOP(result) && */
10202 isOperandInFarSpace (result))
10204 genFarFarAssign (result, right, ic);
10208 aopOp (result, ic, TRUE, FALSE);
10210 /* if they are the same registers */
10211 if (sameRegs (AOP (right), AOP (result)))
10214 /* if the result is a bit */
10215 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10217 /* if the right size is a literal then
10218 we know what the value is */
10219 if (AOP_TYPE (right) == AOP_LIT)
10221 if (((int) operandLitValue (right)))
10222 aopPut (AOP (result), one, 0);
10224 aopPut (AOP (result), zero, 0);
10228 /* the right is also a bit variable */
10229 if (AOP_TYPE (right) == AOP_CRY)
10231 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10232 aopPut (AOP (result), "c", 0);
10236 /* we need to or */
10238 aopPut (AOP (result), "a", 0);
10242 /* bit variables done */
10244 size = AOP_SIZE (result);
10246 if (AOP_TYPE (right) == AOP_LIT)
10247 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10250 (AOP_TYPE (result) != AOP_REG) &&
10251 (AOP_TYPE (right) == AOP_LIT) &&
10252 !IS_FLOAT (operandType (right)))
10254 _startLazyDPSEvaluation ();
10255 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10257 aopPut (AOP (result),
10258 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10263 /* And now fill the rest with zeros. */
10266 emitcode ("clr", "a");
10270 aopPut (AOP (result), "a", offset++);
10272 _endLazyDPSEvaluation ();
10276 _startLazyDPSEvaluation ();
10279 aopPut (AOP (result),
10280 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10284 _endLazyDPSEvaluation ();
10288 freeAsmop (right, NULL, ic, FALSE);
10289 freeAsmop (result, NULL, ic, TRUE);
10292 /*-----------------------------------------------------------------*/
10293 /* genJumpTab - generates code for jump table */
10294 /*-----------------------------------------------------------------*/
10296 genJumpTab (iCode * ic)
10301 D (emitcode (";", "genJumpTab ");
10304 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10305 /* get the condition into accumulator */
10306 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10308 /* multiply by four! */
10309 emitcode ("add", "a,acc");
10310 emitcode ("add", "a,acc");
10311 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10313 jtab = newiTempLabel (NULL);
10314 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10315 emitcode ("jmp", "@a+dptr");
10316 emitcode ("", "%05d$:", jtab->key + 100);
10317 /* now generate the jump labels */
10318 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10319 jtab = setNextItem (IC_JTLABELS (ic)))
10320 emitcode ("ljmp", "%05d$", jtab->key + 100);
10324 /*-----------------------------------------------------------------*/
10325 /* genCast - gen code for casting */
10326 /*-----------------------------------------------------------------*/
10328 genCast (iCode * ic)
10330 operand *result = IC_RESULT (ic);
10331 sym_link *ctype = operandType (IC_LEFT (ic));
10332 sym_link *rtype = operandType (IC_RIGHT (ic));
10333 operand *right = IC_RIGHT (ic);
10336 D (emitcode (";", "genCast ");
10339 /* if they are equivalent then do nothing */
10340 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10343 aopOp (right, ic, FALSE, FALSE);
10344 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10346 /* if the result is a bit */
10347 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10348 if (IS_BITVAR(OP_SYMBOL(result)->type))
10350 /* if the right size is a literal then
10351 we know what the value is */
10352 if (AOP_TYPE (right) == AOP_LIT)
10354 if (((int) operandLitValue (right)))
10355 aopPut (AOP (result), one, 0);
10357 aopPut (AOP (result), zero, 0);
10362 /* the right is also a bit variable */
10363 if (AOP_TYPE (right) == AOP_CRY)
10365 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10366 aopPut (AOP (result), "c", 0);
10370 /* we need to or */
10372 aopPut (AOP (result), "a", 0);
10376 /* if they are the same size : or less */
10377 if (AOP_SIZE (result) <= AOP_SIZE (right))
10380 /* if they are in the same place */
10381 if (sameRegs (AOP (right), AOP (result)))
10384 /* if they in different places then copy */
10385 size = AOP_SIZE (result);
10387 _startLazyDPSEvaluation ();
10390 aopPut (AOP (result),
10391 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10395 _endLazyDPSEvaluation ();
10400 /* if the result is of type pointer */
10401 if (IS_PTR (ctype))
10405 sym_link *type = operandType (right);
10407 /* pointer to generic pointer */
10408 if (IS_GENPTR (ctype))
10414 p_type = DCL_TYPE (type);
10418 #if OLD_CAST_BEHAVIOR
10419 /* KV: we are converting a non-pointer type to
10420 * a generic pointer. This (ifdef'd out) code
10421 * says that the resulting generic pointer
10422 * should have the same class as the storage
10423 * location of the non-pointer variable.
10425 * For example, converting an int (which happens
10426 * to be stored in DATA space) to a pointer results
10427 * in a DATA generic pointer; if the original int
10428 * in XDATA space, so will be the resulting pointer.
10430 * I don't like that behavior, and thus this change:
10431 * all such conversions will be forced to XDATA and
10432 * throw a warning. If you want some non-XDATA
10433 * type, or you want to suppress the warning, you
10434 * must go through an intermediate cast, like so:
10436 * char _generic *gp = (char _xdata *)(intVar);
10438 sym_link *etype = getSpec (type);
10440 /* we have to go by the storage class */
10441 if (SPEC_OCLS (etype) != generic)
10443 p_type = PTR_TYPE (SPEC_OCLS (etype));
10448 /* Converting unknown class (i.e. register variable)
10449 * to generic pointer. This is not good, but
10450 * we'll make a guess (and throw a warning).
10453 werror (W_INT_TO_GEN_PTR_CAST);
10457 /* the first two bytes are known */
10458 size = GPTRSIZE - 1;
10460 _startLazyDPSEvaluation ();
10463 aopPut (AOP (result),
10464 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10468 _endLazyDPSEvaluation ();
10470 /* the last byte depending on type */
10488 /* this should never happen */
10489 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10490 "got unknown pointer type");
10493 aopPut (AOP (result), l, GPTRSIZE - 1);
10497 /* just copy the pointers */
10498 size = AOP_SIZE (result);
10500 _startLazyDPSEvaluation ();
10503 aopPut (AOP (result),
10504 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10508 _endLazyDPSEvaluation ();
10512 /* so we now know that the size of destination is greater
10513 than the size of the source */
10514 /* we move to result for the size of source */
10515 size = AOP_SIZE (right);
10517 _startLazyDPSEvaluation ();
10520 aopPut (AOP (result),
10521 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10525 _endLazyDPSEvaluation ();
10527 /* now depending on the sign of the source && destination */
10528 size = AOP_SIZE (result) - AOP_SIZE (right);
10529 /* if unsigned or not an integral type */
10530 /* also, if the source is a bit, we don't need to sign extend, because
10531 * it can't possibly have set the sign bit.
10533 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10537 aopPut (AOP (result), zero, offset++);
10542 /* we need to extend the sign :{ */
10543 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10544 FALSE, FALSE, TRUE);
10546 emitcode ("rlc", "a");
10547 emitcode ("subb", "a,acc");
10549 aopPut (AOP (result), "a", offset++);
10552 /* we are done hurray !!!! */
10555 freeAsmop (right, NULL, ic, TRUE);
10556 freeAsmop (result, NULL, ic, TRUE);
10560 /*-----------------------------------------------------------------*/
10561 /* genDjnz - generate decrement & jump if not zero instrucion */
10562 /*-----------------------------------------------------------------*/
10564 genDjnz (iCode * ic, iCode * ifx)
10566 symbol *lbl, *lbl1;
10570 /* if the if condition has a false label
10571 then we cannot save */
10572 if (IC_FALSE (ifx))
10575 /* if the minus is not of the form
10577 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10578 !IS_OP_LITERAL (IC_RIGHT (ic)))
10581 if (operandLitValue (IC_RIGHT (ic)) != 1)
10584 /* if the size of this greater than one then no
10586 if (getSize (operandType (IC_RESULT (ic))) > 1)
10589 /* otherwise we can save BIG */
10590 D(emitcode(";", "genDjnz"););
10592 lbl = newiTempLabel (NULL);
10593 lbl1 = newiTempLabel (NULL);
10595 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10597 if (AOP_NEEDSACC(IC_RESULT(ic)))
10599 /* If the result is accessed indirectly via
10600 * the accumulator, we must explicitly write
10601 * it back after the decrement.
10603 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10605 if (strcmp(rByte, "a"))
10607 /* Something is hopelessly wrong */
10608 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10609 __FILE__, __LINE__);
10610 /* We can just give up; the generated code will be inefficient,
10611 * but what the hey.
10613 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10616 emitcode ("dec", "%s", rByte);
10617 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10618 emitcode ("jnz", "%05d$", lbl->key + 100);
10620 else if (IS_AOP_PREG (IC_RESULT (ic)))
10622 emitcode ("dec", "%s",
10623 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10624 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10625 emitcode ("jnz", "%05d$", lbl->key + 100);
10629 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10632 emitcode ("sjmp", "%05d$", lbl1->key + 100);
10633 emitcode ("", "%05d$:", lbl->key + 100);
10634 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10635 emitcode ("", "%05d$:", lbl1->key + 100);
10637 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10638 ifx->generated = 1;
10642 /*-----------------------------------------------------------------*/
10643 /* genReceive - generate code for a receive iCode */
10644 /*-----------------------------------------------------------------*/
10646 genReceive (iCode * ic)
10649 D (emitcode (";", "genReceive ");
10652 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10653 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10654 IS_TRUE_SYMOP (IC_RESULT (ic))))
10656 int size = getSize (operandType (IC_RESULT (ic)));
10657 int offset = fReturnSizeDS390 - size;
10660 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10661 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10664 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10665 size = AOP_SIZE (IC_RESULT (ic));
10669 emitcode ("pop", "acc");
10670 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10677 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10679 assignResultValue (IC_RESULT (ic));
10682 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10685 /*-----------------------------------------------------------------*/
10686 /* gen390Code - generate code for Dallas 390 based controllers */
10687 /*-----------------------------------------------------------------*/
10689 gen390Code (iCode * lic)
10694 lineHead = lineCurr = NULL;
10696 if (options.model == MODEL_FLAT24) {
10697 fReturnSizeDS390 = 5;
10698 fReturn = fReturn24;
10700 fReturnSizeDS390 = 4;
10701 fReturn = fReturn16;
10702 options.stack10bit=0;
10706 /* print the allocation information */
10708 printAllocInfo (currFunc, codeOutFile);
10710 /* if debug information required */
10711 if (options.debug && currFunc)
10713 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
10715 if (IS_STATIC (currFunc->etype))
10716 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
10718 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
10721 /* stack pointer name */
10722 if (options.useXstack)
10728 for (ic = lic; ic; ic = ic->next)
10731 if (cln != ic->lineno)
10736 emitcode ("", "C$%s$%d$%d$%d ==.",
10737 FileBaseName (ic->filename), ic->lineno,
10738 ic->level, ic->block);
10741 emitcode (";", "%s %d", ic->filename, ic->lineno);
10744 /* if the result is marked as
10745 spilt and rematerializable or code for
10746 this has already been generated then
10748 if (resultRemat (ic) || ic->generated)
10751 /* depending on the operation */
10771 /* IPOP happens only when trying to restore a
10772 spilt live range, if there is an ifx statement
10773 following this pop then the if statement might
10774 be using some of the registers being popped which
10775 would destory the contents of the register so
10776 we need to check for this condition and handle it */
10778 ic->next->op == IFX &&
10779 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10780 genIfx (ic->next, ic);
10798 genEndFunction (ic);
10818 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10835 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10839 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10846 /* note these two are xlated by algebraic equivalence
10847 during parsing SDCC.y */
10848 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10849 "got '>=' or '<=' shouldn't have come here");
10853 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10865 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10869 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10873 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10897 genRightShift (ic);
10900 case GET_VALUE_AT_ADDRESS:
10901 genPointerGet (ic,hasInc(IC_LEFT(ic),ic));
10905 if (POINTER_SET (ic))
10906 genPointerSet (ic,hasInc(IC_RESULT(ic),ic));
10932 addSet (&_G.sendSet, ic);
10945 /* now we are ready to call the
10946 peep hole optimizer */
10947 if (!options.nopeep)
10948 peepHole (&lineHead);
10950 /* now do the actual printing */
10951 printLine (lineHead, codeOutFile);