1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for DS80C390
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 DS390 adaptation by Kevin Vigor <kevin@vigor.nu>
9 This program is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 In other words, you are welcome to use, share and improve this program.
24 You are forbidden to forbid anyone else to use, share and improve
25 what you give them. Help stamp out software-hoarding!
26 -------------------------------------------------------------------------*/
36 #include "SDCCglobl.h"
39 #ifdef HAVE_SYS_ISA_DEFS_H
40 #include <sys/isa_defs.h>
42 #ifdef HAVE_MACHINE_ENDIAN_H
43 #include <machine/endian.h>
48 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
49 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
50 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
56 #define BETTER_LITERAL_SHIFT
58 char *aopLiteral (value * val, int offset);
60 /* this is the down and dirty file with all kinds of
61 kludgy & hacky stuff. This is what it is all about
62 CODE GENERATION for a specific MCU . some of the
63 routines may be reusable, will have to see */
65 static char *zero = "#0x00";
66 static char *one = "#0x01";
71 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
72 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
74 unsigned fReturnSizeDS390 = 5; /* shared with ralloc.c */
75 static char *fReturn24[] =
76 {"dpl", "dph", "dpx", "b", "a"};
77 static char *fReturn16[] =
78 {"dpl", "dph", "b", "a"};
79 static char **fReturn = fReturn24;
80 static char *accUse[] =
83 static short rbank = -1;
97 static void saveRBank (int, iCode *, bool);
99 #define RESULTONSTACK(x) \
100 (IC_RESULT(x) && IC_RESULT(x)->aop && \
101 IC_RESULT(x)->aop->type == AOP_STK )
103 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
104 #define MOVA(x) { char *_mova_tmp = strdup(x); \
105 if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
107 emitcode("mov","a,%s",_mova_tmp); \
111 #define CLRC emitcode("clr","c")
112 #define SETC emitcode("setb","c")
114 // A scratch register which will be used to hold
115 // result bytes from operands in far space via DPTR2.
116 #define DP2_RESULT_REG "ap"
118 static lineNode *lineHead = NULL;
119 static lineNode *lineCurr = NULL;
121 static unsigned char SLMask[] =
122 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
123 0xE0, 0xC0, 0x80, 0x00};
124 static unsigned char SRMask[] =
125 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
126 0x07, 0x03, 0x01, 0x00};
133 /*-----------------------------------------------------------------*/
134 /* emitcode - writes the code into a file : for now it is simple */
135 /*-----------------------------------------------------------------*/
137 emitcode (char *inst, char *fmt,...)
140 char lb[INITIAL_INLINEASM];
148 sprintf (lb, "%s\t", inst);
150 sprintf (lb, "%s", inst);
151 vsprintf (lb + (strlen (lb)), fmt, ap);
154 vsprintf (lb, fmt, ap);
156 while (isspace (*lbp))
160 lineCurr = (lineCurr ?
161 connectLine (lineCurr, newLineNode (lb)) :
162 (lineHead = newLineNode (lb)));
163 lineCurr->isInline = _G.inLine;
164 lineCurr->isDebug = _G.debugLine;
168 /*-----------------------------------------------------------------*/
169 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
170 /*-----------------------------------------------------------------*/
172 getFreePtr (iCode * ic, asmop ** aopp, bool result)
174 bool r0iu = FALSE, r1iu = FALSE;
175 bool r0ou = FALSE, r1ou = FALSE;
177 /* the logic: if r0 & r1 used in the instruction
178 then we are in trouble otherwise */
180 /* first check if r0 & r1 are used by this
181 instruction, in which case we are in trouble */
182 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
183 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
188 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
189 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
191 /* if no usage of r0 then return it */
194 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
195 (*aopp)->type = AOP_R0;
197 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
200 /* if no usage of r1 then return it */
203 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
204 (*aopp)->type = AOP_R1;
206 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
209 /* now we know they both have usage */
210 /* if r0 not used in this instruction */
213 /* push it if not already pushed */
216 emitcode ("push", "%s",
217 ds390_regWithIdx (R0_IDX)->dname);
221 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
222 (*aopp)->type = AOP_R0;
224 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
227 /* if r1 not used then */
231 /* push it if not already pushed */
234 emitcode ("push", "%s",
235 ds390_regWithIdx (R1_IDX)->dname);
239 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
240 (*aopp)->type = AOP_R1;
241 return ds390_regWithIdx (R1_IDX);
245 /* I said end of world but not quite end of world yet */
246 /* if this is a result then we can push it on the stack */
249 (*aopp)->type = AOP_STK;
253 /* other wise this is true end of the world */
254 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
255 "getFreePtr should never reach here");
259 /*-----------------------------------------------------------------*/
260 /* newAsmop - creates a new asmOp */
261 /*-----------------------------------------------------------------*/
263 newAsmop (short type)
267 aop = Safe_calloc (1, sizeof (asmop));
272 static int _currentDPS; /* Current processor DPS. */
273 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
274 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
276 /*-----------------------------------------------------------------*/
277 /* genSetDPTR: generate code to select which DPTR is in use (zero */
278 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
279 /* alternate DPTR (DPL1/DPH1/DPX1). */
280 /*-----------------------------------------------------------------*/
285 /* If we are doing lazy evaluation, simply note the desired
286 * change, but don't emit any code yet.
296 emitcode ("mov", "dps, #0x00");
301 emitcode ("mov", "dps, #0x01");
305 /*-----------------------------------------------------------------*/
306 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
308 /* Any code that operates on DPTR (NB: not on the individual */
309 /* components, like DPH) *must* call _flushLazyDPS() before using */
310 /* DPTR within a lazy DPS evaluation block. */
312 /* Note that aopPut and aopGet already contain the proper calls to */
313 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
314 /* DPS evaluation block. */
316 /* Also, _flushLazyDPS must be called before any flow control */
317 /* operations that could potentially branch out of the block. */
319 /* Lazy DPS evaluation is simply an optimization (though an */
320 /* important one), so if in doubt, leave it out. */
321 /*-----------------------------------------------------------------*/
323 _startLazyDPSEvaluation (void)
327 #ifdef BETTER_LITERAL_SHIFT
334 /*-----------------------------------------------------------------*/
335 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
336 /* desired one. Call before using DPTR within a lazy DPS evaluation */
338 /*-----------------------------------------------------------------*/
348 if (_desiredDPS != _currentDPS)
352 emitcode ("inc", "dps");
356 emitcode ("dec", "dps");
358 _currentDPS = _desiredDPS;
362 /*-----------------------------------------------------------------*/
363 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
365 /* Forces us back to the safe state (standard DPTR selected). */
366 /*-----------------------------------------------------------------*/
368 _endLazyDPSEvaluation (void)
370 #ifdef BETTER_LITERAL_SHIFT
389 /*-----------------------------------------------------------------*/
390 /* pointerCode - returns the code for a pointer type */
391 /*-----------------------------------------------------------------*/
393 pointerCode (sym_link * etype)
396 return PTR_TYPE (SPEC_OCLS (etype));
400 /*-----------------------------------------------------------------*/
401 /* aopForSym - for a true symbol */
402 /*-----------------------------------------------------------------*/
404 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
407 memmap *space = SPEC_OCLS (sym->etype);
409 /* if already has one */
413 /* assign depending on the storage class */
414 /* if it is on the stack or indirectly addressable */
415 /* space we need to assign either r0 or r1 to it */
416 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
418 sym->aop = aop = newAsmop (0);
419 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
420 aop->size = getSize (sym->type);
422 /* now assign the address of the variable to
423 the pointer register */
424 if (aop->type != AOP_STK)
430 emitcode ("push", "acc");
432 emitcode ("mov", "a,_bp");
433 emitcode ("add", "a,#0x%02x",
435 ((char) (sym->stack - _G.nRegsSaved)) :
436 ((char) sym->stack)) & 0xff);
437 emitcode ("mov", "%s,a",
438 aop->aopu.aop_ptr->name);
441 emitcode ("pop", "acc");
444 emitcode ("mov", "%s,#%s",
445 aop->aopu.aop_ptr->name,
447 aop->paged = space->paged;
450 aop->aopu.aop_stk = sym->stack;
454 if (sym->onStack && options.stack10bit)
456 /* It's on the 10 bit stack, which is located in
461 emitcode ("push", "acc");
463 emitcode ("mov", "a,_bpx");
464 emitcode ("clr","c");
465 emitcode ("subb", "a,#0x%02x",
467 ((short) (sym->stack - _G.nRegsSaved)) :
468 ((short) sym->stack)) & 0xff);
469 emitcode ("mov","b,a");
470 emitcode ("mov","a,#0x%02x",(-((sym->stack < 0) ?
471 ((short) (sym->stack - _G.nRegsSaved)) :
472 ((short) sym->stack)) >> 8) & 0xff);
473 emitcode ("subb","a,_bpx+1");
475 if (options.model == MODEL_FLAT24)
476 emitcode ("mov", "dpx1,#0x40");
478 emitcode ("mov", "dph1,a");
479 emitcode ("mov", "dpl1,b");
481 if (options.model == MODEL_FLAT24)
482 emitcode ("mov", "dpx,#0x40");
483 emitcode ("mov", "dph,a");
484 emitcode ("mov", "dpl,b");
488 emitcode ("pop", "acc");
490 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
491 aop->size = getSize (sym->type);
495 /* if in bit space */
496 if (IN_BITSPACE (space))
498 sym->aop = aop = newAsmop (AOP_CRY);
499 aop->aopu.aop_dir = sym->rname;
500 aop->size = getSize (sym->type);
503 /* if it is in direct space */
504 if (IN_DIRSPACE (space))
506 sym->aop = aop = newAsmop (AOP_DIR);
507 aop->aopu.aop_dir = sym->rname;
508 aop->size = getSize (sym->type);
512 /* special case for a function */
513 if (IS_FUNC (sym->type))
515 sym->aop = aop = newAsmop (AOP_IMMD);
516 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
517 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
518 aop->size = FPTRSIZE;
522 /* only remaining is far space */
523 /* in which case DPTR gets the address */
524 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
529 emitcode ("mov", "dptr,#%s", sym->rname);
534 emitcode ("mov", "dptr,#%s", sym->rname);
536 aop->size = getSize (sym->type);
538 /* if it is in code space */
539 if (IN_CODESPACE (space))
545 /*-----------------------------------------------------------------*/
546 /* aopForRemat - rematerialzes an object */
547 /*-----------------------------------------------------------------*/
549 aopForRemat (symbol * sym)
551 iCode *ic = sym->rematiCode;
552 asmop *aop = newAsmop (AOP_IMMD);
559 val += (int) operandLitValue (IC_RIGHT (ic));
560 else if (ic->op == '-')
561 val -= (int) operandLitValue (IC_RIGHT (ic));
562 else if (IS_CAST_ICODE(ic)) {
563 sym_link *from_type = operandType(IC_RIGHT(ic));
564 aop->aopu.aop_immd.from_cast_remat = 1;
565 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
566 ptr_type = DCL_TYPE(from_type);
567 if (ptr_type == IPOINTER) {
574 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
578 sprintf (buffer, "(%s %c 0x%04x)",
579 OP_SYMBOL (IC_LEFT (ic))->rname,
580 val >= 0 ? '+' : '-',
583 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
585 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
586 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
587 /* set immd2 field if required */
588 if (aop->aopu.aop_immd.from_cast_remat) {
589 sprintf(buffer,"#0x%02x",ptr_type);
590 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
591 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
597 /*-----------------------------------------------------------------*/
598 /* regsInCommon - two operands have some registers in common */
599 /*-----------------------------------------------------------------*/
601 regsInCommon (operand * op1, operand * op2)
606 /* if they have registers in common */
607 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
610 sym1 = OP_SYMBOL (op1);
611 sym2 = OP_SYMBOL (op2);
613 if (sym1->nRegs == 0 || sym2->nRegs == 0)
616 for (i = 0; i < sym1->nRegs; i++)
622 for (j = 0; j < sym2->nRegs; j++)
627 if (sym2->regs[j] == sym1->regs[i])
635 /*-----------------------------------------------------------------*/
636 /* operandsEqu - equivalent */
637 /*-----------------------------------------------------------------*/
639 operandsEqu (operand * op1, operand * op2)
643 /* if they not symbols */
644 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
647 sym1 = OP_SYMBOL (op1);
648 sym2 = OP_SYMBOL (op2);
650 /* if both are itemps & one is spilt
651 and the other is not then false */
652 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
653 sym1->isspilt != sym2->isspilt)
656 /* if they are the same */
660 if (strcmp (sym1->rname, sym2->rname) == 0)
664 /* if left is a tmp & right is not */
665 if (IS_ITEMP (op1) &&
668 (sym1->usl.spillLoc == sym2))
671 if (IS_ITEMP (op2) &&
675 (sym2->usl.spillLoc == sym1))
681 /*-----------------------------------------------------------------*/
682 /* sameRegs - two asmops have the same registers */
683 /*-----------------------------------------------------------------*/
685 sameRegs (asmop * aop1, asmop * aop2)
691 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
698 if (aop1->type != AOP_REG ||
699 aop2->type != AOP_REG)
702 if (aop1->size != aop2->size)
705 for (i = 0; i < aop1->size; i++)
706 if (aop1->aopu.aop_reg[i] !=
707 aop2->aopu.aop_reg[i])
713 /*-----------------------------------------------------------------*/
714 /* aopOp - allocates an asmop for an operand : */
715 /*-----------------------------------------------------------------*/
717 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
726 /* if this a literal */
727 if (IS_OP_LITERAL (op))
729 op->aop = aop = newAsmop (AOP_LIT);
730 aop->aopu.aop_lit = op->operand.valOperand;
731 aop->size = getSize (operandType (op));
735 /* if already has a asmop then continue */
739 /* if the underlying symbol has a aop */
740 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
742 op->aop = OP_SYMBOL (op)->aop;
746 /* if this is a true symbol */
747 if (IS_TRUE_SYMOP (op))
749 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
753 /* this is a temporary : this has
759 e) can be a return use only */
761 sym = OP_SYMBOL (op);
764 /* if the type is a conditional */
765 if (sym->regType == REG_CND)
767 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
772 /* if it is spilt then two situations
774 b) has a spill location */
775 if (sym->isspilt || sym->nRegs == 0)
778 /* rematerialize it NOW */
781 sym->aop = op->aop = aop =
783 aop->size = getSize (sym->type);
790 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
791 aop->size = getSize (sym->type);
792 for (i = 0; i < 2; i++)
793 aop->aopu.aop_str[i] = accUse[i];
803 /* a AOP_STR uses DPTR, but DPTR is already in use;
806 fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use! for operand %s\n",sym->name);
809 aop = op->aop = sym->aop = newAsmop (AOP_STR);
810 aop->size = getSize (sym->type);
811 for (i = 0; i < (int) fReturnSizeDS390; i++)
812 aop->aopu.aop_str[i] = fReturn[i];
816 /* else spill location */
817 sym->aop = op->aop = aop =
818 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
819 aop->size = getSize (sym->type);
823 /* must be in a register */
824 sym->aop = op->aop = aop = newAsmop (AOP_REG);
825 aop->size = sym->nRegs;
826 for (i = 0; i < sym->nRegs; i++)
827 aop->aopu.aop_reg[i] = sym->regs[i];
830 /*-----------------------------------------------------------------*/
831 /* freeAsmop - free up the asmop given to an operand */
832 /*----------------------------------------------------------------*/
834 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
851 /* depending on the asmop type only three cases need work AOP_RO
852 , AOP_R1 && AOP_STK */
860 emitcode ("pop", "ar0");
864 bitVectUnSetBit (ic->rUsed, R0_IDX);
872 emitcode ("pop", "ar1");
876 bitVectUnSetBit (ic->rUsed, R1_IDX);
882 int stk = aop->aopu.aop_stk + aop->size;
883 bitVectUnSetBit (ic->rUsed, R0_IDX);
884 bitVectUnSetBit (ic->rUsed, R1_IDX);
886 getFreePtr (ic, &aop, FALSE);
888 if (options.stack10bit)
890 /* I'm not sure what to do here yet... */
893 "*** Warning: probably generating bad code for "
894 "10 bit stack mode.\n");
899 emitcode ("mov", "a,_bp");
900 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
901 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
905 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
910 emitcode ("pop", "acc");
911 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
914 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
917 freeAsmop (op, NULL, ic, TRUE);
920 emitcode ("pop", "ar0");
926 emitcode ("pop", "ar1");
933 /* all other cases just dealloc */
939 OP_SYMBOL (op)->aop = NULL;
940 /* if the symbol has a spill */
942 SPIL_LOC (op)->aop = NULL;
947 /*------------------------------------------------------------------*/
948 /* aopGet - for fetching value of the aop */
950 /* Set canClobberACC if you are sure it is OK to clobber the value */
951 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
952 /* just less efficient. */
953 /*------------------------------------------------------------------*/
965 /* offset is greater than
967 if (offset > (aop->size - 1) &&
968 aop->type != AOP_LIT)
971 /* depending on type */
977 /* if we need to increment it */
978 while (offset > aop->coff)
980 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
984 while (offset < aop->coff)
986 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
993 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
994 return (dname ? "acc" : "a");
996 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
997 rs = Safe_calloc (1, strlen (s) + 1);
1004 if (aop->type == AOP_DPTR2)
1010 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1016 while (offset > aop->coff)
1018 emitcode ("inc", "dptr");
1022 while (offset < aop->coff)
1024 emitcode ("lcall", "__decdptr");
1031 emitcode ("clr", "a");
1032 emitcode ("movc", "a,@a+dptr");
1036 emitcode ("movx", "a,@dptr");
1039 if (aop->type == AOP_DPTR2)
1045 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1046 return DP2_RESULT_REG;
1049 return (dname ? "acc" : "a");
1052 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1053 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1055 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1057 sprintf (s, "#(%s >> %d)",
1058 aop->aopu.aop_immd.aop_immd1,
1062 aop->aopu.aop_immd.aop_immd1);
1063 rs = Safe_calloc (1, strlen (s) + 1);
1069 sprintf (s, "(%s + %d)",
1073 sprintf (s, "%s", aop->aopu.aop_dir);
1074 rs = Safe_calloc (1, strlen (s) + 1);
1080 return aop->aopu.aop_reg[offset]->dname;
1082 return aop->aopu.aop_reg[offset]->name;
1085 emitcode ("clr", "a");
1086 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1087 emitcode ("rlc", "a");
1088 return (dname ? "acc" : "a");
1091 if (!offset && dname)
1093 return aop->aopu.aop_str[offset];
1096 return aopLiteral (aop->aopu.aop_lit, offset);
1100 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1104 return aop->aopu.aop_str[offset];
1108 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1109 "aopget got unsupported aop->type");
1112 /*-----------------------------------------------------------------*/
1113 /* aopPut - puts a string for a aop */
1114 /*-----------------------------------------------------------------*/
1116 aopPut (asmop * aop, char *s, int offset)
1120 if (aop->size && offset > (aop->size - 1))
1122 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1123 "aopPut got offset > aop->size");
1127 /* will assign value to value */
1128 /* depending on where it is ofcourse */
1133 sprintf (d, "(%s + %d)",
1134 aop->aopu.aop_dir, offset);
1136 sprintf (d, "%s", aop->aopu.aop_dir);
1139 emitcode ("mov", "%s,%s", d, s);
1144 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1145 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1148 strcmp (s, "r0") == 0 ||
1149 strcmp (s, "r1") == 0 ||
1150 strcmp (s, "r2") == 0 ||
1151 strcmp (s, "r3") == 0 ||
1152 strcmp (s, "r4") == 0 ||
1153 strcmp (s, "r5") == 0 ||
1154 strcmp (s, "r6") == 0 ||
1155 strcmp (s, "r7") == 0)
1156 emitcode ("mov", "%s,%s",
1157 aop->aopu.aop_reg[offset]->dname, s);
1159 emitcode ("mov", "%s,%s",
1160 aop->aopu.aop_reg[offset]->name, s);
1167 if (aop->type == AOP_DPTR2)
1175 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1176 "aopPut writting to code space");
1180 while (offset > aop->coff)
1183 emitcode ("inc", "dptr");
1186 while (offset < aop->coff)
1189 emitcode ("lcall", "__decdptr");
1194 /* if not in accumulater */
1197 emitcode ("movx", "@dptr,a");
1199 if (aop->type == AOP_DPTR2)
1207 while (offset > aop->coff)
1210 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1212 while (offset < aop->coff)
1215 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1222 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1228 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1230 else if (strcmp (s, "r0") == 0 ||
1231 strcmp (s, "r1") == 0 ||
1232 strcmp (s, "r2") == 0 ||
1233 strcmp (s, "r3") == 0 ||
1234 strcmp (s, "r4") == 0 ||
1235 strcmp (s, "r5") == 0 ||
1236 strcmp (s, "r6") == 0 ||
1237 strcmp (s, "r7") == 0)
1240 sprintf (buffer, "a%s", s);
1241 emitcode ("mov", "@%s,%s",
1242 aop->aopu.aop_ptr->name, buffer);
1245 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1250 if (strcmp (s, "a") == 0)
1251 emitcode ("push", "acc");
1255 emitcode ("push", "acc");
1257 emitcode ("push", s);
1263 /* if bit variable */
1264 if (!aop->aopu.aop_dir)
1266 emitcode ("clr", "a");
1267 emitcode ("rlc", "a");
1272 emitcode ("clr", "%s", aop->aopu.aop_dir);
1274 emitcode ("setb", "%s", aop->aopu.aop_dir);
1275 else if (!strcmp (s, "c"))
1276 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1279 if (strcmp (s, "a"))
1284 symbol *lbl = newiTempLabel (NULL);
1285 emitcode ("clr", "c");
1286 emitcode ("jz", "%05d$", lbl->key + 100);
1287 emitcode ("cpl", "c");
1288 emitcode ("", "%05d$:", lbl->key + 100);
1289 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1297 if (strcmp (aop->aopu.aop_str[offset], s))
1298 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1303 if (!offset && (strcmp (s, "acc") == 0))
1306 if (strcmp (aop->aopu.aop_str[offset], s))
1307 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1311 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1312 "aopPut got unsupported aop->type");
1319 /*--------------------------------------------------------------------*/
1320 /* reAdjustPreg - points a register back to where it should (coff==0) */
1321 /*--------------------------------------------------------------------*/
1323 reAdjustPreg (asmop * aop)
1325 if ((aop->coff==0) || (aop->size <= 1)) {
1334 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1338 if (aop->type == AOP_DPTR2)
1345 emitcode ("lcall", "__decdptr");
1348 if (aop->type == AOP_DPTR2)
1358 #define AOP(op) op->aop
1359 #define AOP_TYPE(op) AOP(op)->type
1360 #define AOP_SIZE(op) AOP(op)->size
1361 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1362 AOP_TYPE(x) == AOP_R0))
1364 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1365 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1368 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1369 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1370 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1372 /* Workaround for DS80C390 bug: div ab may return bogus results
1373 * if A is accessed in instruction immediately before the div.
1375 * Will be fixed in B4 rev of processor, Dallas claims.
1378 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1379 if (!AOP_NEEDSACC(RIGHT)) \
1381 /* We can load A first, then B, since \
1382 * B (the RIGHT operand) won't clobber A, \
1383 * thus avoiding touching A right before the div. \
1385 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1386 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1388 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1392 /* Just stuff in a nop after loading A. */ \
1393 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1394 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1396 emitcode("nop", "; workaround for DS80C390 div bug."); \
1399 /*-----------------------------------------------------------------*/
1400 /* genNotFloat - generates not for float operations */
1401 /*-----------------------------------------------------------------*/
1403 genNotFloat (operand * op, operand * res)
1409 D (emitcode (";", "genNotFloat ");
1412 /* we will put 127 in the first byte of
1414 aopPut (AOP (res), "#127", 0);
1415 size = AOP_SIZE (op) - 1;
1418 _startLazyDPSEvaluation ();
1419 l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1424 emitcode ("orl", "a,%s",
1426 offset++, FALSE, FALSE, FALSE));
1428 _endLazyDPSEvaluation ();
1430 tlbl = newiTempLabel (NULL);
1431 aopPut (res->aop, one, 1);
1432 emitcode ("jz", "%05d$", (tlbl->key + 100));
1433 aopPut (res->aop, zero, 1);
1434 emitcode ("", "%05d$:", (tlbl->key + 100));
1436 size = res->aop->size - 2;
1438 /* put zeros in the rest */
1440 aopPut (res->aop, zero, offset++);
1443 /*-----------------------------------------------------------------*/
1444 /* opIsGptr: returns non-zero if the passed operand is */
1445 /* a generic pointer type. */
1446 /*-----------------------------------------------------------------*/
1448 opIsGptr (operand * op)
1450 sym_link *type = operandType (op);
1452 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1459 /*-----------------------------------------------------------------*/
1460 /* getDataSize - get the operand data size */
1461 /*-----------------------------------------------------------------*/
1463 getDataSize (operand * op)
1466 size = AOP_SIZE (op);
1467 if (size == GPTRSIZE)
1469 sym_link *type = operandType (op);
1470 if (IS_GENPTR (type))
1472 /* generic pointer; arithmetic operations
1473 * should ignore the high byte (pointer type).
1481 /*-----------------------------------------------------------------*/
1482 /* outAcc - output Acc */
1483 /*-----------------------------------------------------------------*/
1485 outAcc (operand * result)
1488 size = getDataSize (result);
1491 aopPut (AOP (result), "a", 0);
1494 /* unsigned or positive */
1497 aopPut (AOP (result), zero, offset++);
1502 /*-----------------------------------------------------------------*/
1503 /* outBitC - output a bit C */
1504 /*-----------------------------------------------------------------*/
1506 outBitC (operand * result)
1508 /* if the result is bit */
1509 if (AOP_TYPE (result) == AOP_CRY)
1511 aopPut (AOP (result), "c", 0);
1515 emitcode ("clr", "a");
1516 emitcode ("rlc", "a");
1521 /*-----------------------------------------------------------------*/
1522 /* toBoolean - emit code for orl a,operator(sizeop) */
1523 /*-----------------------------------------------------------------*/
1525 toBoolean (operand * oper)
1527 int size = AOP_SIZE (oper) - 1;
1531 /* The generic part of a generic pointer should
1532 * not participate in it's truth value.
1534 * i.e. 0x10000000 is zero.
1536 if (opIsGptr (oper))
1538 D (emitcode (";", "toBoolean: generic ptr special case.");
1543 _startLazyDPSEvaluation ();
1544 if (AOP_NEEDSACC (oper) && size)
1547 emitcode ("push", "b");
1548 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1552 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1558 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1562 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1565 _endLazyDPSEvaluation ();
1569 emitcode ("mov", "a,b");
1570 emitcode ("pop", "b");
1575 /*-----------------------------------------------------------------*/
1576 /* genNot - generate code for ! operation */
1577 /*-----------------------------------------------------------------*/
1582 sym_link *optype = operandType (IC_LEFT (ic));
1584 D (emitcode (";", "genNot ");
1587 /* assign asmOps to operand & result */
1588 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1589 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1591 /* if in bit space then a special case */
1592 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1594 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1595 emitcode ("cpl", "c");
1596 outBitC (IC_RESULT (ic));
1600 /* if type float then do float */
1601 if (IS_FLOAT (optype))
1603 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1607 toBoolean (IC_LEFT (ic));
1609 tlbl = newiTempLabel (NULL);
1610 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1611 emitcode ("", "%05d$:", tlbl->key + 100);
1612 outBitC (IC_RESULT (ic));
1615 /* release the aops */
1616 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1617 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1621 /*-----------------------------------------------------------------*/
1622 /* genCpl - generate code for complement */
1623 /*-----------------------------------------------------------------*/
1630 D (emitcode (";", "genCpl ");
1634 /* assign asmOps to operand & result */
1635 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1636 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1638 /* if both are in bit space then
1640 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1641 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1644 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1645 emitcode ("cpl", "c");
1646 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1650 size = AOP_SIZE (IC_RESULT (ic));
1651 _startLazyDPSEvaluation ();
1654 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1656 emitcode ("cpl", "a");
1657 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1659 _endLazyDPSEvaluation ();
1663 /* release the aops */
1664 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1665 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1668 /*-----------------------------------------------------------------*/
1669 /* genUminusFloat - unary minus for floating points */
1670 /*-----------------------------------------------------------------*/
1672 genUminusFloat (operand * op, operand * result)
1674 int size, offset = 0;
1676 /* for this we just need to flip the
1677 first it then copy the rest in place */
1678 D (emitcode (";", "genUminusFloat");
1681 _startLazyDPSEvaluation ();
1682 size = AOP_SIZE (op) - 1;
1683 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1686 emitcode ("cpl", "acc.7");
1687 aopPut (AOP (result), "a", 3);
1691 aopPut (AOP (result),
1692 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1696 _endLazyDPSEvaluation ();
1699 /*-----------------------------------------------------------------*/
1700 /* genUminus - unary minus code generation */
1701 /*-----------------------------------------------------------------*/
1703 genUminus (iCode * ic)
1706 sym_link *optype, *rtype;
1708 D (emitcode (";", "genUminus ");
1713 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1714 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1716 /* if both in bit space then special
1718 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1719 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1722 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1723 emitcode ("cpl", "c");
1724 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1728 optype = operandType (IC_LEFT (ic));
1729 rtype = operandType (IC_RESULT (ic));
1731 /* if float then do float stuff */
1732 if (IS_FLOAT (optype))
1734 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1738 /* otherwise subtract from zero */
1739 size = AOP_SIZE (IC_LEFT (ic));
1741 _startLazyDPSEvaluation ();
1744 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1745 if (!strcmp (l, "a"))
1749 emitcode ("cpl", "a");
1750 emitcode ("addc", "a,#0");
1756 emitcode ("clr", "a");
1757 emitcode ("subb", "a,%s", l);
1759 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1761 _endLazyDPSEvaluation ();
1763 /* if any remaining bytes in the result */
1764 /* we just need to propagate the sign */
1765 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1767 emitcode ("rlc", "a");
1768 emitcode ("subb", "a,acc");
1770 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1774 /* release the aops */
1775 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1776 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1779 /*-----------------------------------------------------------------*/
1780 /* saveRegisters - will look for a call and save the registers */
1781 /*-----------------------------------------------------------------*/
1783 saveRegisters (iCode * lic)
1791 for (ic = lic; ic; ic = ic->next)
1792 if (ic->op == CALL || ic->op == PCALL)
1797 fprintf (stderr, "found parameter push with no function call\n");
1801 /* if the registers have been saved already then
1803 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type) ||
1804 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))))
1807 /* find the registers in use at this time
1808 and push them away to safety */
1809 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1813 if (options.useXstack)
1815 if (bitVectBitValue (rsave, R0_IDX))
1816 emitcode ("mov", "b,r0");
1817 emitcode ("mov", "r0,%s", spname);
1818 for (i = 0; i < ds390_nRegs; i++)
1820 if (bitVectBitValue (rsave, i))
1823 emitcode ("mov", "a,b");
1825 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1826 emitcode ("movx", "@r0,a");
1827 emitcode ("inc", "r0");
1830 emitcode ("mov", "%s,r0", spname);
1831 if (bitVectBitValue (rsave, R0_IDX))
1832 emitcode ("mov", "r0,b");
1835 for (i = 0; i < ds390_nRegs; i++)
1837 if (bitVectBitValue (rsave, i))
1838 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1841 detype = getSpec (operandType (IC_LEFT (ic)));
1844 /*-----------------------------------------------------------------*/
1845 /* unsaveRegisters - pop the pushed registers */
1846 /*-----------------------------------------------------------------*/
1848 unsaveRegisters (iCode * ic)
1852 /* find the registers in use at this time
1853 and push them away to safety */
1854 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1857 if (options.useXstack)
1859 emitcode ("mov", "r0,%s", spname);
1860 for (i = ds390_nRegs; i >= 0; i--)
1862 if (bitVectBitValue (rsave, i))
1864 emitcode ("dec", "r0");
1865 emitcode ("movx", "a,@r0");
1867 emitcode ("mov", "b,a");
1869 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1873 emitcode ("mov", "%s,r0", spname);
1874 if (bitVectBitValue (rsave, R0_IDX))
1875 emitcode ("mov", "r0,b");
1878 for (i = ds390_nRegs; i >= 0; i--)
1880 if (bitVectBitValue (rsave, i))
1881 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1887 /*-----------------------------------------------------------------*/
1889 /*-----------------------------------------------------------------*/
1891 pushSide (operand * oper, int size)
1894 _startLazyDPSEvaluation ();
1897 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1898 if (AOP_TYPE (oper) != AOP_REG &&
1899 AOP_TYPE (oper) != AOP_DIR &&
1902 emitcode ("mov", "a,%s", l);
1903 emitcode ("push", "acc");
1906 emitcode ("push", "%s", l);
1908 _endLazyDPSEvaluation ();
1911 /*-----------------------------------------------------------------*/
1912 /* assignResultValue - */
1913 /*-----------------------------------------------------------------*/
1915 assignResultValue (operand * oper)
1918 int size = AOP_SIZE (oper);
1920 _startLazyDPSEvaluation ();
1923 aopPut (AOP (oper), fReturn[offset], offset);
1926 _endLazyDPSEvaluation ();
1930 /*-----------------------------------------------------------------*/
1931 /* genXpush - pushes onto the external stack */
1932 /*-----------------------------------------------------------------*/
1934 genXpush (iCode * ic)
1936 asmop *aop = newAsmop (0);
1938 int size, offset = 0;
1940 D (emitcode (";", "genXpush ");
1943 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1944 r = getFreePtr (ic, &aop, FALSE);
1947 emitcode ("mov", "%s,_spx", r->name);
1949 size = AOP_SIZE (IC_LEFT (ic));
1950 _startLazyDPSEvaluation ();
1954 char *l = aopGet (AOP (IC_LEFT (ic)),
1955 offset++, FALSE, FALSE, TRUE);
1957 emitcode ("movx", "@%s,a", r->name);
1958 emitcode ("inc", "%s", r->name);
1961 _endLazyDPSEvaluation ();
1964 emitcode ("mov", "_spx,%s", r->name);
1966 freeAsmop (NULL, aop, ic, TRUE);
1967 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1970 /*-----------------------------------------------------------------*/
1971 /* genIpush - genrate code for pushing this gets a little complex */
1972 /*-----------------------------------------------------------------*/
1974 genIpush (iCode * ic)
1976 int size, offset = 0;
1979 D (emitcode (";", "genIpush ");
1982 /* if this is not a parm push : ie. it is spill push
1983 and spill push is always done on the local stack */
1987 /* and the item is spilt then do nothing */
1988 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1991 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1992 size = AOP_SIZE (IC_LEFT (ic));
1993 /* push it on the stack */
1994 _startLazyDPSEvaluation ();
1997 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
2003 emitcode ("push", "%s", l);
2005 _endLazyDPSEvaluation ();
2009 /* this is a paramter push: in this case we call
2010 the routine to find the call and save those
2011 registers that need to be saved */
2014 /* if use external stack then call the external
2015 stack pushing routine */
2016 if (options.useXstack)
2022 /* then do the push */
2023 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2025 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2026 size = AOP_SIZE (IC_LEFT (ic));
2028 _startLazyDPSEvaluation ();
2031 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2032 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2033 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2036 emitcode ("mov", "a,%s", l);
2037 emitcode ("push", "acc");
2040 emitcode ("push", "%s", l);
2042 _endLazyDPSEvaluation ();
2044 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2047 /*-----------------------------------------------------------------*/
2048 /* genIpop - recover the registers: can happen only for spilling */
2049 /*-----------------------------------------------------------------*/
2051 genIpop (iCode * ic)
2055 D (emitcode (";", "genIpop ");
2059 /* if the temp was not pushed then */
2060 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2063 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2064 size = AOP_SIZE (IC_LEFT (ic));
2065 offset = (size - 1);
2066 _startLazyDPSEvaluation ();
2069 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2070 FALSE, TRUE, TRUE));
2072 _endLazyDPSEvaluation ();
2074 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2077 /*-----------------------------------------------------------------*/
2078 /* unsaveRBank - restores the resgister bank from stack */
2079 /*-----------------------------------------------------------------*/
2081 unsaveRBank (int bank, iCode * ic, bool popPsw)
2087 if (options.useXstack)
2091 /* Assume r0 is available for use. */
2092 r = ds390_regWithIdx (R0_IDX);;
2097 r = getFreePtr (ic, &aop, FALSE);
2099 emitcode ("mov", "%s,_spx", r->name);
2104 if (options.useXstack)
2106 emitcode ("movx", "a,@%s", r->name);
2107 emitcode ("mov", "psw,a");
2108 emitcode ("dec", "%s", r->name);
2112 emitcode ("pop", "psw");
2116 for (i = (ds390_nRegs - 1); i >= 0; i--)
2118 if (options.useXstack)
2120 emitcode ("movx", "a,@%s", r->name);
2121 emitcode ("mov", "(%s+%d),a",
2122 regs390[i].base, 8 * bank + regs390[i].offset);
2123 emitcode ("dec", "%s", r->name);
2127 emitcode ("pop", "(%s+%d)",
2128 regs390[i].base, 8 * bank + regs390[i].offset);
2131 if (options.useXstack)
2133 emitcode ("mov", "_spx,%s", r->name);
2138 freeAsmop (NULL, aop, ic, TRUE);
2142 /*-----------------------------------------------------------------*/
2143 /* saveRBank - saves an entire register bank on the stack */
2144 /*-----------------------------------------------------------------*/
2146 saveRBank (int bank, iCode * ic, bool pushPsw)
2152 if (options.useXstack)
2156 /* Assume r0 is available for use. */
2157 r = ds390_regWithIdx (R0_IDX);;
2162 r = getFreePtr (ic, &aop, FALSE);
2164 emitcode ("mov", "%s,_spx", r->name);
2167 for (i = 0; i < ds390_nRegs; i++)
2169 if (options.useXstack)
2171 emitcode ("inc", "%s", r->name);
2172 emitcode ("mov", "a,(%s+%d)",
2173 regs390[i].base, 8 * bank + regs390[i].offset);
2174 emitcode ("movx", "@%s,a", r->name);
2177 emitcode ("push", "(%s+%d)",
2178 regs390[i].base, 8 * bank + regs390[i].offset);
2183 if (options.useXstack)
2185 emitcode ("mov", "a,psw");
2186 emitcode ("movx", "@%s,a", r->name);
2187 emitcode ("inc", "%s", r->name);
2188 emitcode ("mov", "_spx,%s", r->name);
2192 emitcode ("push", "psw");
2195 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2200 freeAsmop (NULL, aop, ic, TRUE);
2209 /*-----------------------------------------------------------------*/
2210 /* genCall - generates a call statement */
2211 /*-----------------------------------------------------------------*/
2213 genCall (iCode * ic)
2216 bool restoreBank = FALSE;
2217 bool swapBanks = FALSE;
2219 D (emitcode (";", "genCall "););
2221 /* if we are calling a not _naked function that is not using
2222 the same register bank then we need to save the
2223 destination registers on the stack */
2224 dtype = operandType (IC_LEFT (ic));
2225 if (dtype && !IFFUNC_ISNAKED(dtype) &&
2226 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2227 IFFUNC_ISISR (currFunc->type))
2231 /* This is unexpected; the bank should have been saved in
2234 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2240 /* if caller saves & we have not saved then */
2244 /* if send set is not empty the assign */
2245 /* We've saved all the registers we care about;
2246 * therefore, we may clobber any register not used
2247 * in the calling convention (i.e. anything not in
2254 for (sic = setFirstItem (_G.sendSet); sic;
2255 sic = setNextItem (_G.sendSet))
2257 int size, offset = 0;
2259 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2260 size = AOP_SIZE (IC_LEFT (sic));
2262 _startLazyDPSEvaluation ();
2265 char *l = aopGet (AOP(IC_LEFT(sic)), offset,
2266 FALSE, FALSE, TRUE);
2267 if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size)
2269 emitcode("mov", "%s,%s", regs390[offset].name, l);
2271 else if (strcmp (l, fReturn[offset]))
2273 emitcode ("mov", "%s,%s",
2279 _endLazyDPSEvaluation ();
2280 if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR)
2282 size = AOP_SIZE (IC_LEFT (sic));
2290 emitcode("mov", "%s,%s",
2291 fReturn[size], regs390[size].name);
2294 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2301 emitcode ("mov", "psw,#0x%02x",
2302 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2306 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2307 OP_SYMBOL (IC_LEFT (ic))->rname :
2308 OP_SYMBOL (IC_LEFT (ic))->name));
2312 emitcode ("mov", "psw,#0x%02x",
2313 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2316 /* if we need assign a result value */
2317 if ((IS_ITEMP (IC_RESULT (ic)) &&
2318 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2319 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2320 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2321 IS_TRUE_SYMOP (IC_RESULT (ic)))
2323 if (isOperandInFarSpace (IC_RESULT (ic))
2324 && getSize (operandType (IC_RESULT (ic))) <= 2)
2326 int size = getSize (operandType (IC_RESULT (ic)));
2328 /* Special case for 1 or 2 byte return in far space. */
2332 emitcode ("mov", "b,%s", fReturn[1]);
2335 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2336 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2340 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2342 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2347 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2350 assignResultValue (IC_RESULT (ic));
2352 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2356 /* adjust the stack for parameters if
2358 if (ic->parmBytes) {
2359 if (options.stack10bit) {
2360 emitcode ("clr","c");
2361 emitcode ("mov","a,sp");
2362 emitcode ("subb","a,#0x%02x",ic->parmBytes & 0xff);
2363 emitcode ("mov","sp,a");
2364 emitcode ("mov","a,#0x%02x",(ic->parmBytes >> 8) & 0xff);
2365 emitcode ("subb","a,_ESP");
2366 emitcode ("mov","_ESP,a");
2369 if (ic->parmBytes > 3) {
2370 emitcode ("mov", "a,%s", spname);
2371 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2372 emitcode ("mov", "%s,a", spname);
2374 for (i = 0; i < ic->parmBytes; i++)
2375 emitcode ("dec", "%s", spname);
2379 /* if we hade saved some registers then unsave them */
2380 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2381 unsaveRegisters (ic);
2383 /* if register bank was saved then pop them */
2385 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2388 /*-----------------------------------------------------------------*/
2389 /* genPcall - generates a call by pointer statement */
2390 /*-----------------------------------------------------------------*/
2392 genPcall (iCode * ic)
2395 symbol *rlbl = newiTempLabel (NULL);
2396 bool restoreBank=FALSE;
2398 D (emitcode (";", "genPcall ");
2402 /* if caller saves & we have not saved then */
2406 /* if we are calling a function that is not using
2407 the same register bank then we need to save the
2408 destination registers on the stack */
2409 dtype = operandType (IC_LEFT (ic));
2410 if (dtype && !IFFUNC_ISNAKED(dtype) &&
2411 IFFUNC_ISISR (currFunc->type) &&
2412 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2413 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2417 /* push the return address on to the stack */
2418 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2419 emitcode ("push", "acc");
2420 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2421 emitcode ("push", "acc");
2423 if (options.model == MODEL_FLAT24)
2425 emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2426 emitcode ("push", "acc");
2429 /* now push the calling address */
2430 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2432 pushSide (IC_LEFT (ic), FPTRSIZE);
2434 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2436 /* if send set is not empty the assign */
2441 for (sic = setFirstItem (_G.sendSet); sic;
2442 sic = setNextItem (_G.sendSet))
2444 int size, offset = 0;
2446 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2447 size = AOP_SIZE (IC_LEFT (sic));
2448 _startLazyDPSEvaluation ();
2451 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2452 FALSE, FALSE, TRUE);
2453 if (strcmp (l, fReturn[offset]))
2455 emitcode ("mov", "%s,%s",
2461 _endLazyDPSEvaluation ();
2462 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2467 emitcode ("ret", "");
2468 emitcode ("", "%05d$:", (rlbl->key + 100));
2471 /* if we need assign a result value */
2472 if ((IS_ITEMP (IC_RESULT (ic)) &&
2473 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2474 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2475 IS_TRUE_SYMOP (IC_RESULT (ic)))
2479 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2482 assignResultValue (IC_RESULT (ic));
2484 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2487 /* adjust the stack for parameters if
2492 if (ic->parmBytes > 3)
2494 emitcode ("mov", "a,%s", spname);
2495 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2496 emitcode ("mov", "%s,a", spname);
2499 for (i = 0; i < ic->parmBytes; i++)
2500 emitcode ("dec", "%s", spname);
2504 /* if register bank was saved then unsave them */
2506 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2508 /* if we hade saved some registers then
2510 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2511 unsaveRegisters (ic);
2515 /*-----------------------------------------------------------------*/
2516 /* resultRemat - result is rematerializable */
2517 /*-----------------------------------------------------------------*/
2519 resultRemat (iCode * ic)
2521 if (SKIP_IC (ic) || ic->op == IFX)
2524 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2526 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2527 if (sym->remat && !POINTER_SET (ic))
2534 #if defined(__BORLANDC__) || defined(_MSC_VER)
2535 #define STRCASECMP stricmp
2537 #define STRCASECMP strcasecmp
2540 /*-----------------------------------------------------------------*/
2541 /* inExcludeList - return 1 if the string is in exclude Reg list */
2542 /*-----------------------------------------------------------------*/
2544 inExcludeList (char *s)
2548 if (options.excludeRegs[i] &&
2549 STRCASECMP (options.excludeRegs[i], "none") == 0)
2552 for (i = 0; options.excludeRegs[i]; i++)
2554 if (options.excludeRegs[i] &&
2555 STRCASECMP (s, options.excludeRegs[i]) == 0)
2561 /*-----------------------------------------------------------------*/
2562 /* genFunction - generated code for function entry */
2563 /*-----------------------------------------------------------------*/
2565 genFunction (iCode * ic)
2569 bool switchedPSW = FALSE;
2571 D (emitcode (";", "genFunction "););
2574 /* create the function header */
2575 emitcode (";", "-----------------------------------------");
2576 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2577 emitcode (";", "-----------------------------------------");
2579 emitcode ("", "%s:", sym->rname);
2580 ftype = operandType (IC_LEFT (ic));
2582 if (IFFUNC_ISNAKED(ftype))
2584 emitcode(";", "naked function: no prologue.");
2588 /* if critical function then turn interrupts off */
2589 if (IFFUNC_ISCRITICAL (ftype))
2590 emitcode ("clr", "ea");
2592 /* here we need to generate the equates for the
2593 register bank if required */
2594 if (FUNC_REGBANK (ftype) != rbank)
2598 rbank = FUNC_REGBANK (ftype);
2599 for (i = 0; i < ds390_nRegs; i++)
2601 if (regs390[i].print) {
2602 if (strcmp (regs390[i].base, "0") == 0)
2603 emitcode ("", "%s = 0x%02x",
2605 8 * rbank + regs390[i].offset);
2607 emitcode ("", "%s = %s + 0x%02x",
2610 8 * rbank + regs390[i].offset);
2615 /* if this is an interrupt service routine then
2616 save acc, b, dpl, dph */
2617 if (IFFUNC_ISISR (sym->type))
2620 if (!inExcludeList ("acc"))
2621 emitcode ("push", "acc");
2622 if (!inExcludeList ("b"))
2623 emitcode ("push", "b");
2624 if (!inExcludeList ("dpl"))
2625 emitcode ("push", "dpl");
2626 if (!inExcludeList ("dph"))
2627 emitcode ("push", "dph");
2628 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2630 emitcode ("push", "dpx");
2631 /* Make sure we're using standard DPTR */
2632 emitcode ("push", "dps");
2633 emitcode ("mov", "dps, #0x00");
2634 if (options.stack10bit)
2636 /* This ISR could conceivably use DPTR2. Better save it. */
2637 emitcode ("push", "dpl1");
2638 emitcode ("push", "dph1");
2639 emitcode ("push", "dpx1");
2640 emitcode ("push", DP2_RESULT_REG);
2643 /* if this isr has no bank i.e. is going to
2644 run with bank 0 , then we need to save more
2646 if (!FUNC_REGBANK (sym->type))
2649 /* if this function does not call any other
2650 function then we can be economical and
2651 save only those registers that are used */
2652 if (!IFFUNC_HASFCALL(sym->type))
2656 /* if any registers used */
2659 /* save the registers used */
2660 for (i = 0; i < sym->regsUsed->size; i++)
2662 if (bitVectBitValue (sym->regsUsed, i) ||
2663 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2664 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2671 /* this function has a function call cannot
2672 determines register usage so we will have to push the
2674 saveRBank (0, ic, FALSE);
2679 /* This ISR uses a non-zero bank.
2681 * We assume that the bank is available for our
2684 * However, if this ISR calls a function which uses some
2685 * other bank, we must save that bank entirely.
2687 unsigned long banksToSave = 0;
2689 if (IFFUNC_HASFCALL(sym->type))
2692 #define MAX_REGISTER_BANKS 4
2697 for (i = ic; i; i = i->next)
2699 if (i->op == ENDFUNCTION)
2701 /* we got to the end OK. */
2709 dtype = operandType (IC_LEFT(i));
2711 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2713 /* Mark this bank for saving. */
2714 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2716 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2720 banksToSave |= (1 << FUNC_REGBANK(dtype));
2723 /* And note that we don't need to do it in
2731 /* This is a mess; we have no idea what
2732 * register bank the called function might
2735 * The only thing I can think of to do is
2736 * throw a warning and hope.
2738 werror(W_FUNCPTR_IN_USING_ISR);
2742 if (banksToSave && options.useXstack)
2744 /* Since we aren't passing it an ic,
2745 * saveRBank will assume r0 is available to abuse.
2747 * So switch to our (trashable) bank now, so
2748 * the caller's R0 isn't trashed.
2750 emitcode ("push", "psw");
2751 emitcode ("mov", "psw,#0x%02x",
2752 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2756 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2758 if (banksToSave & (1 << ix))
2760 saveRBank(ix, NULL, FALSE);
2764 // jwk: this needs a closer look
2765 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2770 /* if callee-save to be used for this function
2771 then save the registers being used in this function */
2772 if (IFFUNC_CALLEESAVES(sym->type))
2776 /* if any registers used */
2779 /* save the registers used */
2780 for (i = 0; i < sym->regsUsed->size; i++)
2782 if (bitVectBitValue (sym->regsUsed, i) ||
2783 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2785 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2793 /* set the register bank to the desired value */
2794 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2797 emitcode ("push", "psw");
2798 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2801 if (IFFUNC_ISREENT (sym->type) || options.stackAuto) {
2802 if (options.stack10bit) {
2803 emitcode ("push","_bpx");
2804 emitcode ("push","_bpx+1");
2805 emitcode ("mov","_bpx,%s",spname);
2806 emitcode ("mov","_bpx+1,_ESP");
2807 emitcode ("anl","_bpx+1,#3");
2809 if (options.useXstack) {
2810 emitcode ("mov", "r0,%s", spname);
2811 emitcode ("mov", "a,_bp");
2812 emitcode ("movx", "@r0,a");
2813 emitcode ("inc", "%s", spname);
2815 /* set up the stack */
2816 emitcode ("push", "_bp"); /* save the callers stack */
2818 emitcode ("mov", "_bp,%s", spname);
2822 /* adjust the stack for the function */
2825 if (options.stack10bit) {
2826 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
2827 assert (sym->recvSize <= 4);
2828 emitcode ("mov","a,sp");
2829 emitcode ("add","a,#0x%02x", ((short) sym->stack & 0xff));
2830 emitcode ("mov","sp,a");
2831 emitcode ("mov","a,_ESP");
2832 emitcode ("addc","a,0x%02x", (((short) sym->stack) >> 8) & 0xff);
2833 emitcode ("mov","_ESP,a");
2836 werror (W_STACK_OVERFLOW, sym->name);
2838 if (i > 3 && sym->recvSize < 4) {
2840 emitcode ("mov", "a,sp");
2841 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2842 emitcode ("mov", "sp,a");
2846 emitcode ("inc", "sp");
2853 emitcode ("mov", "a,_spx");
2854 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2855 emitcode ("mov", "_spx,a");
2860 /*-----------------------------------------------------------------*/
2861 /* genEndFunction - generates epilogue for functions */
2862 /*-----------------------------------------------------------------*/
2864 genEndFunction (iCode * ic)
2866 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2868 D (emitcode (";", "genEndFunction "););
2870 if (IFFUNC_ISNAKED(sym->type))
2872 emitcode(";", "naked function: no epilogue.");
2876 if (IFFUNC_ISREENT (sym->type) || options.stackAuto) {
2877 if (options.stack10bit) {
2878 emitcode ("mov", "sp,_bpx", spname);
2879 emitcode ("mov", "_ESP,_bpx+1", spname);
2881 emitcode ("mov", "%s,_bp", spname);
2885 /* if use external stack but some variables were
2886 added to the local stack then decrement the
2888 if (options.useXstack && sym->stack) {
2889 emitcode ("mov", "a,sp");
2890 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2891 emitcode ("mov", "sp,a");
2895 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto)) {
2896 if (options.useXstack) {
2897 emitcode ("mov", "r0,%s", spname);
2898 emitcode ("movx", "a,@r0");
2899 emitcode ("mov", "_bp,a");
2900 emitcode ("dec", "%s", spname);
2902 if (options.stack10bit) {
2903 emitcode ("pop", "_bpx+1");
2904 emitcode ("pop", "_bpx");
2906 emitcode ("pop", "_bp");
2911 /* restore the register bank */
2912 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2914 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
2915 || !options.useXstack)
2917 /* Special case of ISR using non-zero bank with useXstack
2920 emitcode ("pop", "psw");
2924 if (IFFUNC_ISISR (sym->type))
2927 /* now we need to restore the registers */
2928 /* if this isr has no bank i.e. is going to
2929 run with bank 0 , then we need to save more
2931 if (!FUNC_REGBANK (sym->type))
2933 /* if this function does not call any other
2934 function then we can be economical and
2935 save only those registers that are used */
2936 if (!IFFUNC_HASFCALL(sym->type))
2940 /* if any registers used */
2943 /* save the registers used */
2944 for (i = sym->regsUsed->size; i >= 0; i--)
2946 if (bitVectBitValue (sym->regsUsed, i) ||
2947 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2948 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2955 /* this function has a function call cannot
2956 determines register usage so we will have to pop the
2958 unsaveRBank (0, ic, FALSE);
2963 /* This ISR uses a non-zero bank.
2965 * Restore any register banks saved by genFunction
2968 // jwk: this needs a closer look
2969 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2972 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2974 if (savedBanks & (1 << ix))
2976 unsaveRBank(ix, NULL, FALSE);
2980 if (options.useXstack)
2982 /* Restore bank AFTER calling unsaveRBank,
2983 * since it can trash r0.
2985 emitcode ("pop", "psw");
2989 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2991 if (options.stack10bit)
2993 emitcode ("pop", DP2_RESULT_REG);
2994 emitcode ("pop", "dpx1");
2995 emitcode ("pop", "dph1");
2996 emitcode ("pop", "dpl1");
2998 emitcode ("pop", "dps");
2999 emitcode ("pop", "dpx");
3001 if (!inExcludeList ("dph"))
3002 emitcode ("pop", "dph");
3003 if (!inExcludeList ("dpl"))
3004 emitcode ("pop", "dpl");
3005 if (!inExcludeList ("b"))
3006 emitcode ("pop", "b");
3007 if (!inExcludeList ("acc"))
3008 emitcode ("pop", "acc");
3010 if (IFFUNC_ISCRITICAL (sym->type))
3011 emitcode ("setb", "ea");
3013 /* if debug then send end of function */
3014 if (options.debug && currFunc) {
3016 emitcode ("", "C$%s$%d$%d$%d ==.",
3017 FileBaseName (ic->filename), currFunc->lastLine,
3018 ic->level, ic->block);
3019 if (IS_STATIC (currFunc->etype))
3020 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3022 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3026 emitcode ("reti", "");
3030 if (IFFUNC_ISCRITICAL (sym->type))
3031 emitcode ("setb", "ea");
3033 if (IFFUNC_CALLEESAVES(sym->type))
3037 /* if any registers used */
3040 /* save the registers used */
3041 for (i = sym->regsUsed->size; i >= 0; i--)
3043 if (bitVectBitValue (sym->regsUsed, i) ||
3044 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3045 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3051 /* if debug then send end of function */
3052 if (options.debug && currFunc)
3055 emitcode ("", "C$%s$%d$%d$%d ==.",
3056 FileBaseName (ic->filename), currFunc->lastLine,
3057 ic->level, ic->block);
3058 if (IS_STATIC (currFunc->etype))
3059 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3061 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3065 emitcode ("ret", "");
3070 /*-----------------------------------------------------------------*/
3071 /* genRet - generate code for return statement */
3072 /*-----------------------------------------------------------------*/
3076 int size, offset = 0, pushed = 0;
3078 D (emitcode (";", "genRet ");
3081 /* if we have no return value then
3082 just generate the "ret" */
3086 /* we have something to return then
3087 move the return value into place */
3088 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
3089 size = AOP_SIZE (IC_LEFT (ic));
3091 _startLazyDPSEvaluation ();
3095 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3097 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3098 FALSE, TRUE, FALSE);
3099 emitcode ("push", "%s", l);
3104 /* Since A is the last element of fReturn,
3105 * is is OK to clobber it in the aopGet.
3107 l = aopGet (AOP (IC_LEFT (ic)), offset,
3108 FALSE, FALSE, TRUE);
3109 if (strcmp (fReturn[offset], l))
3110 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3113 _endLazyDPSEvaluation ();
3120 if (strcmp (fReturn[pushed], "a"))
3121 emitcode ("pop", fReturn[pushed]);
3123 emitcode ("pop", "acc");
3126 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3129 /* generate a jump to the return label
3130 if the next is not the return statement */
3131 if (!(ic->next && ic->next->op == LABEL &&
3132 IC_LABEL (ic->next) == returnLabel))
3134 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3138 /*-----------------------------------------------------------------*/
3139 /* genLabel - generates a label */
3140 /*-----------------------------------------------------------------*/
3142 genLabel (iCode * ic)
3144 /* special case never generate */
3145 if (IC_LABEL (ic) == entryLabel)
3148 D (emitcode (";", "genLabel ");
3151 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3154 /*-----------------------------------------------------------------*/
3155 /* genGoto - generates a ljmp */
3156 /*-----------------------------------------------------------------*/
3158 genGoto (iCode * ic)
3160 D (emitcode (";", "genGoto ");
3162 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3165 /*-----------------------------------------------------------------*/
3166 /* findLabelBackwards: walks back through the iCode chain looking */
3167 /* for the given label. Returns number of iCode instructions */
3168 /* between that label and given ic. */
3169 /* Returns zero if label not found. */
3170 /*-----------------------------------------------------------------*/
3172 findLabelBackwards (iCode * ic, int key)
3181 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3183 /* printf("findLabelBackwards = %d\n", count); */
3191 /*-----------------------------------------------------------------*/
3192 /* genPlusIncr :- does addition with increment if possible */
3193 /*-----------------------------------------------------------------*/
3195 genPlusIncr (iCode * ic)
3197 unsigned int icount;
3198 unsigned int size = getDataSize (IC_RESULT (ic));
3200 /* will try to generate an increment */
3201 /* if the right side is not a literal
3203 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3206 /* if the literal value of the right hand side
3207 is greater than 4 then it is not worth it */
3208 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3211 /* if increment 16 bits in register */
3213 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3214 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3215 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3223 /* If the next instruction is a goto and the goto target
3224 * is <= 5 instructions previous to this, we can generate
3225 * jumps straight to that target.
3227 if (ic->next && ic->next->op == GOTO
3228 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3231 emitcode (";", "tail increment optimized (range %d)", labelRange);
3232 tlbl = IC_LABEL (ic->next);
3237 tlbl = newiTempLabel (NULL);
3240 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3241 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3242 IS_AOP_PREG (IC_RESULT (ic)))
3243 emitcode ("cjne", "%s,#0x00,%05d$"
3244 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3248 emitcode ("clr", "a");
3249 emitcode ("cjne", "a,%s,%05d$"
3250 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3254 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3257 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3258 IS_AOP_PREG (IC_RESULT (ic)))
3259 emitcode ("cjne", "%s,#0x00,%05d$"
3260 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3263 emitcode ("cjne", "a,%s,%05d$"
3264 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3267 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, 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)), MSB24, FALSE, FALSE, FALSE)
3278 emitcode ("cjne", "a,%s,%05d$"
3279 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3282 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3287 emitcode ("", "%05d$:", tlbl->key + 100);
3292 /* if the sizes are greater than 1 then we cannot */
3293 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3294 AOP_SIZE (IC_LEFT (ic)) > 1)
3297 /* we can if the aops of the left & result match or
3298 if they are in registers and the registers are the
3301 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3302 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3303 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3308 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3309 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3310 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3315 _startLazyDPSEvaluation ();
3318 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3320 _endLazyDPSEvaluation ();
3329 /*-----------------------------------------------------------------*/
3330 /* outBitAcc - output a bit in acc */
3331 /*-----------------------------------------------------------------*/
3333 outBitAcc (operand * result)
3335 symbol *tlbl = newiTempLabel (NULL);
3336 /* if the result is a bit */
3337 if (AOP_TYPE (result) == AOP_CRY)
3339 aopPut (AOP (result), "a", 0);
3343 emitcode ("jz", "%05d$", tlbl->key + 100);
3344 emitcode ("mov", "a,%s", one);
3345 emitcode ("", "%05d$:", tlbl->key + 100);
3350 /*-----------------------------------------------------------------*/
3351 /* genPlusBits - generates code for addition of two bits */
3352 /*-----------------------------------------------------------------*/
3354 genPlusBits (iCode * ic)
3356 D (emitcode (";", "genPlusBits ");
3358 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3360 symbol *lbl = newiTempLabel (NULL);
3361 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3362 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3363 emitcode ("cpl", "c");
3364 emitcode ("", "%05d$:", (lbl->key + 100));
3365 outBitC (IC_RESULT (ic));
3369 emitcode ("clr", "a");
3370 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3371 emitcode ("rlc", "a");
3372 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3373 emitcode ("addc", "a,#0x00");
3374 outAcc (IC_RESULT (ic));
3379 adjustArithmeticResult (iCode * ic)
3381 if (opIsGptr (IC_RESULT (ic)) &&
3382 opIsGptr (IC_LEFT (ic)) &&
3383 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3385 aopPut (AOP (IC_RESULT (ic)),
3386 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3390 if (opIsGptr (IC_RESULT (ic)) &&
3391 opIsGptr (IC_RIGHT (ic)) &&
3392 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3394 aopPut (AOP (IC_RESULT (ic)),
3395 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3399 if (opIsGptr (IC_RESULT (ic)) &&
3400 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3401 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3402 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3403 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3406 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3407 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3411 #if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
3412 // Please don't bring it back without a really good reason.
3413 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3414 // (because all three operands are in far space).
3415 #define AOP_OP_3(ic) \
3416 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3417 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3418 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3419 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3420 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3421 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3423 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3425 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3429 // Macro to aopOp all three operands of an ic. If this cannot be done,
3430 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3431 // will be set TRUE. The caller must then handle the case specially, noting
3432 // that the IC_RESULT operand is not aopOp'd.
3433 #define AOP_OP_3_NOFATAL(ic, rc) \
3434 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3435 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR) || \
3436 (OP_SYMBOL(IC_RESULT(ic))->ruonly)); \
3437 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3438 (isOperandInFarSpace(IC_RESULT(ic)) || OP_SYMBOL(IC_RESULT(ic))->ruonly )) \
3440 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3445 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3446 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3448 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3449 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3451 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3453 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3457 // aopOp the left & right operands of an ic.
3458 #define AOP_OP_2(ic) \
3459 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3460 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3462 // convienience macro.
3463 #define AOP_SET_LOCALS(ic) \
3464 left = IC_LEFT(ic); \
3465 right = IC_RIGHT(ic); \
3466 result = IC_RESULT(ic);
3469 // Given an integer value of pushedSize bytes on the stack,
3470 // adjust it to be resultSize bytes, either by discarding
3471 // the most significant bytes or by zero-padding.
3473 // On exit from this macro, pushedSize will have been adjusted to
3474 // equal resultSize, and ACC may be trashed.
3475 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3476 /* If the pushed data is bigger than the result, \
3477 * simply discard unused bytes. Icky, but works. \
3479 while (pushedSize > resultSize) \
3481 D (emitcode (";", "discarding unused result byte."););\
3482 emitcode ("pop", "acc"); \
3485 if (pushedSize < resultSize) \
3487 emitcode ("clr", "a"); \
3488 /* Conversly, we haven't pushed enough here. \
3489 * just zero-pad, and all is well. \
3491 while (pushedSize < resultSize) \
3493 emitcode("push", "acc"); \
3497 assert(pushedSize == resultSize);
3499 /*-----------------------------------------------------------------*/
3500 /* genPlus - generates code for addition */
3501 /*-----------------------------------------------------------------*/
3503 genPlus (iCode * ic)
3505 int size, offset = 0;
3506 bool pushResult = FALSE;
3509 D (emitcode (";", "genPlus "););
3511 /* special cases :- */
3512 if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) &&
3513 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3514 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3515 size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3516 while (size--) emitcode ("inc","dptr");
3517 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3520 if ( IS_SYMOP(IC_LEFT(ic)) &&
3521 OP_SYMBOL(IC_LEFT(ic))->remat &&
3522 isOperandInFarSpace(IC_RIGHT(ic))) {
3523 operand *op = IC_RIGHT(ic);
3524 IC_RIGHT(ic) = IC_LEFT(ic);
3528 AOP_OP_3_NOFATAL (ic, pushResult);
3531 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3536 /* if literal, literal on the right or
3537 if left requires ACC or right is already
3539 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3540 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3541 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3543 operand *t = IC_RIGHT (ic);
3544 IC_RIGHT (ic) = IC_LEFT (ic);
3546 emitcode (";", "Swapped plus args.");
3549 /* if both left & right are in bit
3551 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3552 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3558 /* if left in bit space & right literal */
3559 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3560 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3562 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3563 /* if result in bit space */
3564 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3566 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3567 emitcode ("cpl", "c");
3568 outBitC (IC_RESULT (ic));
3572 size = getDataSize (IC_RESULT (ic));
3573 _startLazyDPSEvaluation ();
3576 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3577 emitcode ("addc", "a,#00");
3578 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3580 _endLazyDPSEvaluation ();
3585 /* if I can do an increment instead
3586 of add then GOOD for ME */
3587 if (genPlusIncr (ic) == TRUE)
3589 emitcode (";", "did genPlusIncr");
3594 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3596 _startLazyDPSEvaluation ();
3599 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3601 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3603 emitcode ("add", "a,%s",
3604 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3606 emitcode ("addc", "a,%s",
3607 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3611 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3613 /* right is going to use ACC or we would have taken the
3616 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3618 D(emitcode(";", "+ AOP_ACC special case."););
3619 emitcode("xch", "a, %s", DP2_RESULT_REG);
3621 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3624 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3627 emitcode("add", "a, %s", DP2_RESULT_REG);
3631 emitcode ("add", "a,%s",
3632 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3637 emitcode ("addc", "a,%s",
3638 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3643 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3647 emitcode ("push", "acc");
3651 _endLazyDPSEvaluation ();
3655 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3657 size = getDataSize (IC_LEFT (ic));
3658 rSize = getDataSize (IC_RESULT (ic));
3660 ADJUST_PUSHED_RESULT(size, rSize);
3662 _startLazyDPSEvaluation ();
3665 emitcode ("pop", "acc");
3666 aopPut (AOP (IC_RESULT (ic)), "a", size);
3668 _endLazyDPSEvaluation ();
3671 adjustArithmeticResult (ic);
3674 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3675 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3676 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3679 /*-----------------------------------------------------------------*/
3680 /* genMinusDec :- does subtraction with deccrement if possible */
3681 /*-----------------------------------------------------------------*/
3683 genMinusDec (iCode * ic)
3685 unsigned int icount;
3686 unsigned int size = getDataSize (IC_RESULT (ic));
3688 /* will try to generate an increment */
3689 /* if the right side is not a literal
3691 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3694 /* if the literal value of the right hand side
3695 is greater than 4 then it is not worth it */
3696 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3699 /* if decrement 16 bits in register */
3700 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3701 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3702 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3710 /* If the next instruction is a goto and the goto target
3711 * is <= 5 instructions previous to this, we can generate
3712 * jumps straight to that target.
3714 if (ic->next && ic->next->op == GOTO
3715 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3718 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3719 tlbl = IC_LABEL (ic->next);
3724 tlbl = newiTempLabel (NULL);
3728 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3729 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3730 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3731 IS_AOP_PREG (IC_RESULT (ic)))
3732 emitcode ("cjne", "%s,#0xff,%05d$"
3733 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3737 emitcode ("mov", "a,#0xff");
3738 emitcode ("cjne", "a,%s,%05d$"
3739 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3742 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3745 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3746 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3747 IS_AOP_PREG (IC_RESULT (ic)))
3748 emitcode ("cjne", "%s,#0xff,%05d$"
3749 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3753 emitcode ("cjne", "a,%s,%05d$"
3754 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3757 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3761 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3762 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3763 IS_AOP_PREG (IC_RESULT (ic)))
3764 emitcode ("cjne", "%s,#0xff,%05d$"
3765 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3769 emitcode ("cjne", "a,%s,%05d$"
3770 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3773 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3777 emitcode ("", "%05d$:", tlbl->key + 100);
3782 /* if the sizes are greater than 1 then we cannot */
3783 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3784 AOP_SIZE (IC_LEFT (ic)) > 1)
3787 /* we can if the aops of the left & result match or
3788 if they are in registers and the registers are the
3791 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3792 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3793 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3796 _startLazyDPSEvaluation ();
3799 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3801 _endLazyDPSEvaluation ();
3809 /*-----------------------------------------------------------------*/
3810 /* addSign - complete with sign */
3811 /*-----------------------------------------------------------------*/
3813 addSign (operand * result, int offset, int sign)
3815 int size = (getDataSize (result) - offset);
3818 _startLazyDPSEvaluation();
3821 emitcode ("rlc", "a");
3822 emitcode ("subb", "a,acc");
3825 aopPut (AOP (result), "a", offset++);
3832 aopPut (AOP (result), zero, offset++);
3835 _endLazyDPSEvaluation();
3839 /*-----------------------------------------------------------------*/
3840 /* genMinusBits - generates code for subtraction of two bits */
3841 /*-----------------------------------------------------------------*/
3843 genMinusBits (iCode * ic)
3845 symbol *lbl = newiTempLabel (NULL);
3847 D (emitcode (";", "genMinusBits "););
3849 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3851 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3852 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3853 emitcode ("cpl", "c");
3854 emitcode ("", "%05d$:", (lbl->key + 100));
3855 outBitC (IC_RESULT (ic));
3859 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3860 emitcode ("subb", "a,acc");
3861 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3862 emitcode ("inc", "a");
3863 emitcode ("", "%05d$:", (lbl->key + 100));
3864 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3865 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3869 /*-----------------------------------------------------------------*/
3870 /* genMinus - generates code for subtraction */
3871 /*-----------------------------------------------------------------*/
3873 genMinus (iCode * ic)
3875 int size, offset = 0;
3877 unsigned long lit = 0L;
3878 bool pushResult = FALSE;
3880 D (emitcode (";", "genMinus "););
3882 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3883 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3884 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3885 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3891 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3893 /* special cases :- */
3894 /* if both left & right are in bit space */
3895 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3896 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3902 /* if I can do an decrement instead
3903 of subtract then GOOD for ME */
3904 if (genMinusDec (ic) == TRUE)
3909 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3911 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3917 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3922 /* if literal, add a,#-lit, else normal subb */
3923 _startLazyDPSEvaluation ();
3926 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3927 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3928 emitcode ("subb", "a,%s",
3929 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3932 /* first add without previous c */
3934 if (!size && lit==-1) {
3935 emitcode ("dec", "a");
3937 emitcode ("add", "a,#0x%02x",
3938 (unsigned int) (lit & 0x0FFL));
3941 emitcode ("addc", "a,#0x%02x",
3942 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3948 emitcode ("push", "acc");
3952 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3956 _endLazyDPSEvaluation ();
3960 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3962 size = getDataSize (IC_LEFT (ic));
3963 rSize = getDataSize (IC_RESULT (ic));
3965 ADJUST_PUSHED_RESULT(size, rSize);
3967 _startLazyDPSEvaluation ();
3970 emitcode ("pop", "acc");
3971 aopPut (AOP (IC_RESULT (ic)), "a", size);
3973 _endLazyDPSEvaluation ();
3976 adjustArithmeticResult (ic);
3979 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3980 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3981 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3985 /*-----------------------------------------------------------------*/
3986 /* genMultbits :- multiplication of bits */
3987 /*-----------------------------------------------------------------*/
3989 genMultbits (operand * left,
3994 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3995 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3996 aopOp(result, ic, TRUE, FALSE);
4001 /*-----------------------------------------------------------------*/
4002 /* genMultOneByte : 8*8=8/16 bit multiplication */
4003 /*-----------------------------------------------------------------*/
4005 genMultOneByte (operand * left,
4010 sym_link *opetype = operandType (result);
4014 /* (if two literals: the value is computed before) */
4015 /* if one literal, literal on the right */
4016 if (AOP_TYPE (left) == AOP_LIT)
4021 emitcode (";", "swapped left and right");
4024 if (SPEC_USIGN(opetype)
4025 // ignore the sign of left and right, what else can we do?
4026 || (SPEC_USIGN(operandType(left)) &&
4027 SPEC_USIGN(operandType(right)))) {
4028 // just an unsigned 8*8=8/16 multiply
4029 //emitcode (";","unsigned");
4030 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4031 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4032 emitcode ("mul", "ab");
4035 aopOp(result, ic, TRUE, FALSE);
4037 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4039 // this should never happen
4040 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4041 AOP_SIZE(result), __FILE__, lineno);
4045 aopPut (AOP (result), "a", 0);
4047 if (AOP_SIZE(result)==2)
4049 aopPut (AOP (result), "b", 1);
4054 // we have to do a signed multiply
4056 emitcode (";", "signed");
4057 emitcode ("clr", "F0"); // reset sign flag
4058 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4060 lbl=newiTempLabel(NULL);
4061 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
4062 // left side is negative, 8-bit two's complement, this fails for -128
4063 emitcode ("setb", "F0"); // set sign flag
4064 emitcode ("cpl", "a");
4065 emitcode ("inc", "a");
4067 emitcode ("", "%05d$:", lbl->key+100);
4070 if (AOP_TYPE(right)==AOP_LIT) {
4071 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4072 /* AND literal negative */
4073 if ((int) val < 0) {
4074 emitcode ("cpl", "F0"); // complement sign flag
4075 emitcode ("mov", "b,#0x%02x", -val);
4077 emitcode ("mov", "b,#0x%02x", val);
4080 lbl=newiTempLabel(NULL);
4081 emitcode ("mov", "b,a");
4082 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4083 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
4084 // right side is negative, 8-bit two's complement
4085 emitcode ("cpl", "F0"); // complement sign flag
4086 emitcode ("cpl", "a");
4087 emitcode ("inc", "a");
4088 emitcode ("", "%05d$:", lbl->key+100);
4090 emitcode ("mul", "ab");
4093 aopOp(result, ic, TRUE, FALSE);
4095 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4097 // this should never happen
4098 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4099 AOP_SIZE(result), __FILE__, lineno);
4103 lbl=newiTempLabel(NULL);
4104 emitcode ("jnb", "F0,%05d$", lbl->key+100);
4105 // only ONE op was negative, we have to do a 8/16-bit two's complement
4106 emitcode ("cpl", "a"); // lsb
4107 if (AOP_SIZE(result)==1) {
4108 emitcode ("inc", "a");
4110 emitcode ("add", "a,#1");
4111 emitcode ("xch", "a,b");
4112 emitcode ("cpl", "a"); // msb
4113 emitcode ("addc", "a,#0");
4114 emitcode ("xch", "a,b");
4117 emitcode ("", "%05d$:", lbl->key+100);
4118 aopPut (AOP (result), "a", 0);
4120 if (AOP_SIZE(result)==2) {
4121 aopPut (AOP (result), "b", 1);
4125 /*-----------------------------------------------------------------*/
4126 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4127 /*-----------------------------------------------------------------*/
4128 static void genMultTwoByte (operand *left, operand *right,
4129 operand *result, iCode *ic)
4131 sym_link *retype = getSpec(operandType(right));
4132 sym_link *letype = getSpec(operandType(left));
4133 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4136 if (AOP_TYPE (left) == AOP_LIT) {
4141 /* save EA bit in F1 */
4142 lbl = newiTempLabel(NULL);
4143 emitcode ("setb","F1");
4144 emitcode ("jbc","EA,%05d$",lbl->key+100);
4145 emitcode ("clr","F1");
4146 emitcode("","%05d$:",lbl->key+100);
4148 /* load up MB with right */
4150 emitcode("clr","F0");
4151 if (AOP_TYPE(right) == AOP_LIT) {
4152 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4154 emitcode("setb","F0");
4157 emitcode ("mov","mb,#0x%02x",val & 0xff);
4158 emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4160 lbl = newiTempLabel(NULL);
4161 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4162 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4163 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4164 emitcode ("xch", "a,b");
4165 emitcode ("cpl","a");
4166 emitcode ("add", "a,#1");
4167 emitcode ("xch", "a,b");
4168 emitcode ("cpl", "a"); // msb
4169 emitcode ("addc", "a,#0");
4170 emitcode ("setb","F0");
4171 emitcode ("","%05d$:",lbl->key+100);
4172 emitcode ("mov","mb,b");
4173 emitcode ("mov","mb,a");
4176 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4177 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4179 /* load up MA with left */
4181 lbl = newiTempLabel(NULL);
4182 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4183 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4184 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4185 emitcode ("xch", "a,b");
4186 emitcode ("cpl","a");
4187 emitcode ("add", "a,#1");
4188 emitcode ("xch", "a,b");
4189 emitcode ("cpl", "a"); // msb
4190 emitcode ("addc","a,#0");
4191 emitcode ("jbc","F0,%05d$",lbl->key+100);
4192 emitcode ("setb","F0");
4193 emitcode ("","%05d$:",lbl->key+100);
4194 emitcode ("mov","ma,b");
4195 emitcode ("mov","ma,a");
4197 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4198 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4200 /* wait for multiplication to finish */
4201 lbl = newiTempLabel(NULL);
4202 emitcode("","%05d$:", lbl->key+100);
4203 emitcode("mov","a,mcnt1");
4204 emitcode("anl","a,#0x80");
4205 emitcode("jnz","%05d$",lbl->key+100);
4207 freeAsmop (left, NULL, ic, TRUE);
4208 freeAsmop (right, NULL, ic,TRUE);
4209 aopOp(result, ic, TRUE, FALSE);
4211 /* if unsigned then simple */
4213 emitcode ("mov","a,ma");
4214 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4215 emitcode ("mov","a,ma");
4216 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4217 aopPut(AOP(result),"ma",1);
4218 aopPut(AOP(result),"ma",0);
4220 emitcode("push","ma");
4221 emitcode("push","ma");
4222 emitcode("push","ma");
4224 /* negate result if needed */
4225 lbl = newiTempLabel(NULL);
4226 emitcode("jnb","F0,%05d$",lbl->key+100);
4227 emitcode("cpl","a");
4228 emitcode("add","a,#1");
4229 emitcode("","%05d$:", lbl->key+100);
4230 if (AOP_TYPE(result) == AOP_ACC)
4232 D(emitcode(";", "ACC special case."););
4233 /* We know result is the only live aop, and
4234 * it's obviously not a DPTR2, so AP is available.
4236 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4240 aopPut(AOP(result),"a",0);
4243 emitcode("pop","acc");
4244 lbl = newiTempLabel(NULL);
4245 emitcode("jnb","F0,%05d$",lbl->key+100);
4246 emitcode("cpl","a");
4247 emitcode("addc","a,#0");
4248 emitcode("","%05d$:", lbl->key+100);
4249 aopPut(AOP(result),"a",1);
4250 emitcode("pop","acc");
4251 if (AOP_SIZE(result) >= 3) {
4252 lbl = newiTempLabel(NULL);
4253 emitcode("jnb","F0,%05d$",lbl->key+100);
4254 emitcode("cpl","a");
4255 emitcode("addc","a,#0");
4256 emitcode("","%05d$:", lbl->key+100);
4257 aopPut(AOP(result),"a",2);
4259 emitcode("pop","acc");
4260 if (AOP_SIZE(result) >= 4) {
4261 lbl = newiTempLabel(NULL);
4262 emitcode("jnb","F0,%05d$",lbl->key+100);
4263 emitcode("cpl","a");
4264 emitcode("addc","a,#0");
4265 emitcode("","%05d$:", lbl->key+100);
4266 aopPut(AOP(result),"a",3);
4268 if (AOP_TYPE(result) == AOP_ACC)
4270 /* We stashed the result away above. */
4271 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4275 freeAsmop (result, NULL, ic, TRUE);
4277 /* restore EA bit in F1 */
4278 lbl = newiTempLabel(NULL);
4279 emitcode ("jnb","F1,%05d$",lbl->key+100);
4280 emitcode ("setb","EA");
4281 emitcode("","%05d$:",lbl->key+100);
4285 /*-----------------------------------------------------------------*/
4286 /* genMult - generates code for multiplication */
4287 /*-----------------------------------------------------------------*/
4289 genMult (iCode * ic)
4291 operand *left = IC_LEFT (ic);
4292 operand *right = IC_RIGHT (ic);
4293 operand *result = IC_RESULT (ic);
4295 D (emitcode (";", "genMult "););
4297 /* assign the amsops */
4300 /* special cases first */
4302 if (AOP_TYPE (left) == AOP_CRY &&
4303 AOP_TYPE (right) == AOP_CRY)
4305 genMultbits (left, right, result, ic);
4309 /* if both are of size == 1 */
4310 if (AOP_SIZE (left) == 1 &&
4311 AOP_SIZE (right) == 1)
4313 genMultOneByte (left, right, result, ic);
4317 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4318 /* use the ds390 ARITHMETIC accel UNIT */
4319 genMultTwoByte (left, right, result, ic);
4322 /* should have been converted to function call */
4326 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4327 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4328 freeAsmop (result, NULL, ic, TRUE);
4331 /*-----------------------------------------------------------------*/
4332 /* genDivbits :- division of bits */
4333 /*-----------------------------------------------------------------*/
4335 genDivbits (operand * left,
4343 /* the result must be bit */
4344 LOAD_AB_FOR_DIV (left, right, l);
4345 emitcode ("div", "ab");
4346 emitcode ("rrc", "a");
4347 aopOp(result, ic, TRUE, FALSE);
4349 aopPut (AOP (result), "c", 0);
4352 /*-----------------------------------------------------------------*/
4353 /* genDivOneByte : 8 bit division */
4354 /*-----------------------------------------------------------------*/
4356 genDivOneByte (operand * left,
4361 sym_link *opetype = operandType (result);
4367 /* signed or unsigned */
4368 if (SPEC_USIGN (opetype))
4370 /* unsigned is easy */
4371 LOAD_AB_FOR_DIV (left, right, l);
4372 emitcode ("div", "ab");
4375 aopOp(result, ic, TRUE, FALSE);
4376 aopPut (AOP (result), "a", 0);
4379 size = AOP_SIZE (result) - 1;
4383 aopPut (AOP (result), zero, offset++);
4388 /* signed is a little bit more difficult */
4390 /* save the signs of the operands */
4391 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4393 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4394 emitcode ("push", "acc"); /* save it on the stack */
4396 /* now sign adjust for both left & right */
4397 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4399 lbl = newiTempLabel (NULL);
4400 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4401 emitcode ("cpl", "a");
4402 emitcode ("inc", "a");
4403 emitcode ("", "%05d$:", (lbl->key + 100));
4404 emitcode ("mov", "b,a");
4406 /* sign adjust left side */
4407 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4410 lbl = newiTempLabel (NULL);
4411 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4412 emitcode ("cpl", "a");
4413 emitcode ("inc", "a");
4414 emitcode ("", "%05d$:", (lbl->key + 100));
4416 /* now the division */
4417 emitcode ("nop", "; workaround for DS80C390 div bug.");
4418 emitcode ("div", "ab");
4419 /* we are interested in the lower order
4421 emitcode ("mov", "b,a");
4422 lbl = newiTempLabel (NULL);
4423 emitcode ("pop", "acc");
4424 /* if there was an over flow we don't
4425 adjust the sign of the result */
4426 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4427 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4429 emitcode ("clr", "a");
4430 emitcode ("subb", "a,b");
4431 emitcode ("mov", "b,a");
4432 emitcode ("", "%05d$:", (lbl->key + 100));
4434 /* now we are done */
4436 aopOp(result, ic, TRUE, FALSE);
4438 aopPut (AOP (result), "b", 0);
4440 size = AOP_SIZE (result) - 1;
4444 emitcode ("mov", "c,b.7");
4445 emitcode ("subb", "a,acc");
4449 aopPut (AOP (result), "a", offset++);
4455 /*-----------------------------------------------------------------*/
4456 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4457 /*-----------------------------------------------------------------*/
4458 static void genDivTwoByte (operand *left, operand *right,
4459 operand *result, iCode *ic)
4461 sym_link *retype = getSpec(operandType(right));
4462 sym_link *letype = getSpec(operandType(left));
4463 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4466 /* save EA bit in F1 */
4467 lbl = newiTempLabel(NULL);
4468 emitcode ("setb","F1");
4469 emitcode ("jbc","EA,%05d$",lbl->key+100);
4470 emitcode ("clr","F1");
4471 emitcode("","%05d$:",lbl->key+100);
4473 /* load up MA with left */
4475 emitcode("clr","F0");
4476 lbl = newiTempLabel(NULL);
4477 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4478 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4479 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4480 emitcode ("xch", "a,b");
4481 emitcode ("cpl","a");
4482 emitcode ("add", "a,#1");
4483 emitcode ("xch", "a,b");
4484 emitcode ("cpl", "a"); // msb
4485 emitcode ("addc","a,#0");
4486 emitcode ("setb","F0");
4487 emitcode ("","%05d$:",lbl->key+100);
4488 emitcode ("mov","ma,b");
4489 emitcode ("mov","ma,a");
4491 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4492 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4495 /* load up MB with right */
4497 if (AOP_TYPE(right) == AOP_LIT) {
4498 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4500 lbl = newiTempLabel(NULL);
4501 emitcode ("jbc","F0,%05d$",lbl->key+100);
4502 emitcode("setb","F0");
4503 emitcode ("","%05d$:",lbl->key+100);
4506 emitcode ("mov","mb,#0x%02x",val & 0xff);
4507 emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4509 lbl = newiTempLabel(NULL);
4510 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4511 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4512 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4513 emitcode ("xch", "a,b");
4514 emitcode ("cpl","a");
4515 emitcode ("add", "a,#1");
4516 emitcode ("xch", "a,b");
4517 emitcode ("cpl", "a"); // msb
4518 emitcode ("addc", "a,#0");
4519 emitcode ("jbc","F0,%05d$",lbl->key+100);
4520 emitcode ("setb","F0");
4521 emitcode ("","%05d$:",lbl->key+100);
4522 emitcode ("mov","mb,b");
4523 emitcode ("mov","mb,a");
4526 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4527 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4530 /* wait for multiplication to finish */
4531 lbl = newiTempLabel(NULL);
4532 emitcode("","%05d$:", lbl->key+100);
4533 emitcode("mov","a,mcnt1");
4534 emitcode("anl","a,#0x80");
4535 emitcode("jnz","%05d$",lbl->key+100);
4537 freeAsmop (left, NULL, ic, TRUE);
4538 freeAsmop (right, NULL, ic,TRUE);
4539 aopOp(result, ic, TRUE, FALSE);
4541 /* if unsigned then simple */
4543 aopPut(AOP(result),"ma",1);
4544 aopPut(AOP(result),"ma",0);
4546 emitcode("push","ma");
4548 /* negate result if needed */
4549 lbl = newiTempLabel(NULL);
4550 emitcode("jnb","F0,%05d$",lbl->key+100);
4551 emitcode("cpl","a");
4552 emitcode("add","a,#1");
4553 emitcode("","%05d$:", lbl->key+100);
4554 aopPut(AOP(result),"a",0);
4555 emitcode("pop","acc");
4556 lbl = newiTempLabel(NULL);
4557 emitcode("jnb","F0,%05d$",lbl->key+100);
4558 emitcode("cpl","a");
4559 emitcode("addc","a,#0");
4560 emitcode("","%05d$:", lbl->key+100);
4561 aopPut(AOP(result),"a",1);
4563 freeAsmop (result, NULL, ic, TRUE);
4564 /* restore EA bit in F1 */
4565 lbl = newiTempLabel(NULL);
4566 emitcode ("jnb","F1,%05d$",lbl->key+100);
4567 emitcode ("setb","EA");
4568 emitcode("","%05d$:",lbl->key+100);
4572 /*-----------------------------------------------------------------*/
4573 /* genDiv - generates code for division */
4574 /*-----------------------------------------------------------------*/
4578 operand *left = IC_LEFT (ic);
4579 operand *right = IC_RIGHT (ic);
4580 operand *result = IC_RESULT (ic);
4582 D (emitcode (";", "genDiv "););
4584 /* assign the amsops */
4587 /* special cases first */
4589 if (AOP_TYPE (left) == AOP_CRY &&
4590 AOP_TYPE (right) == AOP_CRY)
4592 genDivbits (left, right, result, ic);
4596 /* if both are of size == 1 */
4597 if (AOP_SIZE (left) == 1 &&
4598 AOP_SIZE (right) == 1)
4600 genDivOneByte (left, right, result, ic);
4604 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4605 /* use the ds390 ARITHMETIC accel UNIT */
4606 genDivTwoByte (left, right, result, ic);
4609 /* should have been converted to function call */
4612 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4613 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4614 freeAsmop (result, NULL, ic, TRUE);
4617 /*-----------------------------------------------------------------*/
4618 /* genModbits :- modulus of bits */
4619 /*-----------------------------------------------------------------*/
4621 genModbits (operand * left,
4629 /* the result must be bit */
4630 LOAD_AB_FOR_DIV (left, right, l);
4631 emitcode ("div", "ab");
4632 emitcode ("mov", "a,b");
4633 emitcode ("rrc", "a");
4634 aopOp(result, ic, TRUE, FALSE);
4635 aopPut (AOP (result), "c", 0);
4638 /*-----------------------------------------------------------------*/
4639 /* genModOneByte : 8 bit modulus */
4640 /*-----------------------------------------------------------------*/
4642 genModOneByte (operand * left,
4647 sym_link *opetype = operandType (result);
4651 /* signed or unsigned */
4652 if (SPEC_USIGN (opetype))
4654 /* unsigned is easy */
4655 LOAD_AB_FOR_DIV (left, right, l);
4656 emitcode ("div", "ab");
4657 aopOp(result, ic, TRUE, FALSE);
4658 aopPut (AOP (result), "b", 0);
4662 /* signed is a little bit more difficult */
4664 /* save the signs of the operands */
4665 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4668 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4669 emitcode ("push", "acc"); /* save it on the stack */
4671 /* now sign adjust for both left & right */
4672 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4675 lbl = newiTempLabel (NULL);
4676 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4677 emitcode ("cpl", "a");
4678 emitcode ("inc", "a");
4679 emitcode ("", "%05d$:", (lbl->key + 100));
4680 emitcode ("mov", "b,a");
4682 /* sign adjust left side */
4683 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4686 lbl = newiTempLabel (NULL);
4687 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4688 emitcode ("cpl", "a");
4689 emitcode ("inc", "a");
4690 emitcode ("", "%05d$:", (lbl->key + 100));
4692 /* now the multiplication */
4693 emitcode ("nop", "; workaround for DS80C390 div bug.");
4694 emitcode ("div", "ab");
4695 /* we are interested in the lower order
4697 lbl = newiTempLabel (NULL);
4698 emitcode ("pop", "acc");
4699 /* if there was an over flow we don't
4700 adjust the sign of the result */
4701 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4702 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4704 emitcode ("clr", "a");
4705 emitcode ("subb", "a,b");
4706 emitcode ("mov", "b,a");
4707 emitcode ("", "%05d$:", (lbl->key + 100));
4709 /* now we are done */
4710 aopOp(result, ic, TRUE, FALSE);
4711 aopPut (AOP (result), "b", 0);
4715 /*-----------------------------------------------------------------*/
4716 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
4717 /*-----------------------------------------------------------------*/
4718 static void genModTwoByte (operand *left, operand *right,
4719 operand *result, iCode *ic)
4721 sym_link *retype = getSpec(operandType(right));
4722 sym_link *letype = getSpec(operandType(left));
4723 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4726 /* load up MA with left */
4727 /* save EA bit in F1 */
4728 lbl = newiTempLabel(NULL);
4729 emitcode ("setb","F1");
4730 emitcode ("jbc","EA,%05d$",lbl->key+100);
4731 emitcode ("clr","F1");
4732 emitcode("","%05d$:",lbl->key+100);
4735 lbl = newiTempLabel(NULL);
4736 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4737 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4738 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4739 emitcode ("xch", "a,b");
4740 emitcode ("cpl","a");
4741 emitcode ("add", "a,#1");
4742 emitcode ("xch", "a,b");
4743 emitcode ("cpl", "a"); // msb
4744 emitcode ("addc","a,#0");
4745 emitcode ("","%05d$:",lbl->key+100);
4746 emitcode ("mov","ma,b");
4747 emitcode ("mov","ma,a");
4749 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4750 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4753 /* load up MB with right */
4755 if (AOP_TYPE(right) == AOP_LIT) {
4756 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4760 emitcode ("mov","mb,#0x%02x",val & 0xff);
4761 emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4763 lbl = newiTempLabel(NULL);
4764 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4765 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4766 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4767 emitcode ("xch", "a,b");
4768 emitcode ("cpl","a");
4769 emitcode ("add", "a,#1");
4770 emitcode ("xch", "a,b");
4771 emitcode ("cpl", "a"); // msb
4772 emitcode ("addc", "a,#0");
4773 emitcode ("","%05d$:",lbl->key+100);
4774 emitcode ("mov","mb,b");
4775 emitcode ("mov","mb,a");
4778 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4779 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4782 /* wait for multiplication to finish */
4783 lbl = newiTempLabel(NULL);
4784 emitcode("","%05d$:", lbl->key+100);
4785 emitcode("mov","a,mcnt1");
4786 emitcode("anl","a,#0x80");
4787 emitcode("jnz","%05d$",lbl->key+100);
4789 freeAsmop (left, NULL, ic, TRUE);
4790 freeAsmop (right, NULL, ic,TRUE);
4791 aopOp(result, ic, TRUE, FALSE);
4793 aopPut(AOP(result),"mb",1);
4794 aopPut(AOP(result),"mb",0);
4795 freeAsmop (result, NULL, ic, TRUE);
4797 /* restore EA bit in F1 */
4798 lbl = newiTempLabel(NULL);
4799 emitcode ("jnb","F1,%05d$",lbl->key+100);
4800 emitcode ("setb","EA");
4801 emitcode("","%05d$:",lbl->key+100);
4805 /*-----------------------------------------------------------------*/
4806 /* genMod - generates code for division */
4807 /*-----------------------------------------------------------------*/
4811 operand *left = IC_LEFT (ic);
4812 operand *right = IC_RIGHT (ic);
4813 operand *result = IC_RESULT (ic);
4815 D (emitcode (";", "genMod "); );
4817 /* assign the amsops */
4820 /* special cases first */
4822 if (AOP_TYPE (left) == AOP_CRY &&
4823 AOP_TYPE (right) == AOP_CRY)
4825 genModbits (left, right, result, ic);
4829 /* if both are of size == 1 */
4830 if (AOP_SIZE (left) == 1 &&
4831 AOP_SIZE (right) == 1)
4833 genModOneByte (left, right, result, ic);
4837 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4838 /* use the ds390 ARITHMETIC accel UNIT */
4839 genModTwoByte (left, right, result, ic);
4843 /* should have been converted to function call */
4847 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4848 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4849 freeAsmop (result, NULL, ic, TRUE);
4852 /*-----------------------------------------------------------------*/
4853 /* genIfxJump :- will create a jump depending on the ifx */
4854 /*-----------------------------------------------------------------*/
4856 genIfxJump (iCode * ic, char *jval)
4859 symbol *tlbl = newiTempLabel (NULL);
4862 D (emitcode (";", "genIfxJump ");
4865 /* if true label then we jump if condition
4869 jlbl = IC_TRUE (ic);
4870 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4871 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4875 /* false label is present */
4876 jlbl = IC_FALSE (ic);
4877 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4878 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4880 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4881 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4883 emitcode (inst, "%05d$", tlbl->key + 100);
4884 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4885 emitcode ("", "%05d$:", tlbl->key + 100);
4887 /* mark the icode as generated */
4891 /*-----------------------------------------------------------------*/
4892 /* genCmp :- greater or less than comparison */
4893 /*-----------------------------------------------------------------*/
4895 genCmp (operand * left, operand * right,
4896 iCode * ic, iCode * ifx, int sign)
4898 int size, offset = 0;
4899 unsigned long lit = 0L;
4902 D (emitcode (";", "genCmp");
4905 result = IC_RESULT (ic);
4907 /* if left & right are bit variables */
4908 if (AOP_TYPE (left) == AOP_CRY &&
4909 AOP_TYPE (right) == AOP_CRY)
4911 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4912 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4916 /* subtract right from left if at the
4917 end the carry flag is set then we know that
4918 left is greater than right */
4919 size = max (AOP_SIZE (left), AOP_SIZE (right));
4921 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4922 if ((size == 1) && !sign &&
4923 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4925 symbol *lbl = newiTempLabel (NULL);
4926 emitcode ("cjne", "%s,%s,%05d$",
4927 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4928 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4930 emitcode ("", "%05d$:", lbl->key + 100);
4934 if (AOP_TYPE (right) == AOP_LIT)
4936 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4937 /* optimize if(x < 0) or if(x >= 0) */
4946 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4948 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4949 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4951 aopOp (result, ic, FALSE, FALSE);
4953 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4955 freeAsmop (result, NULL, ic, TRUE);
4956 genIfxJump (ifx, "acc.7");
4961 emitcode ("rlc", "a");
4963 goto release_freedLR;
4971 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4972 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4973 emitcode (";", "genCmp #2");
4974 if (sign && (size == 0))
4976 emitcode (";", "genCmp #3");
4977 emitcode ("xrl", "a,#0x80");
4978 if (AOP_TYPE (right) == AOP_LIT)
4980 unsigned long lit = (unsigned long)
4981 floatFromVal (AOP (right)->aopu.aop_lit);
4982 emitcode (";", "genCmp #3.1");
4983 emitcode ("subb", "a,#0x%02x",
4984 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4988 emitcode (";", "genCmp #3.2");
4989 if (AOP_NEEDSACC (right))
4991 emitcode ("push", "acc");
4993 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4994 FALSE, FALSE, FALSE));
4995 emitcode ("xrl", "b,#0x80");
4996 if (AOP_NEEDSACC (right))
4998 emitcode ("pop", "acc");
5000 emitcode ("subb", "a,b");
5007 emitcode (";", "genCmp #4");
5008 if (AOP_NEEDSACC (right))
5011 emitcode (";", "genCmp #4.1");
5012 emitcode ("xch", "a, b");
5013 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
5014 emitcode ("xch", "a, b");
5019 emitcode (";", "genCmp #4.2");
5020 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
5023 emitcode ("subb", "a,%s", s);
5030 /* Don't need the left & right operands any more; do need the result. */
5031 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5032 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5034 aopOp (result, ic, FALSE, FALSE);
5038 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5044 /* if the result is used in the next
5045 ifx conditional branch then generate
5046 code a little differently */
5049 genIfxJump (ifx, "c");
5055 /* leave the result in acc */
5057 freeAsmop (result, NULL, ic, TRUE);
5060 /*-----------------------------------------------------------------*/
5061 /* genCmpGt :- greater than comparison */
5062 /*-----------------------------------------------------------------*/
5064 genCmpGt (iCode * ic, iCode * ifx)
5066 operand *left, *right;
5067 sym_link *letype, *retype;
5070 D (emitcode (";", "genCmpGt ");
5073 left = IC_LEFT (ic);
5074 right = IC_RIGHT (ic);
5076 letype = getSpec (operandType (left));
5077 retype = getSpec (operandType (right));
5078 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5080 /* assign the left & right amsops */
5083 genCmp (right, left, ic, ifx, sign);
5086 /*-----------------------------------------------------------------*/
5087 /* genCmpLt - less than comparisons */
5088 /*-----------------------------------------------------------------*/
5090 genCmpLt (iCode * ic, iCode * ifx)
5092 operand *left, *right;
5093 sym_link *letype, *retype;
5096 D (emitcode (";", "genCmpLt "););
5098 left = IC_LEFT (ic);
5099 right = IC_RIGHT (ic);
5101 letype = getSpec (operandType (left));
5102 retype = getSpec (operandType (right));
5103 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5105 /* assign the left & right amsops */
5108 genCmp (left, right, ic, ifx, sign);
5111 /*-----------------------------------------------------------------*/
5112 /* gencjneshort - compare and jump if not equal */
5113 /*-----------------------------------------------------------------*/
5115 gencjneshort (operand * left, operand * right, symbol * lbl)
5117 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5119 unsigned long lit = 0L;
5121 D (emitcode (";", "gencjneshort");
5124 /* if the left side is a literal or
5125 if the right is in a pointer register and left
5127 if ((AOP_TYPE (left) == AOP_LIT) ||
5128 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5135 if (AOP_TYPE (right) == AOP_LIT)
5136 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5138 if (opIsGptr (left) || opIsGptr (right))
5140 /* We are comparing a generic pointer to something.
5141 * Exclude the generic type byte from the comparison.
5144 D (emitcode (";", "cjneshort: generic ptr special case.");
5149 /* if the right side is a literal then anything goes */
5150 if (AOP_TYPE (right) == AOP_LIT &&
5151 AOP_TYPE (left) != AOP_DIR)
5155 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5157 emitcode ("cjne", "a,%s,%05d$",
5158 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5164 /* if the right side is in a register or in direct space or
5165 if the left is a pointer register & right is not */
5166 else if (AOP_TYPE (right) == AOP_REG ||
5167 AOP_TYPE (right) == AOP_DIR ||
5168 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5169 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5173 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5174 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5175 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5176 emitcode ("jnz", "%05d$", lbl->key + 100);
5178 emitcode ("cjne", "a,%s,%05d$",
5179 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5186 /* right is a pointer reg need both a & b */
5189 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5190 if (strcmp (l, "b"))
5191 emitcode ("mov", "b,%s", l);
5192 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5193 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5199 /*-----------------------------------------------------------------*/
5200 /* gencjne - compare and jump if not equal */
5201 /*-----------------------------------------------------------------*/
5203 gencjne (operand * left, operand * right, symbol * lbl)
5205 symbol *tlbl = newiTempLabel (NULL);
5207 D (emitcode (";", "gencjne");
5210 gencjneshort (left, right, lbl);
5212 emitcode ("mov", "a,%s", one);
5213 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5214 emitcode ("", "%05d$:", lbl->key + 100);
5215 emitcode ("clr", "a");
5216 emitcode ("", "%05d$:", tlbl->key + 100);
5219 /*-----------------------------------------------------------------*/
5220 /* genCmpEq - generates code for equal to */
5221 /*-----------------------------------------------------------------*/
5223 genCmpEq (iCode * ic, iCode * ifx)
5225 operand *left, *right, *result;
5227 D (emitcode (";", "genCmpEq ");
5231 AOP_SET_LOCALS (ic);
5233 /* if literal, literal on the right or
5234 if the right is in a pointer register and left
5236 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5237 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5239 operand *t = IC_RIGHT (ic);
5240 IC_RIGHT (ic) = IC_LEFT (ic);
5244 if (ifx && /* !AOP_SIZE(result) */
5245 OP_SYMBOL (result) &&
5246 OP_SYMBOL (result)->regType == REG_CND)
5249 /* if they are both bit variables */
5250 if (AOP_TYPE (left) == AOP_CRY &&
5251 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5253 if (AOP_TYPE (right) == AOP_LIT)
5255 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5258 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5259 emitcode ("cpl", "c");
5263 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5267 emitcode ("clr", "c");
5269 /* AOP_TYPE(right) == AOP_CRY */
5273 symbol *lbl = newiTempLabel (NULL);
5274 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5275 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5276 emitcode ("cpl", "c");
5277 emitcode ("", "%05d$:", (lbl->key + 100));
5279 /* if true label then we jump if condition
5281 tlbl = newiTempLabel (NULL);
5284 emitcode ("jnc", "%05d$", tlbl->key + 100);
5285 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5289 emitcode ("jc", "%05d$", tlbl->key + 100);
5290 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5292 emitcode ("", "%05d$:", tlbl->key + 100);
5296 tlbl = newiTempLabel (NULL);
5297 gencjneshort (left, right, tlbl);
5300 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5301 emitcode ("", "%05d$:", tlbl->key + 100);
5305 symbol *lbl = newiTempLabel (NULL);
5306 emitcode ("sjmp", "%05d$", lbl->key + 100);
5307 emitcode ("", "%05d$:", tlbl->key + 100);
5308 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5309 emitcode ("", "%05d$:", lbl->key + 100);
5312 /* mark the icode as generated */
5315 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5316 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5320 /* if they are both bit variables */
5321 if (AOP_TYPE (left) == AOP_CRY &&
5322 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5324 if (AOP_TYPE (right) == AOP_LIT)
5326 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5329 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5330 emitcode ("cpl", "c");
5334 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5338 emitcode ("clr", "c");
5340 /* AOP_TYPE(right) == AOP_CRY */
5344 symbol *lbl = newiTempLabel (NULL);
5345 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5346 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5347 emitcode ("cpl", "c");
5348 emitcode ("", "%05d$:", (lbl->key + 100));
5351 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5352 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5354 aopOp (result, ic, TRUE, FALSE);
5357 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5364 genIfxJump (ifx, "c");
5367 /* if the result is used in an arithmetic operation
5368 then put the result in place */
5373 gencjne (left, right, newiTempLabel (NULL));
5375 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5376 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5378 aopOp (result, ic, TRUE, FALSE);
5380 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5382 aopPut (AOP (result), "a", 0);
5387 genIfxJump (ifx, "a");
5390 /* if the result is used in an arithmetic operation
5391 then put the result in place */
5392 if (AOP_TYPE (result) != AOP_CRY)
5394 /* leave the result in acc */
5398 freeAsmop (result, NULL, ic, TRUE);
5401 /*-----------------------------------------------------------------*/
5402 /* ifxForOp - returns the icode containing the ifx for operand */
5403 /*-----------------------------------------------------------------*/
5405 ifxForOp (operand * op, iCode * ic)
5407 /* if true symbol then needs to be assigned */
5408 if (IS_TRUE_SYMOP (op))
5411 /* if this has register type condition and
5412 the next instruction is ifx with the same operand
5413 and live to of the operand is upto the ifx only then */
5415 ic->next->op == IFX &&
5416 IC_COND (ic->next)->key == op->key &&
5417 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5422 /*-----------------------------------------------------------------*/
5423 /* hasInc - operand is incremented before any other use */
5424 /*-----------------------------------------------------------------*/
5426 hasInc (operand *op, iCode *ic)
5428 sym_link *type = operandType(op);
5429 sym_link *retype = getSpec (type);
5430 iCode *lic = ic->next;
5433 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5434 if (!IS_SYMOP(op)) return NULL;
5436 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5437 isize = getSize(type->next);
5439 /* if operand of the form op = op + <sizeof *op> */
5440 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5441 isOperandEqual(IC_RESULT(lic),op) &&
5442 isOperandLiteral(IC_RIGHT(lic)) &&
5443 operandLitValue(IC_RIGHT(lic)) == isize) {
5446 /* if the operand used or deffed */
5447 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5450 /* if GOTO or IFX */
5451 if (lic->op == IFX || lic->op == GOTO) break;
5457 /*-----------------------------------------------------------------*/
5458 /* genAndOp - for && operation */
5459 /*-----------------------------------------------------------------*/
5461 genAndOp (iCode * ic)
5463 operand *left, *right, *result;
5466 D (emitcode (";", "genAndOp "););
5468 /* note here that && operations that are in an
5469 if statement are taken away by backPatchLabels
5470 only those used in arthmetic operations remain */
5472 AOP_SET_LOCALS (ic);
5474 /* if both are bit variables */
5475 if (AOP_TYPE (left) == AOP_CRY &&
5476 AOP_TYPE (right) == AOP_CRY)
5478 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5479 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5480 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5481 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5483 aopOp (result,ic,FALSE, FALSE);
5488 tlbl = newiTempLabel (NULL);
5490 emitcode ("jz", "%05d$", tlbl->key + 100);
5492 emitcode ("", "%05d$:", tlbl->key + 100);
5493 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5494 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5496 aopOp (result,ic,FALSE, FALSE);
5499 freeAsmop (result, NULL, ic, TRUE);
5503 /*-----------------------------------------------------------------*/
5504 /* genOrOp - for || operation */
5505 /*-----------------------------------------------------------------*/
5507 genOrOp (iCode * ic)
5509 operand *left, *right, *result;
5512 D (emitcode (";", "genOrOp "););
5514 /* note here that || operations that are in an
5515 if statement are taken away by backPatchLabels
5516 only those used in arthmetic operations remain */
5518 AOP_SET_LOCALS (ic);
5520 /* if both are bit variables */
5521 if (AOP_TYPE (left) == AOP_CRY &&
5522 AOP_TYPE (right) == AOP_CRY)
5524 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5525 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5526 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5527 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5529 aopOp (result,ic,FALSE, FALSE);
5535 tlbl = newiTempLabel (NULL);
5537 emitcode ("jnz", "%05d$", tlbl->key + 100);
5539 emitcode ("", "%05d$:", tlbl->key + 100);
5540 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5541 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5543 aopOp (result,ic,FALSE, FALSE);
5548 freeAsmop (result, NULL, ic, TRUE);
5551 /*-----------------------------------------------------------------*/
5552 /* isLiteralBit - test if lit == 2^n */
5553 /*-----------------------------------------------------------------*/
5555 isLiteralBit (unsigned long lit)
5557 unsigned long pw[32] =
5558 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5559 0x100L, 0x200L, 0x400L, 0x800L,
5560 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5561 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5562 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5563 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5564 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5567 for (idx = 0; idx < 32; idx++)
5573 /*-----------------------------------------------------------------*/
5574 /* continueIfTrue - */
5575 /*-----------------------------------------------------------------*/
5577 continueIfTrue (iCode * ic)
5580 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5584 /*-----------------------------------------------------------------*/
5586 /*-----------------------------------------------------------------*/
5588 jumpIfTrue (iCode * ic)
5591 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5595 /*-----------------------------------------------------------------*/
5596 /* jmpTrueOrFalse - */
5597 /*-----------------------------------------------------------------*/
5599 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5601 // ugly but optimized by peephole
5604 symbol *nlbl = newiTempLabel (NULL);
5605 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5606 emitcode ("", "%05d$:", tlbl->key + 100);
5607 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5608 emitcode ("", "%05d$:", nlbl->key + 100);
5612 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5613 emitcode ("", "%05d$:", tlbl->key + 100);
5618 // Generate code to perform a bit-wise logic operation
5619 // on two operands in far space (assumed to already have been
5620 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5621 // in far space. This requires pushing the result on the stack
5622 // then popping it into the result.
5624 genFarFarLogicOp(iCode *ic, char *logicOp)
5626 int size, resultSize, compSize;
5630 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5631 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5632 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5634 _startLazyDPSEvaluation();
5635 for (size = compSize; (size--); offset++)
5637 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5638 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5639 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5641 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5642 emitcode ("push", "acc");
5644 _endLazyDPSEvaluation();
5646 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5647 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5648 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5650 resultSize = AOP_SIZE(IC_RESULT(ic));
5652 ADJUST_PUSHED_RESULT(compSize, resultSize);
5654 _startLazyDPSEvaluation();
5657 emitcode ("pop", "acc");
5658 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5660 _endLazyDPSEvaluation();
5661 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5665 /*-----------------------------------------------------------------*/
5666 /* genAnd - code for and */
5667 /*-----------------------------------------------------------------*/
5669 genAnd (iCode * ic, iCode * ifx)
5671 operand *left, *right, *result;
5672 int size, offset = 0;
5673 unsigned long lit = 0L;
5678 D (emitcode (";", "genAnd "););
5680 AOP_OP_3_NOFATAL (ic, pushResult);
5681 AOP_SET_LOCALS (ic);
5685 genFarFarLogicOp(ic, "anl");
5690 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5692 AOP_TYPE (left), AOP_TYPE (right));
5693 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5695 AOP_SIZE (left), AOP_SIZE (right));
5698 /* if left is a literal & right is not then exchange them */
5699 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5700 #ifdef LOGIC_OPS_BROKEN
5701 || AOP_NEEDSACC (left)
5705 operand *tmp = right;
5710 /* if result = right then exchange them */
5711 if (sameRegs (AOP (result), AOP (right)))
5713 operand *tmp = right;
5718 /* if right is bit then exchange them */
5719 if (AOP_TYPE (right) == AOP_CRY &&
5720 AOP_TYPE (left) != AOP_CRY)
5722 operand *tmp = right;
5726 if (AOP_TYPE (right) == AOP_LIT)
5727 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5729 size = AOP_SIZE (result);
5732 // result = bit & yy;
5733 if (AOP_TYPE (left) == AOP_CRY)
5735 // c = bit & literal;
5736 if (AOP_TYPE (right) == AOP_LIT)
5740 if (size && sameRegs (AOP (result), AOP (left)))
5743 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5748 if (size && (AOP_TYPE (result) == AOP_CRY))
5750 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5753 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5758 emitcode ("clr", "c");
5763 if (AOP_TYPE (right) == AOP_CRY)
5766 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5767 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5772 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5774 emitcode ("rrc", "a");
5775 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5783 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5784 genIfxJump (ifx, "c");
5788 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5789 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5790 if ((AOP_TYPE (right) == AOP_LIT) &&
5791 (AOP_TYPE (result) == AOP_CRY) &&
5792 (AOP_TYPE (left) != AOP_CRY))
5794 int posbit = isLiteralBit (lit);
5799 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5802 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5808 sprintf (buffer, "acc.%d", posbit & 0x07);
5809 genIfxJump (ifx, buffer);
5816 symbol *tlbl = newiTempLabel (NULL);
5817 int sizel = AOP_SIZE (left);
5819 emitcode ("setb", "c");
5822 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5824 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5826 if ((posbit = isLiteralBit (bytelit)) != 0)
5827 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5830 if (bytelit != 0x0FFL)
5831 emitcode ("anl", "a,%s",
5832 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5833 emitcode ("jnz", "%05d$", tlbl->key + 100);
5838 // bit = left & literal
5841 emitcode ("clr", "c");
5842 emitcode ("", "%05d$:", tlbl->key + 100);
5844 // if(left & literal)
5848 jmpTrueOrFalse (ifx, tlbl);
5856 /* if left is same as result */
5857 if (sameRegs (AOP (result), AOP (left)))
5859 for (; size--; offset++)
5861 if (AOP_TYPE (right) == AOP_LIT)
5863 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5865 else if (bytelit == 0)
5866 aopPut (AOP (result), zero, offset);
5867 else if (IS_AOP_PREG (result))
5869 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5870 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5871 aopPut (AOP (result), "a", offset);
5874 emitcode ("anl", "%s,%s",
5875 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5876 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5880 if (AOP_TYPE (left) == AOP_ACC)
5881 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5884 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5885 if (IS_AOP_PREG (result))
5887 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5888 aopPut (AOP (result), "a", offset);
5892 emitcode ("anl", "%s,a",
5893 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5900 // left & result in different registers
5901 if (AOP_TYPE (result) == AOP_CRY)
5904 // if(size), result in bit
5905 // if(!size && ifx), conditional oper: if(left & right)
5906 symbol *tlbl = newiTempLabel (NULL);
5907 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5909 emitcode ("setb", "c");
5912 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5913 emitcode ("anl", "a,%s",
5914 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5916 if (AOP_TYPE(left)==AOP_ACC) {
5917 emitcode("mov", "b,a");
5918 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5919 emitcode("anl", "a,b");
5921 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5922 emitcode ("anl", "a,%s",
5923 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5926 emitcode ("jnz", "%05d$", tlbl->key + 100);
5932 emitcode ("", "%05d$:", tlbl->key + 100);
5936 jmpTrueOrFalse (ifx, tlbl);
5940 for (; (size--); offset++)
5943 // result = left & right
5944 if (AOP_TYPE (right) == AOP_LIT)
5946 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5948 aopPut (AOP (result),
5949 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5953 else if (bytelit == 0)
5955 aopPut (AOP (result), zero, offset);
5958 D (emitcode (";", "better literal AND."););
5959 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5960 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5961 FALSE, FALSE, FALSE));
5966 // faster than result <- left, anl result,right
5967 // and better if result is SFR
5968 if (AOP_TYPE (left) == AOP_ACC)
5970 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5971 FALSE, FALSE, FALSE));
5975 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
5976 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
5978 emitcode("mov", "b,a");
5982 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5983 emitcode ("anl", "a,%s", rOp);
5986 aopPut (AOP (result), "a", offset);
5992 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5993 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5994 freeAsmop (result, NULL, ic, TRUE);
5998 /*-----------------------------------------------------------------*/
5999 /* genOr - code for or */
6000 /*-----------------------------------------------------------------*/
6002 genOr (iCode * ic, iCode * ifx)
6004 operand *left, *right, *result;
6005 int size, offset = 0;
6006 unsigned long lit = 0L;
6009 D (emitcode (";", "genOr "););
6011 AOP_OP_3_NOFATAL (ic, pushResult);
6012 AOP_SET_LOCALS (ic);
6016 genFarFarLogicOp(ic, "orl");
6022 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6024 AOP_TYPE (left), AOP_TYPE (right));
6025 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6027 AOP_SIZE (left), AOP_SIZE (right));
6030 /* if left is a literal & right is not then exchange them */
6031 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6032 #ifdef LOGIC_OPS_BROKEN
6033 || AOP_NEEDSACC (left) // I think this is a net loss now.
6037 operand *tmp = right;
6042 /* if result = right then exchange them */
6043 if (sameRegs (AOP (result), AOP (right)))
6045 operand *tmp = right;
6050 /* if right is bit then exchange them */
6051 if (AOP_TYPE (right) == AOP_CRY &&
6052 AOP_TYPE (left) != AOP_CRY)
6054 operand *tmp = right;
6058 if (AOP_TYPE (right) == AOP_LIT)
6059 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6061 size = AOP_SIZE (result);
6065 if (AOP_TYPE (left) == AOP_CRY)
6067 if (AOP_TYPE (right) == AOP_LIT)
6069 // c = bit & literal;
6072 // lit != 0 => result = 1
6073 if (AOP_TYPE (result) == AOP_CRY)
6076 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6078 continueIfTrue (ifx);
6081 emitcode ("setb", "c");
6085 // lit == 0 => result = left
6086 if (size && sameRegs (AOP (result), AOP (left)))
6088 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6093 if (AOP_TYPE (right) == AOP_CRY)
6096 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6097 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6102 symbol *tlbl = newiTempLabel (NULL);
6103 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6104 emitcode ("setb", "c");
6105 emitcode ("jb", "%s,%05d$",
6106 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6108 emitcode ("jnz", "%05d$", tlbl->key + 100);
6109 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6111 jmpTrueOrFalse (ifx, tlbl);
6117 emitcode ("", "%05d$:", tlbl->key + 100);
6126 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6127 genIfxJump (ifx, "c");
6131 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6132 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6133 if ((AOP_TYPE (right) == AOP_LIT) &&
6134 (AOP_TYPE (result) == AOP_CRY) &&
6135 (AOP_TYPE (left) != AOP_CRY))
6141 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6143 continueIfTrue (ifx);
6148 // lit = 0, result = boolean(left)
6150 emitcode ("setb", "c");
6154 symbol *tlbl = newiTempLabel (NULL);
6155 emitcode ("jnz", "%05d$", tlbl->key + 100);
6157 emitcode ("", "%05d$:", tlbl->key + 100);
6161 genIfxJump (ifx, "a");
6169 /* if left is same as result */
6170 if (sameRegs (AOP (result), AOP (left)))
6172 for (; size--; offset++)
6174 if (AOP_TYPE (right) == AOP_LIT)
6176 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6182 if (IS_AOP_PREG (left))
6184 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6185 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6186 aopPut (AOP (result), "a", offset);
6190 emitcode ("orl", "%s,%s",
6191 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6192 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6198 if (AOP_TYPE (left) == AOP_ACC)
6200 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6204 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6205 if (IS_AOP_PREG (left))
6207 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6208 aopPut (AOP (result), "a", offset);
6212 emitcode ("orl", "%s,a",
6213 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6221 // left & result in different registers
6222 if (AOP_TYPE (result) == AOP_CRY)
6225 // if(size), result in bit
6226 // if(!size && ifx), conditional oper: if(left | right)
6227 symbol *tlbl = newiTempLabel (NULL);
6228 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6230 emitcode ("setb", "c");
6233 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6234 emitcode ("orl", "a,%s",
6235 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6237 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6238 emitcode ("orl", "a,%s",
6239 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6241 emitcode ("jnz", "%05d$", tlbl->key + 100);
6247 emitcode ("", "%05d$:", tlbl->key + 100);
6251 jmpTrueOrFalse (ifx, tlbl);
6255 _startLazyDPSEvaluation();
6256 for (; (size--); offset++)
6259 // result = left & right
6260 if (AOP_TYPE (right) == AOP_LIT)
6262 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6264 aopPut (AOP (result),
6265 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6269 D (emitcode (";", "better literal OR."););
6270 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6271 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6272 FALSE, FALSE, FALSE));
6277 // faster than result <- left, anl result,right
6278 // and better if result is SFR
6279 if (AOP_TYPE (left) == AOP_ACC)
6281 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6282 FALSE, FALSE, FALSE));
6286 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6288 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6290 emitcode("mov", "b,a");
6294 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6295 emitcode ("orl", "a,%s", rOp);
6298 aopPut (AOP (result), "a", offset);
6300 _endLazyDPSEvaluation();
6305 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6306 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6307 freeAsmop (result, NULL, ic, TRUE);
6310 /*-----------------------------------------------------------------*/
6311 /* genXor - code for xclusive or */
6312 /*-----------------------------------------------------------------*/
6314 genXor (iCode * ic, iCode * ifx)
6316 operand *left, *right, *result;
6317 int size, offset = 0;
6318 unsigned long lit = 0L;
6321 D (emitcode (";", "genXor "););
6323 AOP_OP_3_NOFATAL (ic, pushResult);
6324 AOP_SET_LOCALS (ic);
6328 genFarFarLogicOp(ic, "xrl");
6333 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6335 AOP_TYPE (left), AOP_TYPE (right));
6336 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6338 AOP_SIZE (left), AOP_SIZE (right));
6341 /* if left is a literal & right is not ||
6342 if left needs acc & right does not */
6343 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6344 #ifdef LOGIC_OPS_BROKEN
6345 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6349 operand *tmp = right;
6354 /* if result = right then exchange them */
6355 if (sameRegs (AOP (result), AOP (right)))
6357 operand *tmp = right;
6362 /* if right is bit then exchange them */
6363 if (AOP_TYPE (right) == AOP_CRY &&
6364 AOP_TYPE (left) != AOP_CRY)
6366 operand *tmp = right;
6370 if (AOP_TYPE (right) == AOP_LIT)
6371 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6373 size = AOP_SIZE (result);
6377 if (AOP_TYPE (left) == AOP_CRY)
6379 if (AOP_TYPE (right) == AOP_LIT)
6381 // c = bit & literal;
6384 // lit>>1 != 0 => result = 1
6385 if (AOP_TYPE (result) == AOP_CRY)
6388 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6390 continueIfTrue (ifx);
6393 emitcode ("setb", "c");
6400 // lit == 0, result = left
6401 if (size && sameRegs (AOP (result), AOP (left)))
6403 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6407 // lit == 1, result = not(left)
6408 if (size && sameRegs (AOP (result), AOP (left)))
6410 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6415 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6416 emitcode ("cpl", "c");
6425 symbol *tlbl = newiTempLabel (NULL);
6426 if (AOP_TYPE (right) == AOP_CRY)
6429 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6433 int sizer = AOP_SIZE (right);
6435 // if val>>1 != 0, result = 1
6436 emitcode ("setb", "c");
6439 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6441 // test the msb of the lsb
6442 emitcode ("anl", "a,#0xfe");
6443 emitcode ("jnz", "%05d$", tlbl->key + 100);
6447 emitcode ("rrc", "a");
6449 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6450 emitcode ("cpl", "c");
6451 emitcode ("", "%05d$:", (tlbl->key + 100));
6458 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6459 genIfxJump (ifx, "c");
6463 if (sameRegs (AOP (result), AOP (left)))
6465 /* if left is same as result */
6466 for (; size--; offset++)
6468 if (AOP_TYPE (right) == AOP_LIT)
6470 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6472 else if (IS_AOP_PREG (left))
6474 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6475 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6476 aopPut (AOP (result), "a", offset);
6479 emitcode ("xrl", "%s,%s",
6480 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6481 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6485 if (AOP_TYPE (left) == AOP_ACC)
6486 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6489 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6490 if (IS_AOP_PREG (left))
6492 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6493 aopPut (AOP (result), "a", offset);
6496 emitcode ("xrl", "%s,a",
6497 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6504 // left & result in different registers
6505 if (AOP_TYPE (result) == AOP_CRY)
6508 // if(size), result in bit
6509 // if(!size && ifx), conditional oper: if(left ^ right)
6510 symbol *tlbl = newiTempLabel (NULL);
6511 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6513 emitcode ("setb", "c");
6516 if ((AOP_TYPE (right) == AOP_LIT) &&
6517 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6519 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6523 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6524 emitcode ("xrl", "a,%s",
6525 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6527 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6528 emitcode ("xrl", "a,%s",
6529 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6532 emitcode ("jnz", "%05d$", tlbl->key + 100);
6538 emitcode ("", "%05d$:", tlbl->key + 100);
6542 jmpTrueOrFalse (ifx, tlbl);
6545 for (; (size--); offset++)
6548 // result = left & right
6549 if (AOP_TYPE (right) == AOP_LIT)
6551 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6553 aopPut (AOP (result),
6554 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6558 D (emitcode (";", "better literal XOR.");
6560 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6561 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6562 FALSE, FALSE, FALSE));
6566 // faster than result <- left, anl result,right
6567 // and better if result is SFR
6568 if (AOP_TYPE (left) == AOP_ACC)
6570 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6571 FALSE, FALSE, FALSE));
6575 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6576 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6578 emitcode("mov", "b,a");
6582 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6583 emitcode ("xrl", "a,%s", rOp);
6586 aopPut (AOP (result), "a", offset);
6591 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6592 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6593 freeAsmop (result, NULL, ic, TRUE);
6596 /*-----------------------------------------------------------------*/
6597 /* genInline - write the inline code out */
6598 /*-----------------------------------------------------------------*/
6600 genInline (iCode * ic)
6602 char *buffer, *bp, *bp1;
6604 D (emitcode (";", "genInline ");
6607 _G.inLine += (!options.asmpeep);
6609 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6610 strcpy (buffer, IC_INLINE (ic));
6612 /* emit each line as a code */
6637 /* emitcode("",buffer); */
6638 _G.inLine -= (!options.asmpeep);
6641 /*-----------------------------------------------------------------*/
6642 /* genRRC - rotate right with carry */
6643 /*-----------------------------------------------------------------*/
6647 operand *left, *result;
6648 int size, offset = 0;
6651 D (emitcode (";", "genRRC ");
6654 /* rotate right with carry */
6655 left = IC_LEFT (ic);
6656 result = IC_RESULT (ic);
6657 aopOp (left, ic, FALSE, FALSE);
6658 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6660 /* move it to the result */
6661 size = AOP_SIZE (result);
6665 _startLazyDPSEvaluation ();
6668 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6670 emitcode ("rrc", "a");
6671 if (AOP_SIZE (result) > 1)
6672 aopPut (AOP (result), "a", offset--);
6674 _endLazyDPSEvaluation ();
6676 /* now we need to put the carry into the
6677 highest order byte of the result */
6678 if (AOP_SIZE (result) > 1)
6680 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6683 emitcode ("mov", "acc.7,c");
6684 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6685 freeAsmop (left, NULL, ic, TRUE);
6686 freeAsmop (result, NULL, ic, TRUE);
6689 /*-----------------------------------------------------------------*/
6690 /* genRLC - generate code for rotate left with carry */
6691 /*-----------------------------------------------------------------*/
6695 operand *left, *result;
6696 int size, offset = 0;
6699 D (emitcode (";", "genRLC ");
6702 /* rotate right with carry */
6703 left = IC_LEFT (ic);
6704 result = IC_RESULT (ic);
6705 aopOp (left, ic, FALSE, FALSE);
6706 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6708 /* move it to the result */
6709 size = AOP_SIZE (result);
6713 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6715 emitcode ("add", "a,acc");
6716 if (AOP_SIZE (result) > 1)
6718 aopPut (AOP (result), "a", offset++);
6721 _startLazyDPSEvaluation ();
6724 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6726 emitcode ("rlc", "a");
6727 if (AOP_SIZE (result) > 1)
6728 aopPut (AOP (result), "a", offset++);
6730 _endLazyDPSEvaluation ();
6732 /* now we need to put the carry into the
6733 highest order byte of the result */
6734 if (AOP_SIZE (result) > 1)
6736 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6739 emitcode ("mov", "acc.0,c");
6740 aopPut (AOP (result), "a", 0);
6741 freeAsmop (left, NULL, ic, TRUE);
6742 freeAsmop (result, NULL, ic, TRUE);
6745 /*-----------------------------------------------------------------*/
6746 /* genGetHbit - generates code get highest order bit */
6747 /*-----------------------------------------------------------------*/
6749 genGetHbit (iCode * ic)
6751 operand *left, *result;
6752 left = IC_LEFT (ic);
6753 result = IC_RESULT (ic);
6754 aopOp (left, ic, FALSE, FALSE);
6755 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6757 D (emitcode (";", "genGetHbit ");
6760 /* get the highest order byte into a */
6761 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6762 if (AOP_TYPE (result) == AOP_CRY)
6764 emitcode ("rlc", "a");
6769 emitcode ("rl", "a");
6770 emitcode ("anl", "a,#0x01");
6775 freeAsmop (left, NULL, ic, TRUE);
6776 freeAsmop (result, NULL, ic, TRUE);
6779 /*-----------------------------------------------------------------*/
6780 /* AccRol - rotate left accumulator by known count */
6781 /*-----------------------------------------------------------------*/
6783 AccRol (int shCount)
6785 shCount &= 0x0007; // shCount : 0..7
6792 emitcode ("rl", "a");
6795 emitcode ("rl", "a");
6796 emitcode ("rl", "a");
6799 emitcode ("swap", "a");
6800 emitcode ("rr", "a");
6803 emitcode ("swap", "a");
6806 emitcode ("swap", "a");
6807 emitcode ("rl", "a");
6810 emitcode ("rr", "a");
6811 emitcode ("rr", "a");
6814 emitcode ("rr", "a");
6819 /*-----------------------------------------------------------------*/
6820 /* AccLsh - left shift accumulator by known count */
6821 /*-----------------------------------------------------------------*/
6823 AccLsh (int shCount)
6828 emitcode ("add", "a,acc");
6829 else if (shCount == 2)
6831 emitcode ("add", "a,acc");
6832 emitcode ("add", "a,acc");
6836 /* rotate left accumulator */
6838 /* and kill the lower order bits */
6839 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6844 /*-----------------------------------------------------------------*/
6845 /* AccRsh - right shift accumulator by known count */
6846 /*-----------------------------------------------------------------*/
6848 AccRsh (int shCount)
6855 emitcode ("rrc", "a");
6859 /* rotate right accumulator */
6860 AccRol (8 - shCount);
6861 /* and kill the higher order bits */
6862 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6867 #ifdef BETTER_LITERAL_SHIFT
6868 /*-----------------------------------------------------------------*/
6869 /* AccSRsh - signed right shift accumulator by known count */
6870 /*-----------------------------------------------------------------*/
6872 AccSRsh (int shCount)
6879 emitcode ("mov", "c,acc.7");
6880 emitcode ("rrc", "a");
6882 else if (shCount == 2)
6884 emitcode ("mov", "c,acc.7");
6885 emitcode ("rrc", "a");
6886 emitcode ("mov", "c,acc.7");
6887 emitcode ("rrc", "a");
6891 tlbl = newiTempLabel (NULL);
6892 /* rotate right accumulator */
6893 AccRol (8 - shCount);
6894 /* and kill the higher order bits */
6895 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6896 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6897 emitcode ("orl", "a,#0x%02x",
6898 (unsigned char) ~SRMask[shCount]);
6899 emitcode ("", "%05d$:", tlbl->key + 100);
6905 #ifdef BETTER_LITERAL_SHIFT
6906 /*-----------------------------------------------------------------*/
6907 /* shiftR1Left2Result - shift right one byte from left to result */
6908 /*-----------------------------------------------------------------*/
6910 shiftR1Left2Result (operand * left, int offl,
6911 operand * result, int offr,
6912 int shCount, int sign)
6914 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6915 /* shift right accumulator */
6920 aopPut (AOP (result), "a", offr);
6924 #ifdef BETTER_LITERAL_SHIFT
6925 /*-----------------------------------------------------------------*/
6926 /* shiftL1Left2Result - shift left one byte from left to result */
6927 /*-----------------------------------------------------------------*/
6929 shiftL1Left2Result (operand * left, int offl,
6930 operand * result, int offr, int shCount)
6932 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6933 /* shift left accumulator */
6935 aopPut (AOP (result), "a", offr);
6939 #ifdef BETTER_LITERAL_SHIFT
6940 /*-----------------------------------------------------------------*/
6941 /* movLeft2Result - move byte from left to result */
6942 /*-----------------------------------------------------------------*/
6944 movLeft2Result (operand * left, int offl,
6945 operand * result, int offr, int sign)
6948 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6950 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6952 if (*l == '@' && (IS_AOP_PREG (result)))
6954 emitcode ("mov", "a,%s", l);
6955 aopPut (AOP (result), "a", offr);
6961 aopPut (AOP (result), l, offr);
6965 /* MSB sign in acc.7 ! */
6966 if (getDataSize (left) == offl + 1)
6968 emitcode ("mov", "a,%s", l);
6969 aopPut (AOP (result), "a", offr);
6977 #ifdef BETTER_LITERAL_SHIFT
6978 /*-----------------------------------------------------------------*/
6979 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6980 /*-----------------------------------------------------------------*/
6984 emitcode ("rrc", "a");
6985 emitcode ("xch", "a,%s", x);
6986 emitcode ("rrc", "a");
6987 emitcode ("xch", "a,%s", x);
6991 #ifdef BETTER_LITERAL_SHIFT
6993 /*-----------------------------------------------------------------*/
6994 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6995 /*-----------------------------------------------------------------*/
6999 emitcode ("xch", "a,%s", x);
7000 emitcode ("rlc", "a");
7001 emitcode ("xch", "a,%s", x);
7002 emitcode ("rlc", "a");
7006 #ifdef BETTER_LITERAL_SHIFT
7007 /*-----------------------------------------------------------------*/
7008 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7009 /*-----------------------------------------------------------------*/
7013 emitcode ("xch", "a,%s", x);
7014 emitcode ("add", "a,acc");
7015 emitcode ("xch", "a,%s", x);
7016 emitcode ("rlc", "a");
7020 #ifdef BETTER_LITERAL_SHIFT
7021 /*-----------------------------------------------------------------*/
7022 /* AccAXLsh - left shift a:x by known count (0..7) */
7023 /*-----------------------------------------------------------------*/
7025 AccAXLsh (char *x, int shCount)
7040 case 5: // AAAAABBB:CCCCCDDD
7042 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7044 emitcode ("anl", "a,#0x%02x",
7045 SLMask[shCount]); // BBB00000:CCCCCDDD
7047 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7049 AccRol (shCount); // DDDCCCCC:BBB00000
7051 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7053 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7055 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7057 emitcode ("anl", "a,#0x%02x",
7058 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7060 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7062 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7065 case 6: // AAAAAABB:CCCCCCDD
7066 emitcode ("anl", "a,#0x%02x",
7067 SRMask[shCount]); // 000000BB:CCCCCCDD
7068 emitcode ("mov", "c,acc.0"); // c = B
7069 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7071 AccAXRrl1 (x); // BCCCCCCD:D000000B
7072 AccAXRrl1 (x); // BBCCCCCC:DD000000
7074 emitcode("rrc","a");
7075 emitcode("xch","a,%s", x);
7076 emitcode("rrc","a");
7077 emitcode("mov","c,acc.0"); //<< get correct bit
7078 emitcode("xch","a,%s", x);
7080 emitcode("rrc","a");
7081 emitcode("xch","a,%s", x);
7082 emitcode("rrc","a");
7083 emitcode("xch","a,%s", x);
7086 case 7: // a:x <<= 7
7088 emitcode ("anl", "a,#0x%02x",
7089 SRMask[shCount]); // 0000000B:CCCCCCCD
7091 emitcode ("mov", "c,acc.0"); // c = B
7093 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7095 AccAXRrl1 (x); // BCCCCCCC:D0000000
7104 #ifdef BETTER_LITERAL_SHIFT
7106 /*-----------------------------------------------------------------*/
7107 /* AccAXRsh - right shift a:x known count (0..7) */
7108 /*-----------------------------------------------------------------*/
7110 AccAXRsh (char *x, int shCount)
7118 AccAXRrl1 (x); // 0->a:x
7123 AccAXRrl1 (x); // 0->a:x
7126 AccAXRrl1 (x); // 0->a:x
7131 case 5: // AAAAABBB:CCCCCDDD = a:x
7133 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7135 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7137 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7139 emitcode ("anl", "a,#0x%02x",
7140 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7142 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7144 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7146 emitcode ("anl", "a,#0x%02x",
7147 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7149 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7151 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7153 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7156 case 6: // AABBBBBB:CCDDDDDD
7158 emitcode ("mov", "c,acc.7");
7159 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7161 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7163 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7165 emitcode ("anl", "a,#0x%02x",
7166 SRMask[shCount]); // 000000AA:BBBBBBCC
7169 case 7: // ABBBBBBB:CDDDDDDD
7171 emitcode ("mov", "c,acc.7"); // c = A
7173 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7175 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7177 emitcode ("anl", "a,#0x%02x",
7178 SRMask[shCount]); // 0000000A:BBBBBBBC
7187 #ifdef BETTER_LITERAL_SHIFT
7188 /*-----------------------------------------------------------------*/
7189 /* AccAXRshS - right shift signed a:x known count (0..7) */
7190 /*-----------------------------------------------------------------*/
7192 AccAXRshS (char *x, int shCount)
7200 emitcode ("mov", "c,acc.7");
7201 AccAXRrl1 (x); // s->a:x
7205 emitcode ("mov", "c,acc.7");
7206 AccAXRrl1 (x); // s->a:x
7208 emitcode ("mov", "c,acc.7");
7209 AccAXRrl1 (x); // s->a:x
7214 case 5: // AAAAABBB:CCCCCDDD = a:x
7216 tlbl = newiTempLabel (NULL);
7217 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7219 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7221 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7223 emitcode ("anl", "a,#0x%02x",
7224 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7226 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7228 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7230 emitcode ("anl", "a,#0x%02x",
7231 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7233 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7235 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7237 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7239 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7240 emitcode ("orl", "a,#0x%02x",
7241 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7243 emitcode ("", "%05d$:", tlbl->key + 100);
7244 break; // SSSSAAAA:BBBCCCCC
7246 case 6: // AABBBBBB:CCDDDDDD
7248 tlbl = newiTempLabel (NULL);
7249 emitcode ("mov", "c,acc.7");
7250 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7252 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7254 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7256 emitcode ("anl", "a,#0x%02x",
7257 SRMask[shCount]); // 000000AA:BBBBBBCC
7259 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7260 emitcode ("orl", "a,#0x%02x",
7261 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7263 emitcode ("", "%05d$:", tlbl->key + 100);
7265 case 7: // ABBBBBBB:CDDDDDDD
7267 tlbl = newiTempLabel (NULL);
7268 emitcode ("mov", "c,acc.7"); // c = A
7270 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7272 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7274 emitcode ("anl", "a,#0x%02x",
7275 SRMask[shCount]); // 0000000A:BBBBBBBC
7277 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7278 emitcode ("orl", "a,#0x%02x",
7279 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7281 emitcode ("", "%05d$:", tlbl->key + 100);
7289 #ifdef BETTER_LITERAL_SHIFT
7291 _loadLeftIntoAx(char **lsb,
7297 // Get the initial value from left into a pair of registers.
7298 // MSB must be in A, LSB can be any register.
7300 // If the result is held in registers, it is an optimization
7301 // if the LSB can be held in the register which will hold the,
7302 // result LSB since this saves us from having to copy it into
7303 // the result following AccAXLsh.
7305 // If the result is addressed indirectly, this is not a gain.
7306 if (AOP_NEEDSACC(result))
7310 _startLazyDPSEvaluation();
7311 if (AOP_TYPE(left) == AOP_DPTR2)
7314 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7315 // get LSB in DP2_RESULT_REG.
7316 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7317 assert(!strcmp(leftByte, DP2_RESULT_REG));
7321 // get LSB into DP2_RESULT_REG
7322 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7323 if (strcmp(leftByte, DP2_RESULT_REG))
7326 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7329 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7330 assert(strcmp(leftByte, DP2_RESULT_REG));
7333 _endLazyDPSEvaluation();
7334 *lsb = DP2_RESULT_REG;
7338 if (sameRegs (AOP (result), AOP (left)) &&
7339 ((offl + MSB16) == offr))
7341 /* don't crash result[offr] */
7342 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7343 emitcode ("xch", "a,%s",
7344 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7348 movLeft2Result (left, offl, result, offr, 0);
7349 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7351 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7352 assert(strcmp(*lsb,"a"));
7357 _storeAxResults(char *lsb,
7361 _startLazyDPSEvaluation();
7362 if (AOP_NEEDSACC(result))
7364 /* We have to explicitly update the result LSB.
7366 emitcode("xch","a,%s", lsb);
7367 aopPut(AOP(result), "a", offr);
7368 emitcode("mov","a,%s", lsb);
7370 if (getDataSize (result) > 1)
7372 aopPut (AOP (result), "a", offr + MSB16);
7374 _endLazyDPSEvaluation();
7377 /*-----------------------------------------------------------------*/
7378 /* shiftL2Left2Result - shift left two bytes from left to result */
7379 /*-----------------------------------------------------------------*/
7381 shiftL2Left2Result (operand * left, int offl,
7382 operand * result, int offr, int shCount)
7386 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7388 AccAXLsh (lsb, shCount);
7390 _storeAxResults(lsb, result, offr);
7394 #ifdef BETTER_LITERAL_SHIFT
7395 /*-----------------------------------------------------------------*/
7396 /* shiftR2Left2Result - shift right two bytes from left to result */
7397 /*-----------------------------------------------------------------*/
7399 shiftR2Left2Result (operand * left, int offl,
7400 operand * result, int offr,
7401 int shCount, int sign)
7405 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7407 /* a:x >> shCount (x = lsb(result)) */
7410 AccAXRshS(lsb, shCount);
7414 AccAXRsh(lsb, shCount);
7417 _storeAxResults(lsb, result, offr);
7423 /*-----------------------------------------------------------------*/
7424 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7425 /*-----------------------------------------------------------------*/
7427 shiftLLeftOrResult (operand * left, int offl,
7428 operand * result, int offr, int shCount)
7430 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7431 /* shift left accumulator */
7433 /* or with result */
7434 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7435 /* back to result */
7436 aopPut (AOP (result), "a", offr);
7442 /*-----------------------------------------------------------------*/
7443 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7444 /*-----------------------------------------------------------------*/
7446 shiftRLeftOrResult (operand * left, int offl,
7447 operand * result, int offr, int shCount)
7449 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7450 /* shift right accumulator */
7452 /* or with result */
7453 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7454 /* back to result */
7455 aopPut (AOP (result), "a", offr);
7459 #ifdef BETTER_LITERAL_SHIFT
7460 /*-----------------------------------------------------------------*/
7461 /* genlshOne - left shift a one byte quantity by known count */
7462 /*-----------------------------------------------------------------*/
7464 genlshOne (operand * result, operand * left, int shCount)
7466 D (emitcode (";", "genlshOne "););
7467 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7471 #ifdef BETTER_LITERAL_SHIFT
7472 /*-----------------------------------------------------------------*/
7473 /* genlshTwo - left shift two bytes by known amount != 0 */
7474 /*-----------------------------------------------------------------*/
7476 genlshTwo (operand * result, operand * left, int shCount)
7480 D (emitcode (";", "genlshTwo "););
7482 size = getDataSize (result);
7484 /* if shCount >= 8 */
7489 _startLazyDPSEvaluation();
7495 _endLazyDPSEvaluation();
7496 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7497 aopPut (AOP (result), zero, LSB);
7501 movLeft2Result (left, LSB, result, MSB16, 0);
7502 aopPut (AOP (result), zero, LSB);
7503 _endLazyDPSEvaluation();
7508 aopPut (AOP (result), zero, LSB);
7509 _endLazyDPSEvaluation();
7513 /* 1 <= shCount <= 7 */
7518 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7522 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7530 /*-----------------------------------------------------------------*/
7531 /* shiftLLong - shift left one long from left to result */
7532 /* offl = LSB or MSB16 */
7533 /*-----------------------------------------------------------------*/
7535 shiftLLong (operand * left, operand * result, int offr)
7538 int size = AOP_SIZE (result);
7540 if (size >= LSB + offr)
7542 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7544 emitcode ("add", "a,acc");
7545 if (sameRegs (AOP (left), AOP (result)) &&
7546 size >= MSB16 + offr && offr != LSB)
7547 emitcode ("xch", "a,%s",
7548 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7550 aopPut (AOP (result), "a", LSB + offr);
7553 if (size >= MSB16 + offr)
7555 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7557 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7560 emitcode ("rlc", "a");
7561 if (sameRegs (AOP (left), AOP (result)) &&
7562 size >= MSB24 + offr && offr != LSB)
7563 emitcode ("xch", "a,%s",
7564 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7566 aopPut (AOP (result), "a", MSB16 + offr);
7569 if (size >= MSB24 + offr)
7571 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7573 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7576 emitcode ("rlc", "a");
7577 if (sameRegs (AOP (left), AOP (result)) &&
7578 size >= MSB32 + offr && offr != LSB)
7579 emitcode ("xch", "a,%s",
7580 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7582 aopPut (AOP (result), "a", MSB24 + offr);
7585 if (size > MSB32 + offr)
7587 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7589 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7592 emitcode ("rlc", "a");
7593 aopPut (AOP (result), "a", MSB32 + offr);
7596 aopPut (AOP (result), zero, LSB);
7602 /*-----------------------------------------------------------------*/
7603 /* genlshFour - shift four byte by a known amount != 0 */
7604 /*-----------------------------------------------------------------*/
7606 genlshFour (operand * result, operand * left, int shCount)
7610 D (emitcode (";", "genlshFour ");
7613 size = AOP_SIZE (result);
7615 /* if shifting more that 3 bytes */
7620 /* lowest order of left goes to the highest
7621 order of the destination */
7622 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7624 movLeft2Result (left, LSB, result, MSB32, 0);
7625 aopPut (AOP (result), zero, LSB);
7626 aopPut (AOP (result), zero, MSB16);
7627 aopPut (AOP (result), zero, MSB24);
7631 /* more than two bytes */
7632 else if (shCount >= 16)
7634 /* lower order two bytes goes to higher order two bytes */
7636 /* if some more remaining */
7638 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7641 movLeft2Result (left, MSB16, result, MSB32, 0);
7642 movLeft2Result (left, LSB, result, MSB24, 0);
7644 aopPut (AOP (result), zero, MSB16);
7645 aopPut (AOP (result), zero, LSB);
7649 /* if more than 1 byte */
7650 else if (shCount >= 8)
7652 /* lower order three bytes goes to higher order three bytes */
7657 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7659 movLeft2Result (left, LSB, result, MSB16, 0);
7665 movLeft2Result (left, MSB24, result, MSB32, 0);
7666 movLeft2Result (left, MSB16, result, MSB24, 0);
7667 movLeft2Result (left, LSB, result, MSB16, 0);
7668 aopPut (AOP (result), zero, LSB);
7670 else if (shCount == 1)
7671 shiftLLong (left, result, MSB16);
7674 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7675 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7676 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7677 aopPut (AOP (result), zero, LSB);
7682 /* 1 <= shCount <= 7 */
7683 else if (shCount <= 2)
7685 shiftLLong (left, result, LSB);
7687 shiftLLong (result, result, LSB);
7689 /* 3 <= shCount <= 7, optimize */
7692 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7693 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7694 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7699 #ifdef BETTER_LITERAL_SHIFT
7700 /*-----------------------------------------------------------------*/
7701 /* genLeftShiftLiteral - left shifting by known count */
7702 /*-----------------------------------------------------------------*/
7704 genLeftShiftLiteral (operand * left,
7709 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7712 size = getSize (operandType (result));
7714 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7716 /* We only handle certain easy cases so far. */
7718 && (shCount < (size * 8))
7722 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7726 freeAsmop (right, NULL, ic, TRUE);
7728 aopOp(left, ic, FALSE, FALSE);
7729 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7732 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7734 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7735 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7737 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7740 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7742 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7743 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7745 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7751 emitcode ("; shift left ", "result %d, left %d", size,
7755 /* I suppose that the left size >= result size */
7758 _startLazyDPSEvaluation();
7761 movLeft2Result (left, size, result, size, 0);
7763 _endLazyDPSEvaluation();
7765 else if (shCount >= (size * 8))
7767 _startLazyDPSEvaluation();
7770 aopPut (AOP (result), zero, size);
7772 _endLazyDPSEvaluation();
7779 genlshOne (result, left, shCount);
7783 genlshTwo (result, left, shCount);
7787 genlshFour (result, left, shCount);
7791 fprintf(stderr, "*** ack! mystery literal shift!\n");
7795 freeAsmop (left, NULL, ic, TRUE);
7796 freeAsmop (result, NULL, ic, TRUE);
7801 /*-----------------------------------------------------------------*/
7802 /* genLeftShift - generates code for left shifting */
7803 /*-----------------------------------------------------------------*/
7805 genLeftShift (iCode * ic)
7807 operand *left, *right, *result;
7810 symbol *tlbl, *tlbl1;
7812 D (emitcode (";", "genLeftShift "););
7814 right = IC_RIGHT (ic);
7815 left = IC_LEFT (ic);
7816 result = IC_RESULT (ic);
7818 aopOp (right, ic, FALSE, FALSE);
7821 #ifdef BETTER_LITERAL_SHIFT
7822 /* if the shift count is known then do it
7823 as efficiently as possible */
7824 if (AOP_TYPE (right) == AOP_LIT)
7826 if (genLeftShiftLiteral (left, right, result, ic))
7833 /* shift count is unknown then we have to form
7834 a loop get the loop count in B : Note: we take
7835 only the lower order byte since shifting
7836 more that 32 bits make no sense anyway, ( the
7837 largest size of an object can be only 32 bits ) */
7839 if (AOP_TYPE (right) == AOP_LIT)
7841 /* Really should be handled by genLeftShiftLiteral,
7842 * but since I'm too lazy to fix that today, at least we can make
7843 * some small improvement.
7845 emitcode("mov", "b,#0x%02x",
7846 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7850 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7851 emitcode ("inc", "b");
7853 freeAsmop (right, NULL, ic, TRUE);
7854 aopOp (left, ic, FALSE, FALSE);
7855 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7857 /* now move the left to the result if they are not the
7859 if (!sameRegs (AOP (left), AOP (result)) &&
7860 AOP_SIZE (result) > 1)
7863 size = AOP_SIZE (result);
7865 _startLazyDPSEvaluation ();
7868 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7869 if (*l == '@' && (IS_AOP_PREG (result)))
7872 emitcode ("mov", "a,%s", l);
7873 aopPut (AOP (result), "a", offset);
7876 aopPut (AOP (result), l, offset);
7879 _endLazyDPSEvaluation ();
7882 tlbl = newiTempLabel (NULL);
7883 size = AOP_SIZE (result);
7885 tlbl1 = newiTempLabel (NULL);
7887 /* if it is only one byte then */
7890 symbol *tlbl1 = newiTempLabel (NULL);
7892 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7894 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7895 emitcode ("", "%05d$:", tlbl->key + 100);
7896 emitcode ("add", "a,acc");
7897 emitcode ("", "%05d$:", tlbl1->key + 100);
7898 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7899 aopPut (AOP (result), "a", 0);
7903 reAdjustPreg (AOP (result));
7905 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7906 emitcode ("", "%05d$:", tlbl->key + 100);
7907 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7909 emitcode ("add", "a,acc");
7910 aopPut (AOP (result), "a", offset++);
7911 _startLazyDPSEvaluation ();
7914 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7916 emitcode ("rlc", "a");
7917 aopPut (AOP (result), "a", offset++);
7919 _endLazyDPSEvaluation ();
7920 reAdjustPreg (AOP (result));
7922 emitcode ("", "%05d$:", tlbl1->key + 100);
7923 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7925 freeAsmop (left, NULL, ic, TRUE);
7926 freeAsmop (result, NULL, ic, TRUE);
7929 #ifdef BETTER_LITERAL_SHIFT
7930 /*-----------------------------------------------------------------*/
7931 /* genrshOne - right shift a one byte quantity by known count */
7932 /*-----------------------------------------------------------------*/
7934 genrshOne (operand * result, operand * left,
7935 int shCount, int sign)
7937 D (emitcode (";", "genrshOne"););
7938 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7942 #ifdef BETTER_LITERAL_SHIFT
7943 /*-----------------------------------------------------------------*/
7944 /* genrshTwo - right shift two bytes by known amount != 0 */
7945 /*-----------------------------------------------------------------*/
7947 genrshTwo (operand * result, operand * left,
7948 int shCount, int sign)
7950 D (emitcode (";", "genrshTwo"););
7952 /* if shCount >= 8 */
7956 _startLazyDPSEvaluation();
7959 shiftR1Left2Result (left, MSB16, result, LSB,
7964 movLeft2Result (left, MSB16, result, LSB, sign);
7966 addSign (result, MSB16, sign);
7967 _endLazyDPSEvaluation();
7970 /* 1 <= shCount <= 7 */
7973 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7980 /*-----------------------------------------------------------------*/
7981 /* shiftRLong - shift right one long from left to result */
7982 /* offl = LSB or MSB16 */
7983 /*-----------------------------------------------------------------*/
7985 shiftRLong (operand * left, int offl,
7986 operand * result, int sign)
7988 int isSameRegs=sameRegs(AOP(left),AOP(result));
7990 if (isSameRegs && offl>1) {
7991 // we are in big trouble, but this shouldn't happen
7992 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7995 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
8000 emitcode ("rlc", "a");
8001 emitcode ("subb", "a,acc");
8002 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
8004 aopPut (AOP(result), zero, MSB32);
8009 emitcode ("clr", "c");
8011 emitcode ("mov", "c,acc.7");
8014 emitcode ("rrc", "a");
8016 if (isSameRegs && offl==MSB16) {
8017 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
8019 aopPut (AOP (result), "a", MSB32);
8020 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
8023 emitcode ("rrc", "a");
8024 if (isSameRegs && offl==1) {
8025 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
8027 aopPut (AOP (result), "a", MSB24);
8028 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
8030 emitcode ("rrc", "a");
8031 aopPut (AOP (result), "a", MSB16 - offl);
8035 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
8036 emitcode ("rrc", "a");
8037 aopPut (AOP (result), "a", LSB);
8044 /*-----------------------------------------------------------------*/
8045 /* genrshFour - shift four byte by a known amount != 0 */
8046 /*-----------------------------------------------------------------*/
8048 genrshFour (operand * result, operand * left,
8049 int shCount, int sign)
8051 D (emitcode (";", "genrshFour");
8054 /* if shifting more that 3 bytes */
8059 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8061 movLeft2Result (left, MSB32, result, LSB, sign);
8062 addSign (result, MSB16, sign);
8064 else if (shCount >= 16)
8068 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8071 movLeft2Result (left, MSB24, result, LSB, 0);
8072 movLeft2Result (left, MSB32, result, MSB16, sign);
8074 addSign (result, MSB24, sign);
8076 else if (shCount >= 8)
8080 shiftRLong (left, MSB16, result, sign);
8081 else if (shCount == 0)
8083 movLeft2Result (left, MSB16, result, LSB, 0);
8084 movLeft2Result (left, MSB24, result, MSB16, 0);
8085 movLeft2Result (left, MSB32, result, MSB24, sign);
8086 addSign (result, MSB32, sign);
8090 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8091 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8092 /* the last shift is signed */
8093 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8094 addSign (result, MSB32, sign);
8098 { /* 1 <= shCount <= 7 */
8101 shiftRLong (left, LSB, result, sign);
8103 shiftRLong (result, LSB, result, sign);
8107 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8108 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8109 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8115 #ifdef BETTER_LITERAL_SHIFT
8116 /*-----------------------------------------------------------------*/
8117 /* genRightShiftLiteral - right shifting by known count */
8118 /*-----------------------------------------------------------------*/
8120 genRightShiftLiteral (operand * left,
8126 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8129 size = getSize (operandType (result));
8131 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8133 /* We only handle certain easy cases so far. */
8135 && (shCount < (size * 8))
8139 D(emitcode (";", "genRightShiftLiteral wimping out"););
8143 freeAsmop (right, NULL, ic, TRUE);
8145 aopOp (left, ic, FALSE, FALSE);
8146 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8149 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8153 /* test the LEFT size !!! */
8155 /* I suppose that the left size >= result size */
8158 size = getDataSize (result);
8159 _startLazyDPSEvaluation();
8162 movLeft2Result (left, size, result, size, 0);
8164 _endLazyDPSEvaluation();
8166 else if (shCount >= (size * 8))
8170 /* get sign in acc.7 */
8171 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8173 addSign (result, LSB, sign);
8180 genrshOne (result, left, shCount, sign);
8184 genrshTwo (result, left, shCount, sign);
8188 genrshFour (result, left, shCount, sign);
8195 freeAsmop (left, NULL, ic, TRUE);
8196 freeAsmop (result, NULL, ic, TRUE);
8202 /*-----------------------------------------------------------------*/
8203 /* genSignedRightShift - right shift of signed number */
8204 /*-----------------------------------------------------------------*/
8206 genSignedRightShift (iCode * ic)
8208 operand *right, *left, *result;
8211 symbol *tlbl, *tlbl1;
8213 D (emitcode (";", "genSignedRightShift "););
8215 /* we do it the hard way put the shift count in b
8216 and loop thru preserving the sign */
8218 right = IC_RIGHT (ic);
8219 left = IC_LEFT (ic);
8220 result = IC_RESULT (ic);
8222 aopOp (right, ic, FALSE, FALSE);
8224 #ifdef BETTER_LITERAL_SHIFT
8225 if (AOP_TYPE (right) == AOP_LIT)
8227 if (genRightShiftLiteral (left, right, result, ic, 1))
8233 /* shift count is unknown then we have to form
8234 a loop get the loop count in B : Note: we take
8235 only the lower order byte since shifting
8236 more that 32 bits make no sense anyway, ( the
8237 largest size of an object can be only 32 bits ) */
8239 if (AOP_TYPE (right) == AOP_LIT)
8241 /* Really should be handled by genRightShiftLiteral,
8242 * but since I'm too lazy to fix that today, at least we can make
8243 * some small improvement.
8245 emitcode("mov", "b,#0x%02x",
8246 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8250 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8251 emitcode ("inc", "b");
8253 freeAsmop (right, NULL, ic, TRUE);
8254 aopOp (left, ic, FALSE, FALSE);
8255 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8257 /* now move the left to the result if they are not the
8259 if (!sameRegs (AOP (left), AOP (result)) &&
8260 AOP_SIZE (result) > 1)
8263 size = AOP_SIZE (result);
8265 _startLazyDPSEvaluation ();
8268 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8269 if (*l == '@' && IS_AOP_PREG (result))
8272 emitcode ("mov", "a,%s", l);
8273 aopPut (AOP (result), "a", offset);
8276 aopPut (AOP (result), l, offset);
8279 _endLazyDPSEvaluation ();
8282 /* mov the highest order bit to OVR */
8283 tlbl = newiTempLabel (NULL);
8284 tlbl1 = newiTempLabel (NULL);
8286 size = AOP_SIZE (result);
8288 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8289 emitcode ("rlc", "a");
8290 emitcode ("mov", "ov,c");
8291 /* if it is only one byte then */
8294 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8296 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8297 emitcode ("", "%05d$:", tlbl->key + 100);
8298 emitcode ("mov", "c,ov");
8299 emitcode ("rrc", "a");
8300 emitcode ("", "%05d$:", tlbl1->key + 100);
8301 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8302 aopPut (AOP (result), "a", 0);
8306 reAdjustPreg (AOP (result));
8307 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8308 emitcode ("", "%05d$:", tlbl->key + 100);
8309 emitcode ("mov", "c,ov");
8310 _startLazyDPSEvaluation ();
8313 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8315 emitcode ("rrc", "a");
8316 aopPut (AOP (result), "a", offset--);
8318 _endLazyDPSEvaluation ();
8319 reAdjustPreg (AOP (result));
8320 emitcode ("", "%05d$:", tlbl1->key + 100);
8321 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8324 freeAsmop (left, NULL, ic, TRUE);
8325 freeAsmop (result, NULL, ic, TRUE);
8328 /*-----------------------------------------------------------------*/
8329 /* genRightShift - generate code for right shifting */
8330 /*-----------------------------------------------------------------*/
8332 genRightShift (iCode * ic)
8334 operand *right, *left, *result;
8338 symbol *tlbl, *tlbl1;
8340 D (emitcode (";", "genRightShift "););
8342 /* if signed then we do it the hard way preserve the
8343 sign bit moving it inwards */
8344 retype = getSpec (operandType (IC_RESULT (ic)));
8346 if (!SPEC_USIGN (retype))
8348 genSignedRightShift (ic);
8352 /* signed & unsigned types are treated the same : i.e. the
8353 signed is NOT propagated inwards : quoting from the
8354 ANSI - standard : "for E1 >> E2, is equivalent to division
8355 by 2**E2 if unsigned or if it has a non-negative value,
8356 otherwise the result is implementation defined ", MY definition
8357 is that the sign does not get propagated */
8359 right = IC_RIGHT (ic);
8360 left = IC_LEFT (ic);
8361 result = IC_RESULT (ic);
8363 aopOp (right, ic, FALSE, FALSE);
8365 #ifdef BETTER_LITERAL_SHIFT
8366 /* if the shift count is known then do it
8367 as efficiently as possible */
8368 if (AOP_TYPE (right) == AOP_LIT)
8370 if (genRightShiftLiteral (left, right, result, ic, 0))
8377 /* shift count is unknown then we have to form
8378 a loop get the loop count in B : Note: we take
8379 only the lower order byte since shifting
8380 more that 32 bits make no sense anyway, ( the
8381 largest size of an object can be only 32 bits ) */
8383 if (AOP_TYPE (right) == AOP_LIT)
8385 /* Really should be handled by genRightShiftLiteral,
8386 * but since I'm too lazy to fix that today, at least we can make
8387 * some small improvement.
8389 emitcode("mov", "b,#0x%02x",
8390 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8394 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8395 emitcode ("inc", "b");
8397 freeAsmop (right, NULL, ic, TRUE);
8398 aopOp (left, ic, FALSE, FALSE);
8399 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8401 /* now move the left to the result if they are not the
8403 if (!sameRegs (AOP (left), AOP (result)) &&
8404 AOP_SIZE (result) > 1)
8407 size = AOP_SIZE (result);
8409 _startLazyDPSEvaluation ();
8412 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8413 if (*l == '@' && IS_AOP_PREG (result))
8416 emitcode ("mov", "a,%s", l);
8417 aopPut (AOP (result), "a", offset);
8420 aopPut (AOP (result), l, offset);
8423 _endLazyDPSEvaluation ();
8426 tlbl = newiTempLabel (NULL);
8427 tlbl1 = newiTempLabel (NULL);
8428 size = AOP_SIZE (result);
8431 /* if it is only one byte then */
8434 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8436 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8437 emitcode ("", "%05d$:", tlbl->key + 100);
8439 emitcode ("rrc", "a");
8440 emitcode ("", "%05d$:", tlbl1->key + 100);
8441 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8442 aopPut (AOP (result), "a", 0);
8446 reAdjustPreg (AOP (result));
8447 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8448 emitcode ("", "%05d$:", tlbl->key + 100);
8450 _startLazyDPSEvaluation ();
8453 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8455 emitcode ("rrc", "a");
8456 aopPut (AOP (result), "a", offset--);
8458 _endLazyDPSEvaluation ();
8459 reAdjustPreg (AOP (result));
8461 emitcode ("", "%05d$:", tlbl1->key + 100);
8462 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8465 freeAsmop (left, NULL, ic, TRUE);
8466 freeAsmop (result, NULL, ic, TRUE);
8469 /*-----------------------------------------------------------------*/
8470 /* genUnpackBits - generates code for unpacking bits */
8471 /*-----------------------------------------------------------------*/
8473 genUnpackBits (operand * result, char *rname, int ptype)
8480 D (emitcode (";", "genUnpackBits ");
8483 etype = getSpec (operandType (result));
8485 /* read the first byte */
8491 emitcode ("mov", "a,@%s", rname);
8495 emitcode ("movx", "a,@%s", rname);
8499 emitcode ("movx", "a,@dptr");
8503 emitcode ("clr", "a");
8504 emitcode ("movc", "a,@a+dptr");
8508 emitcode ("lcall", "__gptrget");
8512 /* if we have bitdisplacement then it fits */
8513 /* into this byte completely or if length is */
8514 /* less than a byte */
8515 if ((shCnt = SPEC_BSTR (etype)) ||
8516 (SPEC_BLEN (etype) <= 8))
8519 /* shift right acc */
8522 emitcode ("anl", "a,#0x%02x",
8523 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8524 aopPut (AOP (result), "a", offset);
8528 /* bit field did not fit in a byte */
8529 rlen = SPEC_BLEN (etype) - 8;
8530 aopPut (AOP (result), "a", offset++);
8539 emitcode ("inc", "%s", rname);
8540 emitcode ("mov", "a,@%s", rname);
8544 emitcode ("inc", "%s", rname);
8545 emitcode ("movx", "a,@%s", rname);
8549 emitcode ("inc", "dptr");
8550 emitcode ("movx", "a,@dptr");
8554 emitcode ("clr", "a");
8555 emitcode ("inc", "dptr");
8556 emitcode ("movc", "a,@a+dptr");
8560 emitcode ("inc", "dptr");
8561 emitcode ("lcall", "__gptrget");
8566 /* if we are done */
8570 aopPut (AOP (result), "a", offset++);
8576 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
8577 aopPut (AOP (result), "a", offset);
8584 /*-----------------------------------------------------------------*/
8585 /* genDataPointerGet - generates code when ptr offset is known */
8586 /*-----------------------------------------------------------------*/
8588 genDataPointerGet (operand * left,
8594 int size, offset = 0;
8595 aopOp (result, ic, TRUE, FALSE);
8597 /* get the string representation of the name */
8598 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8599 size = AOP_SIZE (result);
8600 _startLazyDPSEvaluation ();
8604 sprintf (buffer, "(%s + %d)", l + 1, offset);
8606 sprintf (buffer, "%s", l + 1);
8607 aopPut (AOP (result), buffer, offset++);
8609 _endLazyDPSEvaluation ();
8611 freeAsmop (left, NULL, ic, TRUE);
8612 freeAsmop (result, NULL, ic, TRUE);
8615 /*-----------------------------------------------------------------*/
8616 /* genNearPointerGet - emitcode for near pointer fetch */
8617 /*-----------------------------------------------------------------*/
8619 genNearPointerGet (operand * left,
8627 sym_link *rtype, *retype, *letype;
8628 sym_link *ltype = operandType (left);
8631 rtype = operandType (result);
8632 retype = getSpec (rtype);
8633 letype = getSpec (ltype);
8635 aopOp (left, ic, FALSE, FALSE);
8637 /* if left is rematerialisable and
8638 result is not bit variable type and
8639 the left is pointer to data space i.e
8640 lower 128 bytes of space */
8641 if (AOP_TYPE (left) == AOP_IMMD &&
8642 !IS_BITVAR (retype) &&
8643 !IS_BITVAR (letype) &&
8644 DCL_TYPE (ltype) == POINTER)
8646 genDataPointerGet (left, result, ic);
8650 /* if the value is already in a pointer register
8651 then don't need anything more */
8652 if (!AOP_INPREG (AOP (left)))
8654 /* otherwise get a free pointer register */
8656 preg = getFreePtr (ic, &aop, FALSE);
8657 emitcode ("mov", "%s,%s",
8659 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8663 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8665 freeAsmop (left, NULL, ic, TRUE);
8666 aopOp (result, ic, FALSE, FALSE);
8668 /* if bitfield then unpack the bits */
8669 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8670 genUnpackBits (result, rname, POINTER);
8673 /* we have can just get the values */
8674 int size = AOP_SIZE (result);
8679 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8682 emitcode ("mov", "a,@%s", rname);
8683 aopPut (AOP (result), "a", offset);
8687 sprintf (buffer, "@%s", rname);
8688 aopPut (AOP (result), buffer, offset);
8692 emitcode ("inc", "%s", rname);
8696 /* now some housekeeping stuff */
8699 /* we had to allocate for this iCode */
8700 if (pi) { /* post increment present */
8701 aopPut(AOP ( left ),rname,0);
8703 freeAsmop (NULL, aop, ic, TRUE);
8707 /* we did not allocate which means left
8708 already in a pointer register, then
8709 if size > 0 && this could be used again
8710 we have to point it back to where it
8712 if (AOP_SIZE (result) > 1 &&
8713 !OP_SYMBOL (left)->remat &&
8714 (OP_SYMBOL (left)->liveTo > ic->seq ||
8718 int size = AOP_SIZE (result) - 1;
8720 emitcode ("dec", "%s", rname);
8725 freeAsmop (result, NULL, ic, TRUE);
8726 if (pi) pi->generated = 1;
8729 /*-----------------------------------------------------------------*/
8730 /* genPagedPointerGet - emitcode for paged pointer fetch */
8731 /*-----------------------------------------------------------------*/
8733 genPagedPointerGet (operand * left,
8741 sym_link *rtype, *retype, *letype;
8743 rtype = operandType (result);
8744 retype = getSpec (rtype);
8745 letype = getSpec (operandType (left));
8746 aopOp (left, ic, FALSE, FALSE);
8748 /* if the value is already in a pointer register
8749 then don't need anything more */
8750 if (!AOP_INPREG (AOP (left)))
8752 /* otherwise get a free pointer register */
8754 preg = getFreePtr (ic, &aop, FALSE);
8755 emitcode ("mov", "%s,%s",
8757 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8761 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8763 freeAsmop (left, NULL, ic, TRUE);
8764 aopOp (result, ic, FALSE, FALSE);
8766 /* if bitfield then unpack the bits */
8767 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8768 genUnpackBits (result, rname, PPOINTER);
8771 /* we have can just get the values */
8772 int size = AOP_SIZE (result);
8778 emitcode ("movx", "a,@%s", rname);
8779 aopPut (AOP (result), "a", offset);
8784 emitcode ("inc", "%s", rname);
8788 /* now some housekeeping stuff */
8791 /* we had to allocate for this iCode */
8792 if (pi) aopPut ( AOP (left), rname, 0);
8793 freeAsmop (NULL, aop, ic, TRUE);
8797 /* we did not allocate which means left
8798 already in a pointer register, then
8799 if size > 0 && this could be used again
8800 we have to point it back to where it
8802 if (AOP_SIZE (result) > 1 &&
8803 !OP_SYMBOL (left)->remat &&
8804 (OP_SYMBOL (left)->liveTo > ic->seq ||
8808 int size = AOP_SIZE (result) - 1;
8810 emitcode ("dec", "%s", rname);
8815 freeAsmop (result, NULL, ic, TRUE);
8816 if (pi) pi->generated = 1;
8819 /*-----------------------------------------------------------------*/
8820 /* genFarPointerGet - gget value from far space */
8821 /*-----------------------------------------------------------------*/
8823 genFarPointerGet (operand * left,
8824 operand * result, iCode * ic, iCode *pi)
8827 sym_link *retype = getSpec (operandType (result));
8828 sym_link *letype = getSpec (operandType (left));
8829 D (emitcode (";", "genFarPointerGet");
8832 aopOp (left, ic, FALSE, FALSE);
8834 /* if the operand is already in dptr
8835 then we do nothing else we move the value to dptr */
8836 if (AOP_TYPE (left) != AOP_STR)
8838 /* if this is remateriazable */
8839 if (AOP_TYPE (left) == AOP_IMMD)
8841 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8845 /* we need to get it byte by byte */
8846 _startLazyDPSEvaluation ();
8847 if (AOP_TYPE (left) != AOP_DPTR)
8849 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8850 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8851 if (options.model == MODEL_FLAT24)
8852 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8856 /* We need to generate a load to DPTR indirect through DPTR. */
8857 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8859 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8860 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8861 if (options.model == MODEL_FLAT24)
8862 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8863 emitcode ("pop", "dph");
8864 emitcode ("pop", "dpl");
8866 _endLazyDPSEvaluation ();
8869 /* so dptr know contains the address */
8870 aopOp (result, ic, FALSE, TRUE);
8872 /* if bit then unpack */
8873 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8874 genUnpackBits (result, "dptr", FPOINTER);
8877 size = AOP_SIZE (result);
8880 _startLazyDPSEvaluation ();
8887 emitcode ("movx", "a,@dptr");
8888 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
8889 emitcode ("inc", "dptr");
8891 aopPut (AOP (result), "a", offset++);
8893 _endLazyDPSEvaluation ();
8895 if (pi && AOP_TYPE (left) != AOP_IMMD) {
8896 aopPut ( AOP (left), "dpl", 0);
8897 aopPut ( AOP (left), "dph", 1);
8898 if (options.model == MODEL_FLAT24)
8899 aopPut ( AOP (left), "dpx", 2);
8901 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
8902 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
8904 size = AOP_SIZE (result) - 1;
8905 while (size--) emitcode ("lcall","__decdptr");
8908 freeAsmop (left, NULL, ic, TRUE);
8909 freeAsmop (result, NULL, ic, TRUE);
8912 /*-----------------------------------------------------------------*/
8913 /* emitcodePointerGet - gget value from code space */
8914 /*-----------------------------------------------------------------*/
8916 emitcodePointerGet (operand * left,
8917 operand * result, iCode * ic, iCode *pi)
8920 sym_link *retype = getSpec (operandType (result));
8922 aopOp (left, ic, FALSE, FALSE);
8924 /* if the operand is already in dptr
8925 then we do nothing else we move the value to dptr */
8926 if (AOP_TYPE (left) != AOP_STR)
8928 /* if this is remateriazable */
8929 if (AOP_TYPE (left) == AOP_IMMD)
8931 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8934 { /* we need to get it byte by byte */
8935 _startLazyDPSEvaluation ();
8936 if (AOP_TYPE (left) != AOP_DPTR)
8938 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8939 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8940 if (options.model == MODEL_FLAT24)
8941 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8945 /* We need to generate a load to DPTR indirect through DPTR. */
8946 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8948 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8949 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8950 if (options.model == MODEL_FLAT24)
8951 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8952 emitcode ("pop", "dph");
8953 emitcode ("pop", "dpl");
8955 _endLazyDPSEvaluation ();
8958 /* so dptr know contains the address */
8959 aopOp (result, ic, FALSE, TRUE);
8961 /* if bit then unpack */
8962 if (IS_BITVAR (retype))
8963 genUnpackBits (result, "dptr", CPOINTER);
8966 size = AOP_SIZE (result);
8969 _startLazyDPSEvaluation ();
8975 emitcode ("clr", "a");
8976 emitcode ("movc", "a,@a+dptr");
8977 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
8978 emitcode ("inc", "dptr");
8979 aopPut (AOP (result), "a", offset++);
8981 _endLazyDPSEvaluation ();
8983 if (pi && AOP_TYPE (left) != AOP_IMMD) {
8984 aopPut ( AOP (left), "dpl", 0);
8985 aopPut ( AOP (left), "dph", 1);
8986 if (options.model == MODEL_FLAT24)
8987 aopPut ( AOP (left), "dpx", 2);
8989 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
8990 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
8992 size = AOP_SIZE (result) - 1;
8993 while (size--) emitcode ("lcall","__decdptr");
8996 freeAsmop (left, NULL, ic, TRUE);
8997 freeAsmop (result, NULL, ic, TRUE);
9000 /*-----------------------------------------------------------------*/
9001 /* genGenPointerGet - gget value from generic pointer space */
9002 /*-----------------------------------------------------------------*/
9004 genGenPointerGet (operand * left,
9005 operand * result, iCode * ic, iCode * pi)
9008 sym_link *retype = getSpec (operandType (result));
9009 sym_link *letype = getSpec (operandType (left));
9011 D (emitcode (";", "genGenPointerGet "); );
9013 aopOp (left, ic, FALSE, (OP_SYMBOL(left)->ruonly ? FALSE : TRUE));
9015 /* if the operand is already in dptr
9016 then we do nothing else we move the value to dptr */
9017 if (AOP_TYPE (left) != AOP_STR)
9019 /* if this is remateriazable */
9020 if (AOP_TYPE (left) == AOP_IMMD)
9022 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9023 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9024 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
9026 emitcode ("mov", "b,#%d", pointerCode (retype));
9029 { /* we need to get it byte by byte */
9030 _startLazyDPSEvaluation ();
9031 if (AOP(left)->type==AOP_DPTR2) {
9033 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
9036 emitcode ("mov", "dpl,%s", l);
9037 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
9040 emitcode ("mov", "dph,%s", l);
9041 if (options.model == MODEL_FLAT24) {
9042 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
9045 emitcode ("mov", "dpx,%s", l);
9046 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9048 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9051 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
9052 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
9053 if (options.model == MODEL_FLAT24) {
9054 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9055 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9057 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9060 _endLazyDPSEvaluation ();
9063 /* so dptr know contains the address */
9064 aopOp (result, ic, FALSE, TRUE);
9066 /* if bit then unpack */
9067 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9068 genUnpackBits (result, "dptr", GPOINTER);
9071 size = AOP_SIZE (result);
9076 emitcode ("lcall", "__gptrget");
9077 aopPut (AOP (result), "a", offset++);
9078 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9079 emitcode ("inc", "dptr");
9083 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9084 aopPut ( AOP (left), "dpl", 0);
9085 aopPut ( AOP (left), "dph", 1);
9086 if (options.model == MODEL_FLAT24) {
9087 aopPut ( AOP (left), "dpx", 2);
9088 aopPut ( AOP (left), "b", 3);
9089 } else aopPut ( AOP (left), "b", 2);
9091 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9092 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9094 size = AOP_SIZE (result) - 1;
9095 while (size--) emitcode ("lcall","__decdptr");
9098 freeAsmop (left, NULL, ic, TRUE);
9099 freeAsmop (result, NULL, ic, TRUE);
9102 /*-----------------------------------------------------------------*/
9103 /* genPointerGet - generate code for pointer get */
9104 /*-----------------------------------------------------------------*/
9106 genPointerGet (iCode * ic, iCode *pi)
9108 operand *left, *result;
9109 sym_link *type, *etype;
9112 D (emitcode (";", "genPointerGet ");
9115 left = IC_LEFT (ic);
9116 result = IC_RESULT (ic);
9118 /* depending on the type of pointer we need to
9119 move it to the correct pointer register */
9120 type = operandType (left);
9121 etype = getSpec (type);
9122 /* if left is of type of pointer then it is simple */
9123 if (IS_PTR (type) && !IS_FUNC (type->next))
9124 p_type = DCL_TYPE (type);
9127 /* we have to go by the storage class */
9128 p_type = PTR_TYPE (SPEC_OCLS (etype));
9130 /* special case when cast remat */
9131 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9132 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9133 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9134 type = type = operandType (left);
9135 p_type = DCL_TYPE (type);
9137 /* now that we have the pointer type we assign
9138 the pointer values */
9144 genNearPointerGet (left, result, ic, pi);
9148 genPagedPointerGet (left, result, ic, pi);
9152 genFarPointerGet (left, result, ic, pi);
9156 emitcodePointerGet (left, result, ic, pi);
9160 genGenPointerGet (left, result, ic, pi);
9166 /*-----------------------------------------------------------------*/
9167 /* genPackBits - generates code for packed bit storage */
9168 /*-----------------------------------------------------------------*/
9170 genPackBits (sym_link * etype,
9172 char *rname, int p_type)
9180 blen = SPEC_BLEN (etype);
9181 bstr = SPEC_BSTR (etype);
9183 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9186 /* if the bit lenth is less than or */
9187 /* it exactly fits a byte then */
9188 if (SPEC_BLEN (etype) <= 8)
9190 shCount = SPEC_BSTR (etype);
9192 /* shift left acc */
9195 if (SPEC_BLEN (etype) < 8)
9196 { /* if smaller than a byte */
9202 emitcode ("mov", "b,a");
9203 emitcode ("mov", "a,@%s", rname);
9207 emitcode ("mov", "b,a");
9208 emitcode ("movx", "a,@dptr");
9212 emitcode ("push", "b");
9213 emitcode ("push", "acc");
9214 emitcode ("lcall", "__gptrget");
9215 emitcode ("pop", "b");
9219 emitcode ("anl", "a,#0x%02x", (unsigned char)
9220 ((unsigned char) (0xFF << (blen + bstr)) |
9221 (unsigned char) (0xFF >> (8 - bstr))));
9222 emitcode ("orl", "a,b");
9223 if (p_type == GPOINTER)
9224 emitcode ("pop", "b");
9231 emitcode ("mov", "@%s,a", rname);
9235 emitcode ("movx", "@dptr,a");
9239 emitcode ("lcall", "__gptrput");
9244 if (SPEC_BLEN (etype) <= 8)
9247 emitcode ("inc", "%s", rname);
9248 rLen = SPEC_BLEN (etype);
9250 /* now generate for lengths greater than one byte */
9254 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9266 emitcode ("mov", "@%s,a", rname);
9269 emitcode ("mov", "@%s,%s", rname, l);
9274 emitcode ("movx", "@dptr,a");
9279 emitcode ("lcall", "__gptrput");
9282 emitcode ("inc", "%s", rname);
9287 /* last last was not complete */
9290 /* save the byte & read byte */
9294 emitcode ("mov", "b,a");
9295 emitcode ("mov", "a,@%s", rname);
9299 emitcode ("mov", "b,a");
9300 emitcode ("movx", "a,@dptr");
9304 emitcode ("push", "b");
9305 emitcode ("push", "acc");
9306 emitcode ("lcall", "__gptrget");
9307 emitcode ("pop", "b");
9311 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
9312 emitcode ("orl", "a,b");
9315 if (p_type == GPOINTER)
9316 emitcode ("pop", "b");
9322 emitcode ("mov", "@%s,a", rname);
9326 emitcode ("movx", "@dptr,a");
9330 emitcode ("lcall", "__gptrput");
9334 /*-----------------------------------------------------------------*/
9335 /* genDataPointerSet - remat pointer to data space */
9336 /*-----------------------------------------------------------------*/
9338 genDataPointerSet (operand * right,
9342 int size, offset = 0;
9343 char *l, buffer[256];
9345 aopOp (right, ic, FALSE, FALSE);
9347 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9348 size = AOP_SIZE (right);
9352 sprintf (buffer, "(%s + %d)", l + 1, offset);
9354 sprintf (buffer, "%s", l + 1);
9355 emitcode ("mov", "%s,%s", buffer,
9356 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9359 freeAsmop (right, NULL, ic, TRUE);
9360 freeAsmop (result, NULL, ic, TRUE);
9363 /*-----------------------------------------------------------------*/
9364 /* genNearPointerSet - emitcode for near pointer put */
9365 /*-----------------------------------------------------------------*/
9367 genNearPointerSet (operand * right,
9375 sym_link *retype, *letype;
9376 sym_link *ptype = operandType (result);
9378 retype = getSpec (operandType (right));
9379 letype = getSpec (ptype);
9381 aopOp (result, ic, FALSE, FALSE);
9383 /* if the result is rematerializable &
9384 in data space & not a bit variable */
9385 if (AOP_TYPE (result) == AOP_IMMD &&
9386 DCL_TYPE (ptype) == POINTER &&
9387 !IS_BITVAR (retype) &&
9388 !IS_BITVAR (letype))
9390 genDataPointerSet (right, result, ic);
9394 /* if the value is already in a pointer register
9395 then don't need anything more */
9396 if (!AOP_INPREG (AOP (result)))
9398 /* otherwise get a free pointer register */
9400 preg = getFreePtr (ic, &aop, FALSE);
9401 emitcode ("mov", "%s,%s",
9403 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9407 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9409 aopOp (right, ic, FALSE, FALSE);
9411 /* if bitfield then unpack the bits */
9412 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9413 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9416 /* we have can just get the values */
9417 int size = AOP_SIZE (right);
9422 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9426 emitcode ("mov", "@%s,a", rname);
9429 emitcode ("mov", "@%s,%s", rname, l);
9431 emitcode ("inc", "%s", rname);
9436 /* now some housekeeping stuff */
9439 /* we had to allocate for this iCode */
9440 if (pi) aopPut (AOP (result),rname,0);
9441 freeAsmop (NULL, aop, ic, TRUE);
9445 /* we did not allocate which means left
9446 already in a pointer register, then
9447 if size > 0 && this could be used again
9448 we have to point it back to where it
9450 if (AOP_SIZE (right) > 1 &&
9451 !OP_SYMBOL (result)->remat &&
9452 (OP_SYMBOL (result)->liveTo > ic->seq ||
9456 int size = AOP_SIZE (right) - 1;
9458 emitcode ("dec", "%s", rname);
9463 if (pi) pi->generated = 1;
9464 freeAsmop (result, NULL, ic, TRUE);
9465 freeAsmop (right, NULL, ic, TRUE);
9470 /*-----------------------------------------------------------------*/
9471 /* genPagedPointerSet - emitcode for Paged pointer put */
9472 /*-----------------------------------------------------------------*/
9474 genPagedPointerSet (operand * right,
9482 sym_link *retype, *letype;
9484 retype = getSpec (operandType (right));
9485 letype = getSpec (operandType (result));
9487 aopOp (result, ic, FALSE, FALSE);
9489 /* if the value is already in a pointer register
9490 then don't need anything more */
9491 if (!AOP_INPREG (AOP (result)))
9493 /* otherwise get a free pointer register */
9495 preg = getFreePtr (ic, &aop, FALSE);
9496 emitcode ("mov", "%s,%s",
9498 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9502 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9504 aopOp (right, ic, FALSE, FALSE);
9506 /* if bitfield then unpack the bits */
9507 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9508 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9511 /* we have can just get the values */
9512 int size = AOP_SIZE (right);
9517 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9520 emitcode ("movx", "@%s,a", rname);
9523 emitcode ("inc", "%s", rname);
9529 /* now some housekeeping stuff */
9532 if (pi) aopPut (AOP (result),rname,0);
9533 /* we had to allocate for this iCode */
9534 freeAsmop (NULL, aop, ic, TRUE);
9538 /* we did not allocate which means left
9539 already in a pointer register, then
9540 if size > 0 && this could be used again
9541 we have to point it back to where it
9543 if (AOP_SIZE (right) > 1 &&
9544 !OP_SYMBOL (result)->remat &&
9545 (OP_SYMBOL (result)->liveTo > ic->seq ||
9549 int size = AOP_SIZE (right) - 1;
9551 emitcode ("dec", "%s", rname);
9556 if (pi) pi->generated = 1;
9557 freeAsmop (result, NULL, ic, TRUE);
9558 freeAsmop (right, NULL, ic, TRUE);
9563 /*-----------------------------------------------------------------*/
9564 /* genFarPointerSet - set value from far space */
9565 /*-----------------------------------------------------------------*/
9567 genFarPointerSet (operand * right,
9568 operand * result, iCode * ic, iCode *pi)
9571 sym_link *retype = getSpec (operandType (right));
9572 sym_link *letype = getSpec (operandType (result));
9574 aopOp (result, ic, FALSE, FALSE);
9576 /* if the operand is already in dptr
9577 then we do nothing else we move the value to dptr */
9578 if (AOP_TYPE (result) != AOP_STR)
9580 /* if this is remateriazable */
9581 if (AOP_TYPE (result) == AOP_IMMD)
9582 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9585 /* we need to get it byte by byte */
9586 _startLazyDPSEvaluation ();
9587 if (AOP_TYPE (result) != AOP_DPTR)
9589 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9590 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9591 if (options.model == MODEL_FLAT24)
9592 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9596 /* We need to generate a load to DPTR indirect through DPTR. */
9597 D (emitcode (";", "genFarPointerSet -- indirection special case.");
9599 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9600 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9601 if (options.model == MODEL_FLAT24)
9602 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9603 emitcode ("pop", "dph");
9604 emitcode ("pop", "dpl");
9606 _endLazyDPSEvaluation ();
9609 /* so dptr know contains the address */
9610 aopOp (right, ic, FALSE, TRUE);
9612 /* if bit then unpack */
9613 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9614 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9617 size = AOP_SIZE (right);
9620 _startLazyDPSEvaluation ();
9623 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9629 emitcode ("movx", "@dptr,a");
9630 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
9631 emitcode ("inc", "dptr");
9633 _endLazyDPSEvaluation ();
9636 if (pi && AOP_TYPE (result) != AOP_IMMD) {
9637 aopPut (AOP(result),"dpl",0);
9638 aopPut (AOP(result),"dph",1);
9639 if (options.model == MODEL_FLAT24)
9640 aopPut (AOP(result),"dpx",2);
9642 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9643 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9645 size = AOP_SIZE (right) - 1;
9646 while (size--) emitcode ("lcall","__decdptr");
9648 freeAsmop (result, NULL, ic, TRUE);
9649 freeAsmop (right, NULL, ic, TRUE);
9652 /*-----------------------------------------------------------------*/
9653 /* genGenPointerSet - set value from generic pointer space */
9654 /*-----------------------------------------------------------------*/
9656 genGenPointerSet (operand * right,
9657 operand * result, iCode * ic, iCode *pi)
9660 sym_link *retype = getSpec (operandType (right));
9661 sym_link *letype = getSpec (operandType (result));
9663 aopOp (result, ic, FALSE, OP_SYMBOL(result)->ruonly ? FALSE : TRUE);
9665 /* if the operand is already in dptr
9666 then we do nothing else we move the value to dptr */
9667 if (AOP_TYPE (result) != AOP_STR)
9669 _startLazyDPSEvaluation ();
9670 /* if this is remateriazable */
9671 if (AOP_TYPE (result) == AOP_IMMD)
9673 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9674 if (AOP(result)->aopu.aop_immd.from_cast_remat)
9675 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
9677 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9680 { /* we need to get it byte by byte */
9681 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9682 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9683 if (options.model == MODEL_FLAT24) {
9684 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9685 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9687 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9690 _endLazyDPSEvaluation ();
9692 /* so dptr know contains the address */
9693 aopOp (right, ic, FALSE, TRUE);
9695 /* if bit then unpack */
9696 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9697 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9700 size = AOP_SIZE (right);
9703 _startLazyDPSEvaluation ();
9706 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9712 emitcode ("lcall", "__gptrput");
9713 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
9714 emitcode ("inc", "dptr");
9716 _endLazyDPSEvaluation ();
9719 if (pi && AOP_TYPE (result) != AOP_IMMD) {
9720 aopPut (AOP(result),"dpl",0);
9721 aopPut (AOP(result),"dph",1);
9722 if (options.model == MODEL_FLAT24) {
9723 aopPut (AOP(result),"dpx",2);
9724 aopPut (AOP(result),"b",3);
9726 aopPut (AOP(result),"b",2);
9729 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9730 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9732 size = AOP_SIZE (right) - 1;
9733 while (size--) emitcode ("lcall","__decdptr");
9735 freeAsmop (result, NULL, ic, TRUE);
9736 freeAsmop (right, NULL, ic, TRUE);
9739 /*-----------------------------------------------------------------*/
9740 /* genPointerSet - stores the value into a pointer location */
9741 /*-----------------------------------------------------------------*/
9743 genPointerSet (iCode * ic, iCode *pi)
9745 operand *right, *result;
9746 sym_link *type, *etype;
9749 D (emitcode (";", "genPointerSet ");
9752 right = IC_RIGHT (ic);
9753 result = IC_RESULT (ic);
9755 /* depending on the type of pointer we need to
9756 move it to the correct pointer register */
9757 type = operandType (result);
9758 etype = getSpec (type);
9759 /* if left is of type of pointer then it is simple */
9760 if (IS_PTR (type) && !IS_FUNC (type->next))
9762 p_type = DCL_TYPE (type);
9766 /* we have to go by the storage class */
9767 p_type = PTR_TYPE (SPEC_OCLS (etype));
9769 /* special case when cast remat */
9770 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9771 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9772 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9773 type = type = operandType (result);
9774 p_type = DCL_TYPE (type);
9777 /* now that we have the pointer type we assign
9778 the pointer values */
9784 genNearPointerSet (right, result, ic, pi);
9788 genPagedPointerSet (right, result, ic, pi);
9792 genFarPointerSet (right, result, ic, pi);
9796 genGenPointerSet (right, result, ic, pi);
9802 /*-----------------------------------------------------------------*/
9803 /* genIfx - generate code for Ifx statement */
9804 /*-----------------------------------------------------------------*/
9806 genIfx (iCode * ic, iCode * popIc)
9808 operand *cond = IC_COND (ic);
9811 D (emitcode (";", "genIfx "););
9813 aopOp (cond, ic, FALSE, FALSE);
9815 /* get the value into acc */
9816 if (AOP_TYPE (cond) != AOP_CRY)
9820 /* the result is now in the accumulator */
9821 freeAsmop (cond, NULL, ic, TRUE);
9823 /* if there was something to be popped then do it */
9827 /* if the condition is a bit variable */
9828 if (isbit && IS_ITEMP (cond) &&
9830 genIfxJump (ic, SPIL_LOC (cond)->rname);
9831 else if (isbit && !IS_ITEMP (cond))
9832 genIfxJump (ic, OP_SYMBOL (cond)->rname);
9834 genIfxJump (ic, "a");
9839 /*-----------------------------------------------------------------*/
9840 /* genAddrOf - generates code for address of */
9841 /*-----------------------------------------------------------------*/
9843 genAddrOf (iCode * ic)
9845 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9848 D (emitcode (";", "genAddrOf ");
9851 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9853 /* if the operand is on the stack then we
9854 need to get the stack offset of this
9858 /* if 10 bit stack */
9859 if (options.stack10bit) {
9860 /* if it has an offset then we need to compute it */
9862 emitcode ("mov", "a,_bpx");
9863 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9864 emitcode ("mov", "b,a");
9865 emitcode ("mov", "a,_bpx+1");
9866 emitcode ("addc","a,#0x%02x", (((short) sym->stack) >> 8) & 0xff);
9867 aopPut (AOP (IC_RESULT (ic)), "b", 0);
9868 aopPut (AOP (IC_RESULT (ic)), "a", 1);
9869 aopPut (AOP (IC_RESULT (ic)), "#0x40", 2);
9871 /* we can just move _bp */
9872 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
9873 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
9874 aopPut (AOP (IC_RESULT (ic)), "#0x40", 2);
9877 /* if it has an offset then we need to compute it */
9879 emitcode ("mov", "a,_bp");
9880 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9881 aopPut (AOP (IC_RESULT (ic)), "a", 0);
9883 /* we can just move _bp */
9884 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9886 /* fill the result with zero */
9887 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9890 if (options.stack10bit && size < (FPTRSIZE - 1)) {
9892 "*** warning: pointer to stack var truncated.\n");
9897 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9903 /* object not on stack then we need the name */
9904 size = AOP_SIZE (IC_RESULT (ic));
9909 char s[SDCC_NAME_MAX];
9911 sprintf (s, "#(%s >> %d)",
9915 sprintf (s, "#%s", sym->rname);
9916 aopPut (AOP (IC_RESULT (ic)), s, offset++);
9920 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9924 /*-----------------------------------------------------------------*/
9925 /* genArrayInit - generates code for address of */
9926 /*-----------------------------------------------------------------*/
9928 genArrayInit (iCode * ic)
9932 int elementSize = 0, eIndex;
9933 unsigned val, lastVal;
9935 operand *left=IC_LEFT(ic);
9937 D (emitcode (";", "genArrayInit "););
9939 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
9941 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
9943 // Load immediate value into DPTR.
9944 emitcode("mov", "dptr, %s",
9945 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
9947 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
9950 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9951 "Unexpected operand to genArrayInit.\n");
9954 // a regression because of SDCCcse.c:1.52
9955 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9956 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9957 if (options.model == MODEL_FLAT24)
9958 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9962 type = operandType(IC_LEFT(ic));
9964 if (type && type->next)
9966 elementSize = getSize(type->next);
9970 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9971 "can't determine element size in genArrayInit.\n");
9975 iLoop = IC_ARRAYILIST(ic);
9980 bool firstpass = TRUE;
9982 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
9983 iLoop->count, (int)iLoop->literalValue, elementSize);
9989 symbol *tlbl = NULL;
9991 count = ix > 256 ? 256 : ix;
9995 tlbl = newiTempLabel (NULL);
9996 if (firstpass || (count & 0xff))
9998 emitcode("mov", "b, #0x%x", count & 0xff);
10001 emitcode ("", "%05d$:", tlbl->key + 100);
10006 for (eIndex = 0; eIndex < elementSize; eIndex++)
10008 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10009 if (val != lastVal)
10011 emitcode("mov", "a, #0x%x", val);
10015 emitcode("movx", "@dptr, a");
10016 emitcode("inc", "dptr");
10021 emitcode("djnz", "b, %05d$", tlbl->key + 100);
10027 iLoop = iLoop->next;
10030 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10033 /*-----------------------------------------------------------------*/
10034 /* genFarFarAssign - assignment when both are in far space */
10035 /*-----------------------------------------------------------------*/
10037 genFarFarAssign (operand * result, operand * right, iCode * ic)
10039 int size = AOP_SIZE (right);
10041 symbol *rSym = NULL;
10045 /* quick & easy case. */
10046 D(emitcode(";","genFarFarAssign (1 byte case)"););
10047 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
10048 freeAsmop (right, NULL, ic, FALSE);
10049 /* now assign DPTR to result */
10051 aopOp(result, ic, FALSE, FALSE);
10053 aopPut(AOP(result), "a", 0);
10054 freeAsmop(result, NULL, ic, FALSE);
10058 /* See if we've got an underlying symbol to abuse. */
10059 if (IS_SYMOP(result) && OP_SYMBOL(result))
10061 if (IS_TRUE_SYMOP(result))
10063 rSym = OP_SYMBOL(result);
10065 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10067 rSym = OP_SYMBOL(result)->usl.spillLoc;
10071 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10073 /* We can use the '390 auto-toggle feature to good effect here. */
10075 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10076 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
10077 emitcode ("mov", "dptr,#%s", rSym->rname);
10078 /* DP2 = result, DP1 = right, DP1 is current. */
10081 emitcode("movx", "a,@dptr");
10082 emitcode("movx", "@dptr,a");
10085 emitcode("inc", "dptr");
10086 emitcode("inc", "dptr");
10089 emitcode("mov", "dps, #0");
10090 freeAsmop (right, NULL, ic, FALSE);
10092 some alternative code for processors without auto-toggle
10093 no time to test now, so later well put in...kpb
10094 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10095 emitcode("mov", "dps, #0x01"); /* Select DPTR2. */
10096 emitcode ("mov", "dptr,#%s", rSym->rname);
10097 /* DP2 = result, DP1 = right, DP1 is current. */
10101 emitcode("movx", "a,@dptr");
10103 emitcode("inc", "dptr");
10104 emitcode("inc", "dps");
10105 emitcode("movx", "@dptr,a");
10107 emitcode("inc", "dptr");
10108 emitcode("inc", "dps");
10110 emitcode("mov", "dps, #0");
10111 freeAsmop (right, NULL, ic, FALSE);
10116 D (emitcode (";", "genFarFarAssign"););
10117 aopOp (result, ic, TRUE, TRUE);
10119 _startLazyDPSEvaluation ();
10123 aopPut (AOP (result),
10124 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10127 _endLazyDPSEvaluation ();
10128 freeAsmop (result, NULL, ic, FALSE);
10129 freeAsmop (right, NULL, ic, FALSE);
10133 /*-----------------------------------------------------------------*/
10134 /* genAssign - generate code for assignment */
10135 /*-----------------------------------------------------------------*/
10137 genAssign (iCode * ic)
10139 operand *result, *right;
10141 unsigned long lit = 0L;
10143 D (emitcode (";", "genAssign ");
10146 result = IC_RESULT (ic);
10147 right = IC_RIGHT (ic);
10149 /* if they are the same */
10150 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10153 aopOp (right, ic, FALSE, FALSE);
10155 emitcode (";", "genAssign: resultIsFar = %s",
10156 isOperandInFarSpace (result) ?
10159 /* special case both in far space */
10160 if ((AOP_TYPE (right) == AOP_DPTR ||
10161 AOP_TYPE (right) == AOP_DPTR2) &&
10162 /* IS_TRUE_SYMOP(result) && */
10163 isOperandInFarSpace (result))
10165 genFarFarAssign (result, right, ic);
10169 aopOp (result, ic, TRUE, FALSE);
10171 /* if they are the same registers */
10172 if (sameRegs (AOP (right), AOP (result)))
10175 /* if the result is a bit */
10176 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10178 /* if the right size is a literal then
10179 we know what the value is */
10180 if (AOP_TYPE (right) == AOP_LIT)
10182 if (((int) operandLitValue (right)))
10183 aopPut (AOP (result), one, 0);
10185 aopPut (AOP (result), zero, 0);
10189 /* the right is also a bit variable */
10190 if (AOP_TYPE (right) == AOP_CRY)
10192 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10193 aopPut (AOP (result), "c", 0);
10197 /* we need to or */
10199 aopPut (AOP (result), "a", 0);
10203 /* bit variables done */
10205 size = AOP_SIZE (result);
10207 if (AOP_TYPE (right) == AOP_LIT)
10208 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10211 (AOP_TYPE (result) != AOP_REG) &&
10212 (AOP_TYPE (right) == AOP_LIT) &&
10213 !IS_FLOAT (operandType (right)))
10215 _startLazyDPSEvaluation ();
10216 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10218 aopPut (AOP (result),
10219 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10224 /* And now fill the rest with zeros. */
10227 emitcode ("clr", "a");
10231 aopPut (AOP (result), "a", offset++);
10233 _endLazyDPSEvaluation ();
10237 _startLazyDPSEvaluation ();
10240 aopPut (AOP (result),
10241 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10245 _endLazyDPSEvaluation ();
10249 freeAsmop (right, NULL, ic, FALSE);
10250 freeAsmop (result, NULL, ic, TRUE);
10253 /*-----------------------------------------------------------------*/
10254 /* genJumpTab - generates code for jump table */
10255 /*-----------------------------------------------------------------*/
10257 genJumpTab (iCode * ic)
10262 D (emitcode (";", "genJumpTab ");
10265 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10266 /* get the condition into accumulator */
10267 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10269 /* multiply by four! */
10270 emitcode ("add", "a,acc");
10271 emitcode ("add", "a,acc");
10272 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10274 jtab = newiTempLabel (NULL);
10275 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10276 emitcode ("jmp", "@a+dptr");
10277 emitcode ("", "%05d$:", jtab->key + 100);
10278 /* now generate the jump labels */
10279 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10280 jtab = setNextItem (IC_JTLABELS (ic)))
10281 emitcode ("ljmp", "%05d$", jtab->key + 100);
10285 /*-----------------------------------------------------------------*/
10286 /* genCast - gen code for casting */
10287 /*-----------------------------------------------------------------*/
10289 genCast (iCode * ic)
10291 operand *result = IC_RESULT (ic);
10292 sym_link *ctype = operandType (IC_LEFT (ic));
10293 sym_link *rtype = operandType (IC_RIGHT (ic));
10294 operand *right = IC_RIGHT (ic);
10297 D (emitcode (";", "genCast ");
10300 /* if they are equivalent then do nothing */
10301 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10304 aopOp (right, ic, FALSE, FALSE);
10305 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10307 /* if the result is a bit */
10308 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10309 if (IS_BITVAR(OP_SYMBOL(result)->type))
10311 /* if the right size is a literal then
10312 we know what the value is */
10313 if (AOP_TYPE (right) == AOP_LIT)
10315 if (((int) operandLitValue (right)))
10316 aopPut (AOP (result), one, 0);
10318 aopPut (AOP (result), zero, 0);
10323 /* the right is also a bit variable */
10324 if (AOP_TYPE (right) == AOP_CRY)
10326 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10327 aopPut (AOP (result), "c", 0);
10331 /* we need to or */
10333 aopPut (AOP (result), "a", 0);
10337 /* if they are the same size : or less */
10338 if (AOP_SIZE (result) <= AOP_SIZE (right))
10341 /* if they are in the same place */
10342 if (sameRegs (AOP (right), AOP (result)))
10345 /* if they in different places then copy */
10346 size = AOP_SIZE (result);
10348 _startLazyDPSEvaluation ();
10351 aopPut (AOP (result),
10352 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10356 _endLazyDPSEvaluation ();
10361 /* if the result is of type pointer */
10362 if (IS_PTR (ctype))
10366 sym_link *type = operandType (right);
10368 /* pointer to generic pointer */
10369 if (IS_GENPTR (ctype))
10375 p_type = DCL_TYPE (type);
10379 #if OLD_CAST_BEHAVIOR
10380 /* KV: we are converting a non-pointer type to
10381 * a generic pointer. This (ifdef'd out) code
10382 * says that the resulting generic pointer
10383 * should have the same class as the storage
10384 * location of the non-pointer variable.
10386 * For example, converting an int (which happens
10387 * to be stored in DATA space) to a pointer results
10388 * in a DATA generic pointer; if the original int
10389 * in XDATA space, so will be the resulting pointer.
10391 * I don't like that behavior, and thus this change:
10392 * all such conversions will be forced to XDATA and
10393 * throw a warning. If you want some non-XDATA
10394 * type, or you want to suppress the warning, you
10395 * must go through an intermediate cast, like so:
10397 * char _generic *gp = (char _xdata *)(intVar);
10399 sym_link *etype = getSpec (type);
10401 /* we have to go by the storage class */
10402 if (SPEC_OCLS (etype) != generic)
10404 p_type = PTR_TYPE (SPEC_OCLS (etype));
10409 /* Converting unknown class (i.e. register variable)
10410 * to generic pointer. This is not good, but
10411 * we'll make a guess (and throw a warning).
10414 werror (W_INT_TO_GEN_PTR_CAST);
10418 /* the first two bytes are known */
10419 size = GPTRSIZE - 1;
10421 _startLazyDPSEvaluation ();
10424 aopPut (AOP (result),
10425 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10429 _endLazyDPSEvaluation ();
10431 /* the last byte depending on type */
10449 /* this should never happen */
10450 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10451 "got unknown pointer type");
10454 aopPut (AOP (result), l, GPTRSIZE - 1);
10458 /* just copy the pointers */
10459 size = AOP_SIZE (result);
10461 _startLazyDPSEvaluation ();
10464 aopPut (AOP (result),
10465 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10469 _endLazyDPSEvaluation ();
10473 /* so we now know that the size of destination is greater
10474 than the size of the source */
10475 /* we move to result for the size of source */
10476 size = AOP_SIZE (right);
10478 _startLazyDPSEvaluation ();
10481 aopPut (AOP (result),
10482 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10486 _endLazyDPSEvaluation ();
10488 /* now depending on the sign of the source && destination */
10489 size = AOP_SIZE (result) - AOP_SIZE (right);
10490 /* if unsigned or not an integral type */
10491 /* also, if the source is a bit, we don't need to sign extend, because
10492 * it can't possibly have set the sign bit.
10494 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10498 aopPut (AOP (result), zero, offset++);
10503 /* we need to extend the sign :{ */
10504 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10505 FALSE, FALSE, TRUE);
10507 emitcode ("rlc", "a");
10508 emitcode ("subb", "a,acc");
10510 aopPut (AOP (result), "a", offset++);
10513 /* we are done hurray !!!! */
10516 freeAsmop (right, NULL, ic, TRUE);
10517 freeAsmop (result, NULL, ic, TRUE);
10521 /*-----------------------------------------------------------------*/
10522 /* genDjnz - generate decrement & jump if not zero instrucion */
10523 /*-----------------------------------------------------------------*/
10525 genDjnz (iCode * ic, iCode * ifx)
10527 symbol *lbl, *lbl1;
10531 /* if the if condition has a false label
10532 then we cannot save */
10533 if (IC_FALSE (ifx))
10536 /* if the minus is not of the form
10538 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10539 !IS_OP_LITERAL (IC_RIGHT (ic)))
10542 if (operandLitValue (IC_RIGHT (ic)) != 1)
10545 /* if the size of this greater than one then no
10547 if (getSize (operandType (IC_RESULT (ic))) > 1)
10550 /* otherwise we can save BIG */
10551 D(emitcode(";", "genDjnz"););
10553 lbl = newiTempLabel (NULL);
10554 lbl1 = newiTempLabel (NULL);
10556 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10558 if (AOP_NEEDSACC(IC_RESULT(ic)))
10560 /* If the result is accessed indirectly via
10561 * the accumulator, we must explicitly write
10562 * it back after the decrement.
10564 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10566 if (strcmp(rByte, "a"))
10568 /* Something is hopelessly wrong */
10569 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10570 __FILE__, __LINE__);
10571 /* We can just give up; the generated code will be inefficient,
10572 * but what the hey.
10574 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10577 emitcode ("dec", "%s", rByte);
10578 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10579 emitcode ("jnz", "%05d$", lbl->key + 100);
10581 else if (IS_AOP_PREG (IC_RESULT (ic)))
10583 emitcode ("dec", "%s",
10584 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10585 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10586 emitcode ("jnz", "%05d$", lbl->key + 100);
10590 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10593 emitcode ("sjmp", "%05d$", lbl1->key + 100);
10594 emitcode ("", "%05d$:", lbl->key + 100);
10595 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10596 emitcode ("", "%05d$:", lbl1->key + 100);
10598 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10599 ifx->generated = 1;
10603 /*-----------------------------------------------------------------*/
10604 /* genReceive - generate code for a receive iCode */
10605 /*-----------------------------------------------------------------*/
10607 genReceive (iCode * ic)
10610 D (emitcode (";", "genReceive ");
10613 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10614 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10615 IS_TRUE_SYMOP (IC_RESULT (ic))))
10617 int size = getSize (operandType (IC_RESULT (ic)));
10618 int offset = fReturnSizeDS390 - size;
10621 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10622 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10625 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10626 size = AOP_SIZE (IC_RESULT (ic));
10630 emitcode ("pop", "acc");
10631 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10638 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10640 assignResultValue (IC_RESULT (ic));
10643 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10646 /*-----------------------------------------------------------------*/
10647 /* gen390Code - generate code for Dallas 390 based controllers */
10648 /*-----------------------------------------------------------------*/
10650 gen390Code (iCode * lic)
10655 lineHead = lineCurr = NULL;
10657 if (options.model == MODEL_FLAT24) {
10658 fReturnSizeDS390 = 5;
10659 fReturn = fReturn24;
10661 fReturnSizeDS390 = 4;
10662 fReturn = fReturn16;
10663 options.stack10bit=0;
10667 /* print the allocation information */
10669 printAllocInfo (currFunc, codeOutFile);
10671 /* if debug information required */
10672 if (options.debug && currFunc)
10674 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
10676 if (IS_STATIC (currFunc->etype))
10677 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
10679 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
10682 /* stack pointer name */
10683 if (options.useXstack)
10689 for (ic = lic; ic; ic = ic->next)
10692 if (cln != ic->lineno)
10697 emitcode ("", "C$%s$%d$%d$%d ==.",
10698 FileBaseName (ic->filename), ic->lineno,
10699 ic->level, ic->block);
10702 emitcode (";", "%s %d", ic->filename, ic->lineno);
10705 /* if the result is marked as
10706 spilt and rematerializable or code for
10707 this has already been generated then
10709 if (resultRemat (ic) || ic->generated)
10712 /* depending on the operation */
10732 /* IPOP happens only when trying to restore a
10733 spilt live range, if there is an ifx statement
10734 following this pop then the if statement might
10735 be using some of the registers being popped which
10736 would destory the contents of the register so
10737 we need to check for this condition and handle it */
10739 ic->next->op == IFX &&
10740 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10741 genIfx (ic->next, ic);
10759 genEndFunction (ic);
10779 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10796 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10800 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10807 /* note these two are xlated by algebraic equivalence
10808 during parsing SDCC.y */
10809 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10810 "got '>=' or '<=' shouldn't have come here");
10814 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10826 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10830 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10834 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10858 genRightShift (ic);
10861 case GET_VALUE_AT_ADDRESS:
10862 genPointerGet (ic,hasInc(IC_LEFT(ic),ic));
10866 if (POINTER_SET (ic))
10867 genPointerSet (ic,hasInc(IC_RESULT(ic),ic));
10893 addSet (&_G.sendSet, ic);
10906 /* now we are ready to call the
10907 peep hole optimizer */
10908 if (!options.nopeep)
10909 peepHole (&lineHead);
10911 /* now do the actual printing */
10912 printLine (lineHead, codeOutFile);