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);
61 /* this is the down and dirty file with all kinds of
62 kludgy & hacky stuff. This is what it is all about
63 CODE GENERATION for a specific MCU . some of the
64 routines may be reusable, will have to see */
66 static char *zero = "#0";
67 static char *one = "#1";
72 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
73 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
75 unsigned fReturnSizeDS390 = 5; /* shared with ralloc.c */
76 static char *fReturn24[] =
77 {"dpl", "dph", "dpx", "b", "a"};
78 static char *fReturn16[] =
79 {"dpl", "dph", "b", "a"};
80 static char **fReturn = fReturn24;
81 static char *accUse[] =
83 static char *javaRet[] = { "r0","r1","r2","r3"};
84 static short rbank = -1;
99 static void saveRBank (int, iCode *, bool);
101 #define RESULTONSTACK(x) \
102 (IC_RESULT(x) && IC_RESULT(x)->aop && \
103 IC_RESULT(x)->aop->type == AOP_STK )
105 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
106 #define MOVA(x) { char *_mova_tmp = strdup(x); \
107 if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
109 emitcode("mov","a,%s",_mova_tmp); \
113 #define CLRC emitcode("clr","c")
114 #define SETC emitcode("setb","c")
116 // A scratch register which will be used to hold
117 // result bytes from operands in far space via DPTR2.
118 #define DP2_RESULT_REG "_ap"
120 static lineNode *lineHead = NULL;
121 static lineNode *lineCurr = NULL;
123 static unsigned char SLMask[] =
124 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
125 0xE0, 0xC0, 0x80, 0x00};
126 static unsigned char SRMask[] =
127 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
128 0x07, 0x03, 0x01, 0x00};
135 /*-----------------------------------------------------------------*/
136 /* emitcode - writes the code into a file : for now it is simple */
137 /*-----------------------------------------------------------------*/
139 emitcode (char *inst, char *fmt,...)
142 char lb[INITIAL_INLINEASM];
150 sprintf (lb, "%s\t", inst);
152 sprintf (lb, "%s", inst);
153 tvsprintf (lb + (strlen (lb)), fmt, ap);
156 tvsprintf (lb, fmt, ap);
158 while (isspace (*lbp))
162 lineCurr = (lineCurr ?
163 connectLine (lineCurr, newLineNode (lb)) :
164 (lineHead = newLineNode (lb)));
165 lineCurr->isInline = _G.inLine;
166 lineCurr->isDebug = _G.debugLine;
170 /*-----------------------------------------------------------------*/
171 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
172 /*-----------------------------------------------------------------*/
174 getFreePtr (iCode * ic, asmop ** aopp, bool result)
176 bool r0iu = FALSE, r1iu = FALSE;
177 bool r0ou = FALSE, r1ou = FALSE;
179 /* the logic: if r0 & r1 used in the instruction
180 then we are in trouble otherwise */
182 /* first check if r0 & r1 are used by this
183 instruction, in which case we are in trouble */
184 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
185 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
190 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
191 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
193 /* if no usage of r0 then return it */
196 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
197 (*aopp)->type = AOP_R0;
199 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
202 /* if no usage of r1 then return it */
205 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
206 (*aopp)->type = AOP_R1;
208 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
211 /* now we know they both have usage */
212 /* if r0 not used in this instruction */
215 /* push it if not already pushed */
218 emitcode ("push", "%s",
219 ds390_regWithIdx (R0_IDX)->dname);
223 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
224 (*aopp)->type = AOP_R0;
226 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
229 /* if r1 not used then */
233 /* push it if not already pushed */
236 emitcode ("push", "%s",
237 ds390_regWithIdx (R1_IDX)->dname);
241 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
242 (*aopp)->type = AOP_R1;
243 return ds390_regWithIdx (R1_IDX);
247 /* I said end of world but not quite end of world yet */
248 /* if this is a result then we can push it on the stack */
251 (*aopp)->type = AOP_STK;
255 /* other wise this is true end of the world */
256 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
257 "getFreePtr should never reach here");
261 /*-----------------------------------------------------------------*/
262 /* newAsmop - creates a new asmOp */
263 /*-----------------------------------------------------------------*/
265 newAsmop (short type)
269 aop = Safe_calloc (1, sizeof (asmop));
274 static int _currentDPS; /* Current processor DPS. */
275 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
276 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
278 /*-----------------------------------------------------------------*/
279 /* genSetDPTR: generate code to select which DPTR is in use (zero */
280 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
281 /* alternate DPTR (DPL1/DPH1/DPX1). */
282 /*-----------------------------------------------------------------*/
287 /* If we are doing lazy evaluation, simply note the desired
288 * change, but don't emit any code yet.
298 emitcode ("mov", "dps,#0");
303 emitcode ("mov", "dps,#1");
307 /*-----------------------------------------------------------------*/
308 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
310 /* Any code that operates on DPTR (NB: not on the individual */
311 /* components, like DPH) *must* call _flushLazyDPS() before using */
312 /* DPTR within a lazy DPS evaluation block. */
314 /* Note that aopPut and aopGet already contain the proper calls to */
315 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
316 /* DPS evaluation block. */
318 /* Also, _flushLazyDPS must be called before any flow control */
319 /* operations that could potentially branch out of the block. */
321 /* Lazy DPS evaluation is simply an optimization (though an */
322 /* important one), so if in doubt, leave it out. */
323 /*-----------------------------------------------------------------*/
325 _startLazyDPSEvaluation (void)
329 #ifdef BETTER_LITERAL_SHIFT
336 /*-----------------------------------------------------------------*/
337 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
338 /* desired one. Call before using DPTR within a lazy DPS evaluation */
340 /*-----------------------------------------------------------------*/
350 if (_desiredDPS != _currentDPS)
354 emitcode ("inc", "dps");
358 emitcode ("dec", "dps");
360 _currentDPS = _desiredDPS;
364 /*-----------------------------------------------------------------*/
365 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
367 /* Forces us back to the safe state (standard DPTR selected). */
368 /*-----------------------------------------------------------------*/
370 _endLazyDPSEvaluation (void)
372 #ifdef BETTER_LITERAL_SHIFT
391 /*-----------------------------------------------------------------*/
392 /* pointerCode - returns the code for a pointer type */
393 /*-----------------------------------------------------------------*/
395 pointerCode (sym_link * etype)
398 return PTR_TYPE (SPEC_OCLS (etype));
402 /*-----------------------------------------------------------------*/
403 /* aopForSym - for a true symbol */
404 /*-----------------------------------------------------------------*/
406 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
409 memmap *space = SPEC_OCLS (sym->etype);
411 /* if already has one */
415 /* assign depending on the storage class */
416 /* if it is on the stack or indirectly addressable */
417 /* space we need to assign either r0 or r1 to it */
418 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
420 sym->aop = aop = newAsmop (0);
421 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
422 aop->size = getSize (sym->type);
424 /* now assign the address of the variable to
425 the pointer register */
426 if (aop->type != AOP_STK)
432 emitcode ("push", "acc");
435 emitcode ("push", "b");
437 emitcode ("mov", "a,_bp");
438 emitcode ("add", "a,#!constbyte",
440 ((char) (sym->stack - _G.nRegsSaved)) :
441 ((char) sym->stack)) & 0xff);
442 emitcode ("mov", "%s,a",
443 aop->aopu.aop_ptr->name);
446 emitcode ("pop", "b");
449 emitcode ("pop", "acc");
452 emitcode ("mov", "%s,#%s",
453 aop->aopu.aop_ptr->name,
455 aop->paged = space->paged;
458 aop->aopu.aop_stk = sym->stack;
462 if (sym->onStack && options.stack10bit)
464 short stack_val = -((sym->stack < 0) ?
465 ((short) (sym->stack - _G.nRegsSaved)) :
466 ((short) sym->stack)) ;
467 /* It's on the 10 bit stack, which is located in
470 if (stack_val < 0 && stack_val > -3) { /* between -3 & -1 */
472 if (options.model == MODEL_FLAT24)
473 emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
475 emitcode ("mov", "dph1,_bpx+1");
476 emitcode ("mov", "dpl1,_bpx");
477 emitcode ("mov","dps,#1");
479 if (options.model == MODEL_FLAT24)
480 emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
481 emitcode ("mov", "dph,_bpx+1");
482 emitcode ("mov", "dpl,_bpx");
484 stack_val = -stack_val;
485 while (stack_val--) {
486 emitcode ("inc","dptr");
489 emitcode("mov","dps,#0");
493 emitcode ("push", "acc");
496 emitcode ("push", "b");
498 emitcode ("mov", "a,_bpx");
499 emitcode ("clr","c");
500 emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
501 emitcode ("mov","b,a");
502 emitcode ("mov","a,_bpx+1");
503 emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
505 if (options.model == MODEL_FLAT24)
506 emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
508 emitcode ("mov", "dph1,a");
509 emitcode ("mov", "dpl1,b");
511 if (options.model == MODEL_FLAT24)
512 emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
513 emitcode ("mov", "dph,a");
514 emitcode ("mov", "dpl,b");
518 emitcode ("pop", "b");
521 emitcode ("pop", "acc");
523 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
524 aop->size = getSize (sym->type);
528 /* if in bit space */
529 if (IN_BITSPACE (space))
531 sym->aop = aop = newAsmop (AOP_CRY);
532 aop->aopu.aop_dir = sym->rname;
533 aop->size = getSize (sym->type);
536 /* if it is in direct space */
537 if (IN_DIRSPACE (space))
539 sym->aop = aop = newAsmop (AOP_DIR);
540 aop->aopu.aop_dir = sym->rname;
541 aop->size = getSize (sym->type);
545 /* special case for a function */
546 if (IS_FUNC (sym->type))
548 sym->aop = aop = newAsmop (AOP_IMMD);
549 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
550 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
551 aop->size = FPTRSIZE;
555 /* only remaining is far space */
556 /* in which case DPTR gets the address */
557 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
562 emitcode ("mov", "dptr,#%s", sym->rname);
567 emitcode ("mov", "dptr,#%s", sym->rname);
569 aop->size = getSize (sym->type);
571 /* if it is in code space */
572 if (IN_CODESPACE (space))
578 /*-----------------------------------------------------------------*/
579 /* aopForRemat - rematerialzes an object */
580 /*-----------------------------------------------------------------*/
582 aopForRemat (symbol * sym)
584 iCode *ic = sym->rematiCode;
585 asmop *aop = newAsmop (AOP_IMMD);
592 val += (int) operandLitValue (IC_RIGHT (ic));
593 else if (ic->op == '-')
594 val -= (int) operandLitValue (IC_RIGHT (ic));
595 else if (IS_CAST_ICODE(ic)) {
596 sym_link *from_type = operandType(IC_RIGHT(ic));
597 aop->aopu.aop_immd.from_cast_remat = 1;
598 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
599 ptr_type = DCL_TYPE(from_type);
600 if (ptr_type == IPOINTER) {
607 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
611 sprintf (buffer, "(%s %c 0x%04x)",
612 OP_SYMBOL (IC_LEFT (ic))->rname,
613 val >= 0 ? '+' : '-',
616 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
618 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
619 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
620 /* set immd2 field if required */
621 if (aop->aopu.aop_immd.from_cast_remat) {
622 tsprintf(buffer,"#!constbyte",ptr_type);
623 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
624 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
630 /*-----------------------------------------------------------------*/
631 /* aopHasRegs - returns true if aop has regs between from-to */
632 /*-----------------------------------------------------------------*/
633 static int aopHasRegs(asmop *aop, int from, int to)
637 if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
639 for (; size < aop->size ; size++) {
641 for (reg = from ; reg <= to ; reg++)
642 if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
647 /*-----------------------------------------------------------------*/
648 /* regsInCommon - two operands have some registers in common */
649 /*-----------------------------------------------------------------*/
651 regsInCommon (operand * op1, operand * op2)
656 /* if they have registers in common */
657 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
660 sym1 = OP_SYMBOL (op1);
661 sym2 = OP_SYMBOL (op2);
663 if (sym1->nRegs == 0 || sym2->nRegs == 0)
666 for (i = 0; i < sym1->nRegs; i++)
672 for (j = 0; j < sym2->nRegs; j++)
677 if (sym2->regs[j] == sym1->regs[i])
685 /*-----------------------------------------------------------------*/
686 /* operandsEqu - equivalent */
687 /*-----------------------------------------------------------------*/
689 operandsEqu (operand * op1, operand * op2)
693 /* if they not symbols */
694 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
697 sym1 = OP_SYMBOL (op1);
698 sym2 = OP_SYMBOL (op2);
700 /* if both are itemps & one is spilt
701 and the other is not then false */
702 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
703 sym1->isspilt != sym2->isspilt)
706 /* if they are the same */
710 if (strcmp (sym1->rname, sym2->rname) == 0)
714 /* if left is a tmp & right is not */
715 if (IS_ITEMP (op1) &&
718 (sym1->usl.spillLoc == sym2))
721 if (IS_ITEMP (op2) &&
725 (sym2->usl.spillLoc == sym1))
731 /*-----------------------------------------------------------------*/
732 /* sameRegs - two asmops have the same registers */
733 /*-----------------------------------------------------------------*/
735 sameRegs (asmop * aop1, asmop * aop2)
741 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
748 if (aop1->type != AOP_REG ||
749 aop2->type != AOP_REG)
752 if (aop1->size != aop2->size)
755 for (i = 0; i < aop1->size; i++)
756 if (aop1->aopu.aop_reg[i] !=
757 aop2->aopu.aop_reg[i])
763 /*-----------------------------------------------------------------*/
764 /* aopOp - allocates an asmop for an operand : */
765 /*-----------------------------------------------------------------*/
767 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
776 /* if this a literal */
777 if (IS_OP_LITERAL (op))
779 op->aop = aop = newAsmop (AOP_LIT);
780 aop->aopu.aop_lit = op->operand.valOperand;
781 aop->size = getSize (operandType (op));
785 /* if already has a asmop then continue */
789 /* if the underlying symbol has a aop */
790 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
792 op->aop = OP_SYMBOL (op)->aop;
796 /* if this is a true symbol */
797 if (IS_TRUE_SYMOP (op))
799 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
803 /* this is a temporary : this has
809 e) can be a return use only */
811 sym = OP_SYMBOL (op);
814 /* if the type is a conditional */
815 if (sym->regType == REG_CND)
817 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
822 /* if it is spilt then two situations
824 b) has a spill location */
825 if (sym->isspilt || sym->nRegs == 0)
828 /* rematerialize it NOW */
831 sym->aop = op->aop = aop =
833 aop->size = getSize (sym->type);
840 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
841 aop->size = getSize (sym->type);
842 for (i = 0; i < 2; i++)
843 aop->aopu.aop_str[i] = accUse[i];
853 /* a AOP_STR uses DPTR, but DPTR is already in use;
856 fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use! for operand %s\n",sym->name);
859 aop = op->aop = sym->aop = newAsmop (AOP_STR);
860 aop->size = getSize (sym->type);
861 for (i = 0; i < (int) fReturnSizeDS390; i++)
862 aop->aopu.aop_str[i] = fReturn[i];
866 /* else spill location */
867 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
868 /* force a new aop if sizes differ */
869 sym->usl.spillLoc->aop = NULL;
871 sym->aop = op->aop = aop =
872 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
873 aop->size = getSize (sym->type);
877 /* must be in a register */
878 sym->aop = op->aop = aop = newAsmop (AOP_REG);
879 aop->size = sym->nRegs;
880 for (i = 0; i < sym->nRegs; i++)
881 aop->aopu.aop_reg[i] = sym->regs[i];
884 /*-----------------------------------------------------------------*/
885 /* freeAsmop - free up the asmop given to an operand */
886 /*----------------------------------------------------------------*/
888 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
905 /* depending on the asmop type only three cases need work AOP_RO
906 , AOP_R1 && AOP_STK */
914 emitcode ("pop", "ar0");
918 bitVectUnSetBit (ic->rUsed, R0_IDX);
926 emitcode ("pop", "ar1");
930 bitVectUnSetBit (ic->rUsed, R1_IDX);
936 int stk = aop->aopu.aop_stk + aop->size;
937 bitVectUnSetBit (ic->rUsed, R0_IDX);
938 bitVectUnSetBit (ic->rUsed, R1_IDX);
940 getFreePtr (ic, &aop, FALSE);
942 if (options.stack10bit)
944 /* I'm not sure what to do here yet... */
947 "*** Warning: probably generating bad code for "
948 "10 bit stack mode.\n");
953 emitcode ("mov", "a,_bp");
954 emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
955 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
959 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
964 emitcode ("pop", "acc");
965 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
968 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
971 freeAsmop (op, NULL, ic, TRUE);
974 emitcode ("pop", "ar0");
980 emitcode ("pop", "ar1");
987 /* all other cases just dealloc */
993 OP_SYMBOL (op)->aop = NULL;
994 /* if the symbol has a spill */
996 SPIL_LOC (op)->aop = NULL;
1001 /*------------------------------------------------------------------*/
1002 /* aopGet - for fetching value of the aop */
1004 /* Set canClobberACC if you are sure it is OK to clobber the value */
1005 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
1006 /* just less efficient. */
1007 /*------------------------------------------------------------------*/
1010 aopGet (asmop * aop,
1019 /* offset is greater than
1021 if (offset > (aop->size - 1) &&
1022 aop->type != AOP_LIT)
1025 /* depending on type */
1031 /* if we need to increment it */
1032 while (offset > aop->coff)
1034 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1038 while (offset < aop->coff)
1040 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1047 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1048 return (dname ? "acc" : "a");
1050 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1051 rs = Safe_calloc (1, strlen (s) + 1);
1058 if (aop->type == AOP_DPTR2)
1064 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1070 while (offset > aop->coff)
1072 emitcode ("inc", "dptr");
1076 while (offset < aop->coff)
1078 emitcode ("lcall", "__decdptr");
1085 emitcode ("clr", "a");
1086 emitcode ("movc", "a,@a+dptr");
1090 emitcode ("movx", "a,@dptr");
1093 if (aop->type == AOP_DPTR2)
1099 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1100 return DP2_RESULT_REG;
1103 return (dname ? "acc" : "a");
1106 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1107 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1109 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1113 tsprintf(s,"#!his",aop->aopu.aop_immd.aop_immd1);
1116 tsprintf(s,"#!hihis",aop->aopu.aop_immd.aop_immd1);
1119 tsprintf(s,"#!hihihis",aop->aopu.aop_immd.aop_immd1);
1121 default: /* should not need this (just in case) */
1122 sprintf (s, "#(%s >> %d)",
1123 aop->aopu.aop_immd.aop_immd1,
1129 aop->aopu.aop_immd.aop_immd1);
1130 rs = Safe_calloc (1, strlen (s) + 1);
1136 sprintf (s, "(%s + %d)",
1140 sprintf (s, "%s", aop->aopu.aop_dir);
1141 rs = Safe_calloc (1, strlen (s) + 1);
1147 return aop->aopu.aop_reg[offset]->dname;
1149 return aop->aopu.aop_reg[offset]->name;
1152 emitcode ("clr", "a");
1153 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1154 emitcode ("rlc", "a");
1155 return (dname ? "acc" : "a");
1158 if (!offset && dname)
1160 return aop->aopu.aop_str[offset];
1163 return aopLiteral (aop->aopu.aop_lit, offset);
1167 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1171 return aop->aopu.aop_str[offset];
1175 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1176 "aopget got unsupported aop->type");
1179 /*-----------------------------------------------------------------*/
1180 /* aopPut - puts a string for a aop */
1181 /*-----------------------------------------------------------------*/
1183 aopPut (asmop * aop, char *s, int offset)
1187 if (aop->size && offset > (aop->size - 1))
1189 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1190 "aopPut got offset > aop->size");
1194 /* will assign value to value */
1195 /* depending on where it is ofcourse */
1200 sprintf (d, "(%s + %d)",
1201 aop->aopu.aop_dir, offset);
1203 sprintf (d, "%s", aop->aopu.aop_dir);
1206 emitcode ("mov", "%s,%s", d, s);
1211 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1212 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1215 strcmp (s, "r0") == 0 ||
1216 strcmp (s, "r1") == 0 ||
1217 strcmp (s, "r2") == 0 ||
1218 strcmp (s, "r3") == 0 ||
1219 strcmp (s, "r4") == 0 ||
1220 strcmp (s, "r5") == 0 ||
1221 strcmp (s, "r6") == 0 ||
1222 strcmp (s, "r7") == 0)
1223 emitcode ("mov", "%s,%s",
1224 aop->aopu.aop_reg[offset]->dname, s);
1226 emitcode ("mov", "%s,%s",
1227 aop->aopu.aop_reg[offset]->name, s);
1234 if (aop->type == AOP_DPTR2)
1242 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1243 "aopPut writting to code space");
1247 while (offset > aop->coff)
1250 emitcode ("inc", "dptr");
1253 while (offset < aop->coff)
1256 emitcode ("lcall", "__decdptr");
1261 /* if not in accumulater */
1264 emitcode ("movx", "@dptr,a");
1266 if (aop->type == AOP_DPTR2)
1274 while (offset > aop->coff)
1277 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1279 while (offset < aop->coff)
1282 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1289 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1295 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1297 else if (strcmp (s, "r0") == 0 ||
1298 strcmp (s, "r1") == 0 ||
1299 strcmp (s, "r2") == 0 ||
1300 strcmp (s, "r3") == 0 ||
1301 strcmp (s, "r4") == 0 ||
1302 strcmp (s, "r5") == 0 ||
1303 strcmp (s, "r6") == 0 ||
1304 strcmp (s, "r7") == 0)
1307 sprintf (buffer, "a%s", s);
1308 emitcode ("mov", "@%s,%s",
1309 aop->aopu.aop_ptr->name, buffer);
1312 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1317 if (strcmp (s, "a") == 0)
1318 emitcode ("push", "acc");
1322 emitcode ("push", "acc");
1324 emitcode ("push", s);
1330 /* if bit variable */
1331 if (!aop->aopu.aop_dir)
1333 emitcode ("clr", "a");
1334 emitcode ("rlc", "a");
1339 emitcode ("clr", "%s", aop->aopu.aop_dir);
1341 emitcode ("setb", "%s", aop->aopu.aop_dir);
1342 else if (!strcmp (s, "c"))
1343 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1346 if (strcmp (s, "a"))
1351 symbol *lbl = newiTempLabel (NULL);
1352 emitcode ("clr", "c");
1353 emitcode ("jz", "!tlabel", lbl->key + 100);
1354 emitcode ("cpl", "c");
1355 emitcode ("", "!tlabeldef", lbl->key + 100);
1356 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1364 if (strcmp (aop->aopu.aop_str[offset], s))
1365 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1370 if (!offset && (strcmp (s, "acc") == 0))
1373 if (strcmp (aop->aopu.aop_str[offset], s))
1374 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1378 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1379 "aopPut got unsupported aop->type");
1386 /*--------------------------------------------------------------------*/
1387 /* reAdjustPreg - points a register back to where it should (coff==0) */
1388 /*--------------------------------------------------------------------*/
1390 reAdjustPreg (asmop * aop)
1392 if ((aop->coff==0) || (aop->size <= 1)) {
1401 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1405 if (aop->type == AOP_DPTR2)
1412 emitcode ("lcall", "__decdptr");
1415 if (aop->type == AOP_DPTR2)
1425 #define AOP(op) op->aop
1426 #define AOP_TYPE(op) AOP(op)->type
1427 #define AOP_SIZE(op) AOP(op)->size
1428 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1429 AOP_TYPE(x) == AOP_R0))
1431 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1432 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1435 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1436 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1437 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1439 /* Workaround for DS80C390 bug: div ab may return bogus results
1440 * if A is accessed in instruction immediately before the div.
1442 * Will be fixed in B4 rev of processor, Dallas claims.
1445 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1446 if (!AOP_NEEDSACC(RIGHT)) \
1448 /* We can load A first, then B, since \
1449 * B (the RIGHT operand) won't clobber A, \
1450 * thus avoiding touching A right before the div. \
1452 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1453 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1455 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1459 /* Just stuff in a nop after loading A. */ \
1460 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1461 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1463 emitcode("nop", "; workaround for DS80C390 div bug."); \
1466 /*-----------------------------------------------------------------*/
1467 /* genNotFloat - generates not for float operations */
1468 /*-----------------------------------------------------------------*/
1470 genNotFloat (operand * op, operand * res)
1476 D (emitcode (";", "genNotFloat ");
1479 /* we will put 127 in the first byte of
1481 aopPut (AOP (res), "#127", 0);
1482 size = AOP_SIZE (op) - 1;
1485 _startLazyDPSEvaluation ();
1486 l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1491 emitcode ("orl", "a,%s",
1493 offset++, FALSE, FALSE, FALSE));
1495 _endLazyDPSEvaluation ();
1497 tlbl = newiTempLabel (NULL);
1498 aopPut (res->aop, one, 1);
1499 emitcode ("jz", "!tlabel", (tlbl->key + 100));
1500 aopPut (res->aop, zero, 1);
1501 emitcode ("", "!tlabeldef", (tlbl->key + 100));
1503 size = res->aop->size - 2;
1505 /* put zeros in the rest */
1507 aopPut (res->aop, zero, offset++);
1510 /*-----------------------------------------------------------------*/
1511 /* opIsGptr: returns non-zero if the passed operand is */
1512 /* a generic pointer type. */
1513 /*-----------------------------------------------------------------*/
1515 opIsGptr (operand * op)
1517 sym_link *type = operandType (op);
1519 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1526 /*-----------------------------------------------------------------*/
1527 /* getDataSize - get the operand data size */
1528 /*-----------------------------------------------------------------*/
1530 getDataSize (operand * op)
1533 size = AOP_SIZE (op);
1534 if (size == GPTRSIZE)
1536 sym_link *type = operandType (op);
1537 if (IS_GENPTR (type))
1539 /* generic pointer; arithmetic operations
1540 * should ignore the high byte (pointer type).
1548 /*-----------------------------------------------------------------*/
1549 /* outAcc - output Acc */
1550 /*-----------------------------------------------------------------*/
1552 outAcc (operand * result)
1555 size = getDataSize (result);
1558 aopPut (AOP (result), "a", 0);
1561 /* unsigned or positive */
1564 aopPut (AOP (result), zero, offset++);
1569 /*-----------------------------------------------------------------*/
1570 /* outBitC - output a bit C */
1571 /*-----------------------------------------------------------------*/
1573 outBitC (operand * result)
1575 /* if the result is bit */
1576 if (AOP_TYPE (result) == AOP_CRY)
1578 aopPut (AOP (result), "c", 0);
1582 emitcode ("clr", "a");
1583 emitcode ("rlc", "a");
1588 /*-----------------------------------------------------------------*/
1589 /* toBoolean - emit code for orl a,operator(sizeop) */
1590 /*-----------------------------------------------------------------*/
1592 toBoolean (operand * oper)
1594 int size = AOP_SIZE (oper) - 1;
1598 /* The generic part of a generic pointer should
1599 * not participate in it's truth value.
1601 * i.e. 0x10000000 is zero.
1603 if (opIsGptr (oper))
1605 D (emitcode (";", "toBoolean: generic ptr special case.");
1610 _startLazyDPSEvaluation ();
1611 if (AOP_NEEDSACC (oper) && size)
1614 emitcode ("push", "b");
1615 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1619 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1625 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1629 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1632 _endLazyDPSEvaluation ();
1636 emitcode ("mov", "a,b");
1637 emitcode ("pop", "b");
1642 /*-----------------------------------------------------------------*/
1643 /* genNot - generate code for ! operation */
1644 /*-----------------------------------------------------------------*/
1649 sym_link *optype = operandType (IC_LEFT (ic));
1651 D (emitcode (";", "genNot ");
1654 /* assign asmOps to operand & result */
1655 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1656 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1658 /* if in bit space then a special case */
1659 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1661 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1662 emitcode ("cpl", "c");
1663 outBitC (IC_RESULT (ic));
1667 /* if type float then do float */
1668 if (IS_FLOAT (optype))
1670 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1674 toBoolean (IC_LEFT (ic));
1676 tlbl = newiTempLabel (NULL);
1677 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1678 emitcode ("", "!tlabeldef", tlbl->key + 100);
1679 outBitC (IC_RESULT (ic));
1682 /* release the aops */
1683 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1684 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1688 /*-----------------------------------------------------------------*/
1689 /* genCpl - generate code for complement */
1690 /*-----------------------------------------------------------------*/
1698 D (emitcode (";", "genCpl ");
1702 /* assign asmOps to operand & result */
1703 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1704 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1706 /* special case if in bit space */
1707 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1708 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1709 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1710 emitcode ("cpl", "c");
1711 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1714 tlbl=newiTempLabel(NULL);
1715 emitcode ("cjne", "%s,#0x01,%05d$",
1716 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,TRUE), tlbl->key+100);
1717 emitcode ("", "%05d$:", tlbl->key+100);
1718 outBitC (IC_RESULT(ic));
1722 size = AOP_SIZE (IC_RESULT (ic));
1723 _startLazyDPSEvaluation ();
1726 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1728 emitcode ("cpl", "a");
1729 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1731 _endLazyDPSEvaluation ();
1735 /* release the aops */
1736 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1737 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1740 /*-----------------------------------------------------------------*/
1741 /* genUminusFloat - unary minus for floating points */
1742 /*-----------------------------------------------------------------*/
1744 genUminusFloat (operand * op, operand * result)
1746 int size, offset = 0;
1748 /* for this we just need to flip the
1749 first it then copy the rest in place */
1750 D (emitcode (";", "genUminusFloat");
1753 _startLazyDPSEvaluation ();
1754 size = AOP_SIZE (op) - 1;
1755 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1758 emitcode ("cpl", "acc.7");
1759 aopPut (AOP (result), "a", 3);
1763 aopPut (AOP (result),
1764 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1768 _endLazyDPSEvaluation ();
1771 /*-----------------------------------------------------------------*/
1772 /* genUminus - unary minus code generation */
1773 /*-----------------------------------------------------------------*/
1775 genUminus (iCode * ic)
1778 sym_link *optype, *rtype;
1780 D (emitcode (";", "genUminus ");
1785 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1786 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1788 /* if both in bit space then special
1790 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1791 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1794 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1795 emitcode ("cpl", "c");
1796 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1800 optype = operandType (IC_LEFT (ic));
1801 rtype = operandType (IC_RESULT (ic));
1803 /* if float then do float stuff */
1804 if (IS_FLOAT (optype))
1806 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1810 /* otherwise subtract from zero */
1811 size = AOP_SIZE (IC_LEFT (ic));
1813 _startLazyDPSEvaluation ();
1816 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1817 if (!strcmp (l, "a"))
1821 emitcode ("cpl", "a");
1822 emitcode ("addc", "a,#0");
1828 emitcode ("clr", "a");
1829 emitcode ("subb", "a,%s", l);
1831 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1833 _endLazyDPSEvaluation ();
1835 /* if any remaining bytes in the result */
1836 /* we just need to propagate the sign */
1837 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1839 emitcode ("rlc", "a");
1840 emitcode ("subb", "a,acc");
1842 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1846 /* release the aops */
1847 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1848 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1851 /*-----------------------------------------------------------------*/
1852 /* savermask - saves registers in the mask */
1853 /*-----------------------------------------------------------------*/
1854 static void savermask(bitVect *rs_mask)
1857 if (options.useXstack) {
1858 if (bitVectBitValue (rs_mask, R0_IDX))
1859 emitcode ("mov", "b,r0");
1860 emitcode ("mov", "r0,%s", spname);
1861 for (i = 0; i < ds390_nRegs; i++) {
1862 if (bitVectBitValue (rs_mask, i)) {
1864 emitcode ("mov", "a,b");
1866 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1867 emitcode ("movx", "@r0,a");
1868 emitcode ("inc", "r0");
1871 emitcode ("mov", "%s,r0", spname);
1872 if (bitVectBitValue (rs_mask, R0_IDX))
1873 emitcode ("mov", "r0,b");
1875 for (i = 0; i < ds390_nRegs; i++) {
1876 if (bitVectBitValue (rs_mask, i))
1877 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1882 /*-----------------------------------------------------------------*/
1883 /* saveRegisters - will look for a call and save the registers */
1884 /*-----------------------------------------------------------------*/
1886 saveRegisters (iCode * lic)
1892 for (ic = lic; ic; ic = ic->next)
1893 if (ic->op == CALL || ic->op == PCALL)
1898 fprintf (stderr, "found parameter push with no function call\n");
1902 /* if the registers have been saved already then
1904 if (ic->regsSaved || IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))) return ;
1906 /* special case if DPTR alive across a function call then must save it
1907 even though callee saves */
1908 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
1910 rsave = newBitVect(ic->rMask->size);
1911 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
1912 if (bitVectBitValue(ic->rMask,i))
1913 rsave = bitVectSetBit(rsave,i);
1915 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
1917 /* safe the registers in use at this time but skip the
1918 ones for the result */
1919 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1920 ds390_rUmaskForOp (IC_RESULT(ic)));
1926 /*-----------------------------------------------------------------*/
1927 /* usavermask - restore registers with mask */
1928 /*-----------------------------------------------------------------*/
1929 static void unsavermask(bitVect *rs_mask)
1932 if (options.useXstack) {
1933 emitcode ("mov", "r0,%s", spname);
1934 for (i = ds390_nRegs; i >= 0; i--) {
1935 if (bitVectBitValue (rs_mask, i)) {
1936 emitcode ("dec", "r0");
1937 emitcode ("movx", "a,@r0");
1939 emitcode ("mov", "b,a");
1941 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1944 emitcode ("mov", "%s,r0", spname);
1945 if (bitVectBitValue (rs_mask, R0_IDX))
1946 emitcode ("mov", "r0,b");
1948 for (i = ds390_nRegs; i >= 0; i--) {
1949 if (bitVectBitValue (rs_mask, i))
1950 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1955 /*-----------------------------------------------------------------*/
1956 /* unsaveRegisters - pop the pushed registers */
1957 /*-----------------------------------------------------------------*/
1959 unsaveRegisters (iCode * ic)
1963 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
1965 rsave = newBitVect(ic->rMask->size);
1966 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
1967 if (bitVectBitValue(ic->rMask,i))
1968 rsave = bitVectSetBit(rsave,i);
1970 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
1972 /* restore the registers in use at this time but skip the
1973 ones for the result */
1974 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1975 ds390_rUmaskForOp (IC_RESULT(ic)));
1981 /*-----------------------------------------------------------------*/
1983 /*-----------------------------------------------------------------*/
1985 pushSide (operand * oper, int size)
1988 _startLazyDPSEvaluation ();
1991 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1992 if (AOP_TYPE (oper) != AOP_REG &&
1993 AOP_TYPE (oper) != AOP_DIR &&
1996 emitcode ("mov", "a,%s", l);
1997 emitcode ("push", "acc");
2000 emitcode ("push", "%s", l);
2002 _endLazyDPSEvaluation ();
2005 /*-----------------------------------------------------------------*/
2006 /* assignResultValue - */
2007 /*-----------------------------------------------------------------*/
2009 assignResultValue (operand * oper)
2012 int size = AOP_SIZE (oper);
2014 _startLazyDPSEvaluation ();
2017 aopPut (AOP (oper), fReturn[offset], offset);
2020 _endLazyDPSEvaluation ();
2024 /*-----------------------------------------------------------------*/
2025 /* genXpush - pushes onto the external stack */
2026 /*-----------------------------------------------------------------*/
2028 genXpush (iCode * ic)
2030 asmop *aop = newAsmop (0);
2032 int size, offset = 0;
2034 D (emitcode (";", "genXpush ");
2037 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2038 r = getFreePtr (ic, &aop, FALSE);
2041 emitcode ("mov", "%s,_spx", r->name);
2043 size = AOP_SIZE (IC_LEFT (ic));
2044 _startLazyDPSEvaluation ();
2048 char *l = aopGet (AOP (IC_LEFT (ic)),
2049 offset++, FALSE, FALSE, TRUE);
2051 emitcode ("movx", "@%s,a", r->name);
2052 emitcode ("inc", "%s", r->name);
2055 _endLazyDPSEvaluation ();
2058 emitcode ("mov", "_spx,%s", r->name);
2060 freeAsmop (NULL, aop, ic, TRUE);
2061 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2064 /*-----------------------------------------------------------------*/
2065 /* genIpush - genrate code for pushing this gets a little complex */
2066 /*-----------------------------------------------------------------*/
2068 genIpush (iCode * ic)
2070 int size, offset = 0;
2073 D (emitcode (";", "genIpush ");
2076 /* if this is not a parm push : ie. it is spill push
2077 and spill push is always done on the local stack */
2081 /* and the item is spilt then do nothing */
2082 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2085 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2086 size = AOP_SIZE (IC_LEFT (ic));
2087 /* push it on the stack */
2088 _startLazyDPSEvaluation ();
2091 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
2097 emitcode ("push", "%s", l);
2099 _endLazyDPSEvaluation ();
2103 /* this is a paramter push: in this case we call
2104 the routine to find the call and save those
2105 registers that need to be saved */
2108 /* if use external stack then call the external
2109 stack pushing routine */
2110 if (options.useXstack)
2116 /* then do the push */
2117 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2119 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2120 size = AOP_SIZE (IC_LEFT (ic));
2122 _startLazyDPSEvaluation ();
2125 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2126 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2127 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2130 emitcode ("mov", "a,%s", l);
2131 emitcode ("push", "acc");
2134 emitcode ("push", "%s", l);
2136 _endLazyDPSEvaluation ();
2138 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2141 /*-----------------------------------------------------------------*/
2142 /* genIpop - recover the registers: can happen only for spilling */
2143 /*-----------------------------------------------------------------*/
2145 genIpop (iCode * ic)
2149 D (emitcode (";", "genIpop ");
2153 /* if the temp was not pushed then */
2154 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2157 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2158 size = AOP_SIZE (IC_LEFT (ic));
2159 offset = (size - 1);
2160 _startLazyDPSEvaluation ();
2163 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2164 FALSE, TRUE, TRUE));
2166 _endLazyDPSEvaluation ();
2168 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2171 /*-----------------------------------------------------------------*/
2172 /* unsaveRBank - restores the resgister bank from stack */
2173 /*-----------------------------------------------------------------*/
2175 unsaveRBank (int bank, iCode * ic, bool popPsw)
2181 if (options.useXstack)
2185 /* Assume r0 is available for use. */
2186 r = ds390_regWithIdx (R0_IDX);;
2191 r = getFreePtr (ic, &aop, FALSE);
2193 emitcode ("mov", "%s,_spx", r->name);
2198 if (options.useXstack)
2200 emitcode ("movx", "a,@%s", r->name);
2201 emitcode ("mov", "psw,a");
2202 emitcode ("dec", "%s", r->name);
2206 emitcode ("pop", "psw");
2210 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2212 if (options.useXstack)
2214 emitcode ("movx", "a,@%s", r->name);
2215 emitcode ("mov", "(%s+%d),a",
2216 regs390[i].base, 8 * bank + regs390[i].offset);
2217 emitcode ("dec", "%s", r->name);
2221 emitcode ("pop", "(%s+%d)",
2222 regs390[i].base, 8 * bank + regs390[i].offset);
2225 if (options.useXstack)
2227 emitcode ("mov", "_spx,%s", r->name);
2232 freeAsmop (NULL, aop, ic, TRUE);
2236 /*-----------------------------------------------------------------*/
2237 /* saveRBank - saves an entire register bank on the stack */
2238 /*-----------------------------------------------------------------*/
2240 saveRBank (int bank, iCode * ic, bool pushPsw)
2246 if (options.useXstack)
2250 /* Assume r0 is available for use. */
2251 r = ds390_regWithIdx (R0_IDX);;
2256 r = getFreePtr (ic, &aop, FALSE);
2258 emitcode ("mov", "%s,_spx", r->name);
2261 for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2263 if (options.useXstack)
2265 emitcode ("inc", "%s", r->name);
2266 emitcode ("mov", "a,(%s+%d)",
2267 regs390[i].base, 8 * bank + regs390[i].offset);
2268 emitcode ("movx", "@%s,a", r->name);
2271 emitcode ("push", "(%s+%d)",
2272 regs390[i].base, 8 * bank + regs390[i].offset);
2277 if (options.useXstack)
2279 emitcode ("mov", "a,psw");
2280 emitcode ("movx", "@%s,a", r->name);
2281 emitcode ("inc", "%s", r->name);
2282 emitcode ("mov", "_spx,%s", r->name);
2286 emitcode ("push", "psw");
2289 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2294 freeAsmop (NULL, aop, ic, TRUE);
2303 /*-----------------------------------------------------------------*/
2304 /* genCall - generates a call statement */
2305 /*-----------------------------------------------------------------*/
2307 genCall (iCode * ic)
2310 bool restoreBank = FALSE;
2311 bool swapBanks = FALSE;
2313 D (emitcode (";", "genCall "););
2315 /* if we are calling a not _naked function that is not using
2316 the same register bank then we need to save the
2317 destination registers on the stack */
2318 dtype = operandType (IC_LEFT (ic));
2319 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2320 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2321 IFFUNC_ISISR (currFunc->type))
2325 /* This is unexpected; the bank should have been saved in
2328 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2334 /* if caller saves & we have not saved then */
2338 /* if send set is not empty the assign */
2339 /* We've saved all the registers we care about;
2340 * therefore, we may clobber any register not used
2341 * in the calling convention (i.e. anything not in
2348 for (sic = setFirstItem (_G.sendSet); sic;
2349 sic = setNextItem (_G.sendSet))
2351 int size, offset = 0;
2353 // we know that dpl(hxb) is the result, so
2354 _startLazyDPSEvaluation ();
2355 size=getSize(operandType(IC_LEFT(sic)));
2357 aopOp (IC_LEFT (sic), sic, FALSE,
2358 (IS_SYMOP(IC_LEFT(sic)) && OP_SYMBOL(IC_LEFT(sic))->ruonly ? FALSE : TRUE));
2360 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2364 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2365 FALSE, FALSE, TRUE);
2366 if (strcmp (l, fReturn[offset]))
2368 emitcode ("mov", "%s,%s",
2374 _endLazyDPSEvaluation ();
2375 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2382 emitcode ("mov", "psw,#!constbyte",
2383 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2387 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2388 OP_SYMBOL (IC_LEFT (ic))->rname :
2389 OP_SYMBOL (IC_LEFT (ic))->name));
2393 emitcode ("mov", "psw,#!constbyte",
2394 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2397 /* if we need assign a result value */
2398 if ((IS_ITEMP (IC_RESULT (ic)) &&
2399 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2400 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2401 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2402 IS_TRUE_SYMOP (IC_RESULT (ic)))
2404 if (isOperandInFarSpace (IC_RESULT (ic))
2405 && getSize (operandType (IC_RESULT (ic))) <= 2)
2407 int size = getSize (operandType (IC_RESULT (ic)));
2409 /* Special case for 1 or 2 byte return in far space. */
2413 emitcode ("mov", "b,%s", fReturn[1]);
2416 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2417 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2421 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2423 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2428 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2431 assignResultValue (IC_RESULT (ic));
2433 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2437 /* adjust the stack for parameters if
2439 if (ic->parmBytes) {
2441 if (options.stack10bit) {
2442 if (ic->parmBytes <= 4) {
2443 emitcode(";","stack adjustment for parms");
2444 for (i=0; i < ic->parmBytes ; i++) {
2445 emitcode("pop","acc");
2448 emitcode ("clr","c");
2449 emitcode ("mov","a,sp");
2450 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2451 emitcode ("mov","sp,a");
2452 emitcode ("mov","a,esp");
2453 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2454 emitcode ("mov","esp,a");
2457 if (ic->parmBytes > 3) {
2458 emitcode ("mov", "a,%s", spname);
2459 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2460 emitcode ("mov", "%s,a", spname);
2462 for (i = 0; i < ic->parmBytes; i++)
2463 emitcode ("dec", "%s", spname);
2467 /* if we hade saved some registers then unsave them */
2469 unsaveRegisters (ic);
2471 /* if register bank was saved then pop them */
2473 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2476 /*-----------------------------------------------------------------*/
2477 /* genPcall - generates a call by pointer statement */
2478 /*-----------------------------------------------------------------*/
2480 genPcall (iCode * ic)
2483 symbol *rlbl = newiTempLabel (NULL);
2484 bool restoreBank=FALSE;
2486 D (emitcode (";", "genPcall ");
2490 /* if caller saves & we have not saved then */
2494 /* if we are calling a function that is not using
2495 the same register bank then we need to save the
2496 destination registers on the stack */
2497 dtype = operandType (IC_LEFT (ic));
2498 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2499 IFFUNC_ISISR (currFunc->type) &&
2500 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2501 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2505 /* push the return address on to the stack */
2506 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2507 emitcode ("push", "acc");
2508 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2509 emitcode ("push", "acc");
2511 if (options.model == MODEL_FLAT24)
2513 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2514 emitcode ("push", "acc");
2517 /* now push the calling address */
2518 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2520 pushSide (IC_LEFT (ic), FPTRSIZE);
2522 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2524 /* if send set is not empty the assign */
2529 for (sic = setFirstItem (_G.sendSet); sic;
2530 sic = setNextItem (_G.sendSet))
2532 int size, offset = 0;
2534 // we know that dpl(hxb) is the result, so
2535 _startLazyDPSEvaluation ();
2536 size=getSize(operandType(IC_LEFT(sic)));
2538 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2540 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2544 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2545 FALSE, FALSE, TRUE);
2546 if (strcmp (l, fReturn[offset]))
2548 emitcode ("mov", "%s,%s",
2554 _endLazyDPSEvaluation ();
2555 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2560 emitcode ("ret", "");
2561 emitcode ("", "!tlabeldef", (rlbl->key + 100));
2564 /* if we need assign a result value */
2565 if ((IS_ITEMP (IC_RESULT (ic)) &&
2566 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2567 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2568 IS_TRUE_SYMOP (IC_RESULT (ic)))
2572 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2575 assignResultValue (IC_RESULT (ic));
2577 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2580 /* adjust the stack for parameters if
2585 if (ic->parmBytes > 3)
2587 emitcode ("mov", "a,%s", spname);
2588 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2589 emitcode ("mov", "%s,a", spname);
2592 for (i = 0; i < ic->parmBytes; i++)
2593 emitcode ("dec", "%s", spname);
2597 /* if register bank was saved then unsave them */
2599 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2601 /* if we hade saved some registers then
2604 unsaveRegisters (ic);
2608 /*-----------------------------------------------------------------*/
2609 /* resultRemat - result is rematerializable */
2610 /*-----------------------------------------------------------------*/
2612 resultRemat (iCode * ic)
2614 if (SKIP_IC (ic) || ic->op == IFX)
2617 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2619 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2620 if (sym->remat && !POINTER_SET (ic))
2627 #if defined(__BORLANDC__) || defined(_MSC_VER)
2628 #define STRCASECMP stricmp
2630 #define STRCASECMP strcasecmp
2633 /*-----------------------------------------------------------------*/
2634 /* inExcludeList - return 1 if the string is in exclude Reg list */
2635 /*-----------------------------------------------------------------*/
2637 inExcludeList (char *s)
2641 if (options.excludeRegs[i] &&
2642 STRCASECMP (options.excludeRegs[i], "none") == 0)
2645 for (i = 0; options.excludeRegs[i]; i++)
2647 if (options.excludeRegs[i] &&
2648 STRCASECMP (s, options.excludeRegs[i]) == 0)
2654 /*-----------------------------------------------------------------*/
2655 /* genFunction - generated code for function entry */
2656 /*-----------------------------------------------------------------*/
2658 genFunction (iCode * ic)
2662 bool switchedPSW = FALSE;
2664 D (emitcode (";", "genFunction "););
2667 /* create the function header */
2668 emitcode (";", "-----------------------------------------");
2669 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2670 emitcode (";", "-----------------------------------------");
2672 emitcode ("", "%s:", sym->rname);
2673 ftype = operandType (IC_LEFT (ic));
2675 if (IFFUNC_ISNAKED(ftype))
2677 emitcode(";", "naked function: no prologue.");
2681 if (options.stack_probe)
2682 emitcode ("lcall","__stack_probe");
2683 /* if critical function then turn interrupts off */
2684 if (IFFUNC_ISCRITICAL (ftype))
2685 emitcode ("clr", "ea");
2687 /* here we need to generate the equates for the
2688 register bank if required */
2689 if (FUNC_REGBANK (ftype) != rbank)
2693 rbank = FUNC_REGBANK (ftype);
2694 for (i = 0; i < ds390_nRegs; i++)
2696 if (regs390[i].print) {
2697 if (strcmp (regs390[i].base, "0") == 0)
2698 emitcode ("", "%s !equ !constbyte",
2700 8 * rbank + regs390[i].offset);
2702 emitcode ("", "%s !equ %s + !constbyte",
2705 8 * rbank + regs390[i].offset);
2710 /* if this is an interrupt service routine then
2711 save acc, b, dpl, dph */
2712 if (IFFUNC_ISISR (sym->type))
2715 if (!inExcludeList ("acc"))
2716 emitcode ("push", "acc");
2717 if (!inExcludeList ("b"))
2718 emitcode ("push", "b");
2719 if (!inExcludeList ("dpl"))
2720 emitcode ("push", "dpl");
2721 if (!inExcludeList ("dph"))
2722 emitcode ("push", "dph");
2723 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2725 emitcode ("push", "dpx");
2726 /* Make sure we're using standard DPTR */
2727 emitcode ("push", "dps");
2728 emitcode ("mov", "dps,#0");
2729 if (options.stack10bit)
2731 /* This ISR could conceivably use DPTR2. Better save it. */
2732 emitcode ("push", "dpl1");
2733 emitcode ("push", "dph1");
2734 emitcode ("push", "dpx1");
2735 emitcode ("push", DP2_RESULT_REG);
2738 /* if this isr has no bank i.e. is going to
2739 run with bank 0 , then we need to save more
2741 if (!FUNC_REGBANK (sym->type))
2744 /* if this function does not call any other
2745 function then we can be economical and
2746 save only those registers that are used */
2747 if (!IFFUNC_HASFCALL(sym->type))
2751 /* if any registers used */
2754 /* save the registers used */
2755 for (i = 0; i < sym->regsUsed->size; i++)
2757 if (bitVectBitValue (sym->regsUsed, i) ||
2758 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2759 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2766 /* this function has a function call cannot
2767 determines register usage so we will have to push the
2769 saveRBank (0, ic, FALSE);
2774 /* This ISR uses a non-zero bank.
2776 * We assume that the bank is available for our
2779 * However, if this ISR calls a function which uses some
2780 * other bank, we must save that bank entirely.
2782 unsigned long banksToSave = 0;
2784 if (IFFUNC_HASFCALL(sym->type))
2787 #define MAX_REGISTER_BANKS 4
2792 for (i = ic; i; i = i->next)
2794 if (i->op == ENDFUNCTION)
2796 /* we got to the end OK. */
2804 dtype = operandType (IC_LEFT(i));
2806 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2808 /* Mark this bank for saving. */
2809 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2811 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2815 banksToSave |= (1 << FUNC_REGBANK(dtype));
2818 /* And note that we don't need to do it in
2826 /* This is a mess; we have no idea what
2827 * register bank the called function might
2830 * The only thing I can think of to do is
2831 * throw a warning and hope.
2833 werror(W_FUNCPTR_IN_USING_ISR);
2837 if (banksToSave && options.useXstack)
2839 /* Since we aren't passing it an ic,
2840 * saveRBank will assume r0 is available to abuse.
2842 * So switch to our (trashable) bank now, so
2843 * the caller's R0 isn't trashed.
2845 emitcode ("push", "psw");
2846 emitcode ("mov", "psw,#!constbyte",
2847 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2851 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2853 if (banksToSave & (1 << ix))
2855 saveRBank(ix, NULL, FALSE);
2859 // jwk: this needs a closer look
2860 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2865 /* if callee-save to be used for this function
2866 then save the registers being used in this function */
2867 if (IFFUNC_CALLEESAVES(sym->type))
2871 /* if any registers used */
2874 /* save the registers used */
2875 for (i = 0; i < sym->regsUsed->size; i++)
2877 if (bitVectBitValue (sym->regsUsed, i) ||
2878 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2880 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2888 /* set the register bank to the desired value */
2889 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2892 emitcode ("push", "psw");
2893 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2896 if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
2897 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
2898 if (options.stack10bit) {
2899 emitcode ("push","_bpx");
2900 emitcode ("push","_bpx+1");
2901 emitcode ("mov","_bpx,%s",spname);
2902 emitcode ("mov","_bpx+1,esp");
2903 emitcode ("anl","_bpx+1,#3");
2905 if (options.useXstack) {
2906 emitcode ("mov", "r0,%s", spname);
2907 emitcode ("mov", "a,_bp");
2908 emitcode ("movx", "@r0,a");
2909 emitcode ("inc", "%s", spname);
2911 /* set up the stack */
2912 emitcode ("push", "_bp"); /* save the callers stack */
2914 emitcode ("mov", "_bp,%s", spname);
2918 /* adjust the stack for the function */
2921 if (options.stack10bit) {
2922 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
2923 assert (sym->recvSize <= 4);
2924 emitcode ("mov","a,sp");
2925 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
2926 emitcode ("mov","sp,a");
2927 emitcode ("mov","a,esp");
2928 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
2929 emitcode ("mov","esp,a");
2932 werror (W_STACK_OVERFLOW, sym->name);
2934 if (i > 3 && sym->recvSize < 4) {
2936 emitcode ("mov", "a,sp");
2937 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
2938 emitcode ("mov", "sp,a");
2942 emitcode ("inc", "sp");
2949 emitcode ("mov", "a,_spx");
2950 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
2951 emitcode ("mov", "_spx,a");
2956 /*-----------------------------------------------------------------*/
2957 /* genEndFunction - generates epilogue for functions */
2958 /*-----------------------------------------------------------------*/
2960 genEndFunction (iCode * ic)
2962 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2964 D (emitcode (";", "genEndFunction "););
2966 if (IFFUNC_ISNAKED(sym->type))
2968 emitcode(";", "naked function: no epilogue.");
2972 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
2973 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
2975 if (options.stack10bit) {
2976 emitcode ("mov", "sp,_bpx", spname);
2977 emitcode ("mov", "esp,_bpx+1", spname);
2979 emitcode ("mov", "%s,_bp", spname);
2983 /* if use external stack but some variables were
2984 added to the local stack then decrement the
2986 if (options.useXstack && sym->stack) {
2987 emitcode ("mov", "a,sp");
2988 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
2989 emitcode ("mov", "sp,a");
2993 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
2994 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
2996 if (options.useXstack) {
2997 emitcode ("mov", "r0,%s", spname);
2998 emitcode ("movx", "a,@r0");
2999 emitcode ("mov", "_bp,a");
3000 emitcode ("dec", "%s", spname);
3002 if (options.stack10bit) {
3003 emitcode ("pop", "_bpx+1");
3004 emitcode ("pop", "_bpx");
3006 emitcode ("pop", "_bp");
3011 /* restore the register bank */
3012 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3014 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3015 || !options.useXstack)
3017 /* Special case of ISR using non-zero bank with useXstack
3020 emitcode ("pop", "psw");
3024 if (IFFUNC_ISISR (sym->type))
3027 /* now we need to restore the registers */
3028 /* if this isr has no bank i.e. is going to
3029 run with bank 0 , then we need to save more
3031 if (!FUNC_REGBANK (sym->type))
3033 /* if this function does not call any other
3034 function then we can be economical and
3035 save only those registers that are used */
3036 if (!IFFUNC_HASFCALL(sym->type))
3040 /* if any registers used */
3043 /* save the registers used */
3044 for (i = sym->regsUsed->size; i >= 0; i--)
3046 if (bitVectBitValue (sym->regsUsed, i) ||
3047 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3048 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3055 /* this function has a function call cannot
3056 determines register usage so we will have to pop the
3058 unsaveRBank (0, ic, FALSE);
3063 /* This ISR uses a non-zero bank.
3065 * Restore any register banks saved by genFunction
3068 // jwk: this needs a closer look
3069 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3072 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3074 if (savedBanks & (1 << ix))
3076 unsaveRBank(ix, NULL, FALSE);
3080 if (options.useXstack)
3082 /* Restore bank AFTER calling unsaveRBank,
3083 * since it can trash r0.
3085 emitcode ("pop", "psw");
3089 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3091 if (options.stack10bit)
3093 emitcode ("pop", DP2_RESULT_REG);
3094 emitcode ("pop", "dpx1");
3095 emitcode ("pop", "dph1");
3096 emitcode ("pop", "dpl1");
3098 emitcode ("pop", "dps");
3099 emitcode ("pop", "dpx");
3101 if (!inExcludeList ("dph"))
3102 emitcode ("pop", "dph");
3103 if (!inExcludeList ("dpl"))
3104 emitcode ("pop", "dpl");
3105 if (!inExcludeList ("b"))
3106 emitcode ("pop", "b");
3107 if (!inExcludeList ("acc"))
3108 emitcode ("pop", "acc");
3110 if (IFFUNC_ISCRITICAL (sym->type))
3111 emitcode ("setb", "ea");
3113 /* if debug then send end of function */
3114 if (options.debug && currFunc) {
3116 emitcode ("", "C$%s$%d$%d$%d ==.",
3117 FileBaseName (ic->filename), currFunc->lastLine,
3118 ic->level, ic->block);
3119 if (IS_STATIC (currFunc->etype))
3120 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3122 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3126 emitcode ("reti", "");
3130 if (IFFUNC_ISCRITICAL (sym->type))
3131 emitcode ("setb", "ea");
3133 if (IFFUNC_CALLEESAVES(sym->type))
3137 /* if any registers used */
3140 /* save the registers used */
3141 for (i = sym->regsUsed->size; i >= 0; i--)
3143 if (bitVectBitValue (sym->regsUsed, i) ||
3144 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3145 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3151 /* if debug then send end of function */
3152 if (options.debug && currFunc)
3155 emitcode ("", "C$%s$%d$%d$%d ==.",
3156 FileBaseName (ic->filename), currFunc->lastLine,
3157 ic->level, ic->block);
3158 if (IS_STATIC (currFunc->etype))
3159 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3161 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3165 emitcode ("ret", "");
3170 /*-----------------------------------------------------------------*/
3171 /* genJavaNativeRet - generate code for return JavaNative */
3172 /*-----------------------------------------------------------------*/
3173 static void genJavaNativeRet(iCode *ic)
3177 aopOp (IC_LEFT (ic), ic, FALSE,
3178 (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3179 size = AOP_SIZE (IC_LEFT (ic));
3183 /* it is assigned to GPR0-R3 then push them */
3184 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3185 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3186 for (i = 0 ; i < size ; i++ ) {
3187 emitcode ("push","%s",aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,FALSE));
3189 for (i = (size-1) ; i >= 0 ; i--) {
3190 emitcode ("pop","a%s",javaRet[i]);
3193 for (i = 0 ; i < size ; i++)
3194 emitcode ("mov","%s,%s",javaRet[i],aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,FALSE));
3196 for (i = size ; i < 4 ; i++ )
3197 emitcode ("mov","%s,#0",javaRet[i]);
3201 /*-----------------------------------------------------------------*/
3202 /* genRet - generate code for return statement */
3203 /*-----------------------------------------------------------------*/
3207 int size, offset = 0, pushed = 0;
3209 D (emitcode (";", "genRet ");
3212 /* if we have no return value then
3213 just generate the "ret" */
3217 /* if this is a JavaNative function then return
3218 value in different register */
3219 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3220 genJavaNativeRet(ic);
3223 /* we have something to return then
3224 move the return value into place */
3225 aopOp (IC_LEFT (ic), ic, FALSE,
3226 (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3227 size = AOP_SIZE (IC_LEFT (ic));
3229 _startLazyDPSEvaluation ();
3233 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3235 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3236 FALSE, TRUE, FALSE);
3237 emitcode ("push", "%s", l);
3242 /* Since A is the last element of fReturn,
3243 * is is OK to clobber it in the aopGet.
3245 l = aopGet (AOP (IC_LEFT (ic)), offset,
3246 FALSE, FALSE, TRUE);
3247 if (strcmp (fReturn[offset], l))
3248 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3251 _endLazyDPSEvaluation ();
3258 if (strcmp (fReturn[pushed], "a"))
3259 emitcode ("pop", fReturn[pushed]);
3261 emitcode ("pop", "acc");
3264 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3267 /* generate a jump to the return label
3268 if the next is not the return statement */
3269 if (!(ic->next && ic->next->op == LABEL &&
3270 IC_LABEL (ic->next) == returnLabel))
3272 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3276 /*-----------------------------------------------------------------*/
3277 /* genLabel - generates a label */
3278 /*-----------------------------------------------------------------*/
3280 genLabel (iCode * ic)
3282 /* special case never generate */
3283 if (IC_LABEL (ic) == entryLabel)
3286 D (emitcode (";", "genLabel ");
3289 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3292 /*-----------------------------------------------------------------*/
3293 /* genGoto - generates a ljmp */
3294 /*-----------------------------------------------------------------*/
3296 genGoto (iCode * ic)
3298 D (emitcode (";", "genGoto ");
3300 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3303 /*-----------------------------------------------------------------*/
3304 /* findLabelBackwards: walks back through the iCode chain looking */
3305 /* for the given label. Returns number of iCode instructions */
3306 /* between that label and given ic. */
3307 /* Returns zero if label not found. */
3308 /*-----------------------------------------------------------------*/
3310 findLabelBackwards (iCode * ic, int key)
3319 /* If we have any pushes or pops, we cannot predict the distance.
3320 I don't like this at all, this should be dealt with in the
3322 if (ic->op == IPUSH || ic->op == IPOP) {
3326 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3328 /* printf("findLabelBackwards = %d\n", count); */
3336 /*-----------------------------------------------------------------*/
3337 /* genPlusIncr :- does addition with increment if possible */
3338 /*-----------------------------------------------------------------*/
3340 genPlusIncr (iCode * ic)
3342 unsigned int icount;
3343 unsigned int size = getDataSize (IC_RESULT (ic));
3345 /* will try to generate an increment */
3346 /* if the right side is not a literal
3348 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3351 /* if the literal value of the right hand side
3352 is greater than 4 then it is not worth it */
3353 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3356 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3357 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3359 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3363 /* if increment 16 bits in register */
3365 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3366 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3367 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3375 /* If the next instruction is a goto and the goto target
3376 * is <= 5 instructions previous to this, we can generate
3377 * jumps straight to that target.
3379 if (ic->next && ic->next->op == GOTO
3380 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3383 emitcode (";", "tail increment optimized (range %d)", labelRange);
3384 tlbl = IC_LABEL (ic->next);
3389 tlbl = newiTempLabel (NULL);
3392 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3393 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3394 IS_AOP_PREG (IC_RESULT (ic)))
3395 emitcode ("cjne", "%s,#0,!tlabel"
3396 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3400 emitcode ("clr", "a");
3401 emitcode ("cjne", "a,%s,!tlabel"
3402 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3406 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3409 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3410 IS_AOP_PREG (IC_RESULT (ic)))
3411 emitcode ("cjne", "%s,#0,!tlabel"
3412 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3415 emitcode ("cjne", "a,%s,!tlabel"
3416 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3419 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3423 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3424 IS_AOP_PREG (IC_RESULT (ic)))
3425 emitcode ("cjne", "%s,#0,!tlabel"
3426 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3430 emitcode ("cjne", "a,%s,!tlabel"
3431 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3434 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3439 emitcode ("", "!tlabeldef", tlbl->key + 100);
3444 /* if the sizes are greater than 1 then we cannot */
3445 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3446 AOP_SIZE (IC_LEFT (ic)) > 1)
3449 /* we can if the aops of the left & result match or
3450 if they are in registers and the registers are the
3453 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3454 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3455 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3460 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3461 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3462 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3467 _startLazyDPSEvaluation ();
3470 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3472 _endLazyDPSEvaluation ();
3481 /*-----------------------------------------------------------------*/
3482 /* outBitAcc - output a bit in acc */
3483 /*-----------------------------------------------------------------*/
3485 outBitAcc (operand * result)
3487 symbol *tlbl = newiTempLabel (NULL);
3488 /* if the result is a bit */
3489 if (AOP_TYPE (result) == AOP_CRY)
3491 aopPut (AOP (result), "a", 0);
3495 emitcode ("jz", "!tlabel", tlbl->key + 100);
3496 emitcode ("mov", "a,%s", one);
3497 emitcode ("", "!tlabeldef", tlbl->key + 100);
3502 /*-----------------------------------------------------------------*/
3503 /* genPlusBits - generates code for addition of two bits */
3504 /*-----------------------------------------------------------------*/
3506 genPlusBits (iCode * ic)
3508 D (emitcode (";", "genPlusBits ");
3510 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3512 symbol *lbl = newiTempLabel (NULL);
3513 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3514 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3515 emitcode ("cpl", "c");
3516 emitcode ("", "!tlabeldef", (lbl->key + 100));
3517 outBitC (IC_RESULT (ic));
3521 emitcode ("clr", "a");
3522 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3523 emitcode ("rlc", "a");
3524 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3525 emitcode ("addc", "a,#0");
3526 outAcc (IC_RESULT (ic));
3531 adjustArithmeticResult (iCode * ic)
3533 if (opIsGptr (IC_RESULT (ic)) &&
3534 opIsGptr (IC_LEFT (ic)) &&
3535 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3537 aopPut (AOP (IC_RESULT (ic)),
3538 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3542 if (opIsGptr (IC_RESULT (ic)) &&
3543 opIsGptr (IC_RIGHT (ic)) &&
3544 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3546 aopPut (AOP (IC_RESULT (ic)),
3547 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3551 if (opIsGptr (IC_RESULT (ic)) &&
3552 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3553 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3554 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3555 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3558 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3559 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3563 #if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
3564 // Please don't bring it back without a really good reason.
3565 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3566 // (because all three operands are in far space).
3567 #define AOP_OP_3(ic) \
3568 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3569 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3570 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3571 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3572 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3573 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3575 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3577 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3581 // Macro to aopOp all three operands of an ic. If this cannot be done,
3582 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3583 // will be set TRUE. The caller must then handle the case specially, noting
3584 // that the IC_RESULT operand is not aopOp'd.
3585 #define AOP_OP_3_NOFATAL(ic, rc) \
3586 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3587 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR) || \
3588 ((OP_SYMBOL(IC_RESULT(ic))->ruonly) && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))); \
3589 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3590 (isOperandInFarSpace(IC_RESULT(ic)) || (OP_SYMBOL(IC_RESULT(ic))->ruonly && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic))))) \
3592 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3597 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3598 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3600 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3601 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3603 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3605 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3609 // aopOp the left & right operands of an ic.
3610 #define AOP_OP_2(ic) \
3611 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3612 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3614 // convienience macro.
3615 #define AOP_SET_LOCALS(ic) \
3616 left = IC_LEFT(ic); \
3617 right = IC_RIGHT(ic); \
3618 result = IC_RESULT(ic);
3621 // Given an integer value of pushedSize bytes on the stack,
3622 // adjust it to be resultSize bytes, either by discarding
3623 // the most significant bytes or by zero-padding.
3625 // On exit from this macro, pushedSize will have been adjusted to
3626 // equal resultSize, and ACC may be trashed.
3627 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3628 /* If the pushed data is bigger than the result, \
3629 * simply discard unused bytes. Icky, but works. \
3631 while (pushedSize > resultSize) \
3633 D (emitcode (";", "discarding unused result byte."););\
3634 emitcode ("pop", "acc"); \
3637 if (pushedSize < resultSize) \
3639 emitcode ("clr", "a"); \
3640 /* Conversly, we haven't pushed enough here. \
3641 * just zero-pad, and all is well. \
3643 while (pushedSize < resultSize) \
3645 emitcode("push", "acc"); \
3649 assert(pushedSize == resultSize);
3651 /*-----------------------------------------------------------------*/
3652 /* genPlus - generates code for addition */
3653 /*-----------------------------------------------------------------*/
3655 genPlus (iCode * ic)
3657 int size, offset = 0;
3658 bool pushResult = FALSE;
3661 D (emitcode (";", "genPlus "););
3663 /* special cases :- */
3664 if ( IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly &&
3665 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3666 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3667 size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3669 while (size--) emitcode ("inc","dptr");
3671 emitcode ("mov","a,dpl");
3672 emitcode ("add","a,#!constbyte",size & 0xff);
3673 emitcode ("mov","dpl,a");
3674 emitcode ("mov","a,dph");
3675 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3676 emitcode ("mov","dph,a");
3677 emitcode ("mov","a,dpx");
3678 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3679 emitcode ("mov","dpx,a");
3681 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3684 if ( IS_SYMOP(IC_LEFT(ic)) &&
3685 OP_SYMBOL(IC_LEFT(ic))->remat &&
3686 isOperandInFarSpace(IC_RIGHT(ic))) {
3687 operand *op = IC_RIGHT(ic);
3688 IC_RIGHT(ic) = IC_LEFT(ic);
3692 AOP_OP_3_NOFATAL (ic, pushResult);
3695 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3700 /* if literal, literal on the right or
3701 if left requires ACC or right is already
3703 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3704 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3705 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3707 operand *t = IC_RIGHT (ic);
3708 IC_RIGHT (ic) = IC_LEFT (ic);
3710 emitcode (";", "Swapped plus args.");
3713 /* if both left & right are in bit
3715 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3716 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3722 /* if left in bit space & right literal */
3723 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3724 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3726 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3727 /* if result in bit space */
3728 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3730 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3731 emitcode ("cpl", "c");
3732 outBitC (IC_RESULT (ic));
3736 size = getDataSize (IC_RESULT (ic));
3737 _startLazyDPSEvaluation ();
3740 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3741 emitcode ("addc", "a,#0");
3742 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3744 _endLazyDPSEvaluation ();
3749 /* if I can do an increment instead
3750 of add then GOOD for ME */
3751 if (genPlusIncr (ic) == TRUE)
3753 emitcode (";", "did genPlusIncr");
3758 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3760 _startLazyDPSEvaluation ();
3763 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3765 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3767 emitcode ("add", "a,%s",
3768 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3770 emitcode ("addc", "a,%s",
3771 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3775 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3777 /* right is going to use ACC or we would have taken the
3780 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3782 D(emitcode(";", "+ AOP_ACC special case."););
3783 emitcode("xch", "a, %s", DP2_RESULT_REG);
3785 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3788 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3791 emitcode("add", "a, %s", DP2_RESULT_REG);
3795 emitcode ("add", "a,%s",
3796 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3801 emitcode ("addc", "a,%s",
3802 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3807 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3811 emitcode ("push", "acc");
3815 _endLazyDPSEvaluation ();
3819 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3821 size = getDataSize (IC_LEFT (ic));
3822 rSize = getDataSize (IC_RESULT (ic));
3824 ADJUST_PUSHED_RESULT(size, rSize);
3826 _startLazyDPSEvaluation ();
3829 emitcode ("pop", "acc");
3830 aopPut (AOP (IC_RESULT (ic)), "a", size);
3832 _endLazyDPSEvaluation ();
3835 adjustArithmeticResult (ic);
3838 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3839 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3840 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3843 /*-----------------------------------------------------------------*/
3844 /* genMinusDec :- does subtraction with deccrement if possible */
3845 /*-----------------------------------------------------------------*/
3847 genMinusDec (iCode * ic)
3849 unsigned int icount;
3850 unsigned int size = getDataSize (IC_RESULT (ic));
3852 /* will try to generate an increment */
3853 /* if the right side is not a literal
3855 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3858 /* if the literal value of the right hand side
3859 is greater than 4 then it is not worth it */
3860 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3863 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3864 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3866 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3870 /* if decrement 16 bits in register */
3871 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3872 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3873 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3881 /* If the next instruction is a goto and the goto target
3882 * is <= 5 instructions previous to this, we can generate
3883 * jumps straight to that target.
3885 if (ic->next && ic->next->op == GOTO
3886 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3889 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3890 tlbl = IC_LABEL (ic->next);
3895 tlbl = newiTempLabel (NULL);
3899 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3900 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3901 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3902 IS_AOP_PREG (IC_RESULT (ic)))
3903 emitcode ("cjne", "%s,#!constbyte,!tlabel"
3904 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE), 0xff
3908 emitcode ("mov", "a,#!constbyte",0xff);
3909 emitcode ("cjne", "a,%s,!tlabel"
3910 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3913 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3916 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3917 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3918 IS_AOP_PREG (IC_RESULT (ic)))
3919 emitcode ("cjne", "%s,#!constbyte,!tlabel"
3920 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE),0xff
3924 emitcode ("cjne", "a,%s,!tlabel"
3925 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3928 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3932 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3933 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3934 IS_AOP_PREG (IC_RESULT (ic)))
3935 emitcode ("cjne", "%s,#!constbyte,!tlabel"
3936 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE),0xff
3940 emitcode ("cjne", "a,%s,!tlabel"
3941 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3944 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3948 emitcode ("", "!tlabeldef", tlbl->key + 100);
3953 /* if the sizes are greater than 1 then we cannot */
3954 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3955 AOP_SIZE (IC_LEFT (ic)) > 1)
3958 /* we can if the aops of the left & result match or
3959 if they are in registers and the registers are the
3962 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3963 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3964 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3967 _startLazyDPSEvaluation ();
3970 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3972 _endLazyDPSEvaluation ();
3980 /*-----------------------------------------------------------------*/
3981 /* addSign - complete with sign */
3982 /*-----------------------------------------------------------------*/
3984 addSign (operand * result, int offset, int sign)
3986 int size = (getDataSize (result) - offset);
3989 _startLazyDPSEvaluation();
3992 emitcode ("rlc", "a");
3993 emitcode ("subb", "a,acc");
3996 aopPut (AOP (result), "a", offset++);
4003 aopPut (AOP (result), zero, offset++);
4006 _endLazyDPSEvaluation();
4010 /*-----------------------------------------------------------------*/
4011 /* genMinusBits - generates code for subtraction of two bits */
4012 /*-----------------------------------------------------------------*/
4014 genMinusBits (iCode * ic)
4016 symbol *lbl = newiTempLabel (NULL);
4018 D (emitcode (";", "genMinusBits "););
4020 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4022 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4023 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4024 emitcode ("cpl", "c");
4025 emitcode ("", "!tlabeldef", (lbl->key + 100));
4026 outBitC (IC_RESULT (ic));
4030 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4031 emitcode ("subb", "a,acc");
4032 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4033 emitcode ("inc", "a");
4034 emitcode ("", "!tlabeldef", (lbl->key + 100));
4035 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4036 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4040 /*-----------------------------------------------------------------*/
4041 /* genMinus - generates code for subtraction */
4042 /*-----------------------------------------------------------------*/
4044 genMinus (iCode * ic)
4046 int size, offset = 0;
4048 unsigned long lit = 0L;
4049 bool pushResult = FALSE;
4051 D (emitcode (";", "genMinus "););
4053 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
4054 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
4055 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
4056 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
4062 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
4064 /* special cases :- */
4065 /* if both left & right are in bit space */
4066 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4067 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4073 /* if I can do an decrement instead
4074 of subtract then GOOD for ME */
4075 if (genMinusDec (ic) == TRUE)
4080 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4082 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4088 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4093 /* if literal, add a,#-lit, else normal subb */
4094 _startLazyDPSEvaluation ();
4097 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
4098 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4099 emitcode ("subb", "a,%s",
4100 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4103 /* first add without previous c */
4105 if (!size && lit==-1) {
4106 emitcode ("dec", "a");
4108 emitcode ("add", "a,#!constbyte",
4109 (unsigned int) (lit & 0x0FFL));
4112 emitcode ("addc", "a,#!constbyte",
4113 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4119 emitcode ("push", "acc");
4123 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4127 _endLazyDPSEvaluation ();
4131 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4133 size = getDataSize (IC_LEFT (ic));
4134 rSize = getDataSize (IC_RESULT (ic));
4136 ADJUST_PUSHED_RESULT(size, rSize);
4138 _startLazyDPSEvaluation ();
4141 emitcode ("pop", "acc");
4142 aopPut (AOP (IC_RESULT (ic)), "a", size);
4144 _endLazyDPSEvaluation ();
4147 adjustArithmeticResult (ic);
4150 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4151 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4152 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4156 /*-----------------------------------------------------------------*/
4157 /* genMultbits :- multiplication of bits */
4158 /*-----------------------------------------------------------------*/
4160 genMultbits (operand * left,
4165 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4166 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4167 aopOp(result, ic, TRUE, FALSE);
4172 /*-----------------------------------------------------------------*/
4173 /* genMultOneByte : 8*8=8/16 bit multiplication */
4174 /*-----------------------------------------------------------------*/
4176 genMultOneByte (operand * left,
4181 sym_link *opetype = operandType (result);
4185 /* (if two literals: the value is computed before) */
4186 /* if one literal, literal on the right */
4187 if (AOP_TYPE (left) == AOP_LIT)
4192 emitcode (";", "swapped left and right");
4195 if (SPEC_USIGN(opetype)
4196 // ignore the sign of left and right, what else can we do?
4197 || (SPEC_USIGN(operandType(left)) &&
4198 SPEC_USIGN(operandType(right)))) {
4199 // just an unsigned 8*8=8/16 multiply
4200 //emitcode (";","unsigned");
4201 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4202 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4203 emitcode ("mul", "ab");
4205 _G.accInUse++; _G.bInUse++;
4206 aopOp(result, ic, TRUE, FALSE);
4208 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4210 // this should never happen
4211 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4212 AOP_SIZE(result), __FILE__, lineno);
4216 aopPut (AOP (result), "a", 0);
4217 _G.accInUse--; _G.bInUse--;
4218 if (AOP_SIZE(result)==2)
4220 aopPut (AOP (result), "b", 1);
4225 // we have to do a signed multiply
4227 emitcode (";", "signed");
4228 emitcode ("clr", "F0"); // reset sign flag
4229 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4231 lbl=newiTempLabel(NULL);
4232 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4233 // left side is negative, 8-bit two's complement, this fails for -128
4234 emitcode ("setb", "F0"); // set sign flag
4235 emitcode ("cpl", "a");
4236 emitcode ("inc", "a");
4238 emitcode ("", "!tlabeldef", lbl->key+100);
4241 if (AOP_TYPE(right)==AOP_LIT) {
4242 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4243 /* AND literal negative */
4244 if ((int) val < 0) {
4245 emitcode ("cpl", "F0"); // complement sign flag
4246 emitcode ("mov", "b,#!constbyte", -val);
4248 emitcode ("mov", "b,#!constbyte", val);
4251 lbl=newiTempLabel(NULL);
4252 emitcode ("mov", "b,a");
4253 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4254 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4255 // right side is negative, 8-bit two's complement
4256 emitcode ("cpl", "F0"); // complement sign flag
4257 emitcode ("cpl", "a");
4258 emitcode ("inc", "a");
4259 emitcode ("", "!tlabeldef", lbl->key+100);
4261 emitcode ("mul", "ab");
4263 _G.accInUse++;_G.bInUse++;
4264 aopOp(result, ic, TRUE, FALSE);
4266 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4268 // this should never happen
4269 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4270 AOP_SIZE(result), __FILE__, lineno);
4274 lbl=newiTempLabel(NULL);
4275 emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4276 // only ONE op was negative, we have to do a 8/16-bit two's complement
4277 emitcode ("cpl", "a"); // lsb
4278 if (AOP_SIZE(result)==1) {
4279 emitcode ("inc", "a");
4281 emitcode ("add", "a,#1");
4282 emitcode ("xch", "a,b");
4283 emitcode ("cpl", "a"); // msb
4284 emitcode ("addc", "a,#0");
4285 emitcode ("xch", "a,b");
4288 emitcode ("", "!tlabeldef", lbl->key+100);
4289 aopPut (AOP (result), "a", 0);
4290 _G.accInUse--;_G.bInUse--;
4291 if (AOP_SIZE(result)==2) {
4292 aopPut (AOP (result), "b", 1);
4296 /*-----------------------------------------------------------------*/
4297 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4298 /*-----------------------------------------------------------------*/
4299 static void genMultTwoByte (operand *left, operand *right,
4300 operand *result, iCode *ic)
4302 sym_link *retype = getSpec(operandType(right));
4303 sym_link *letype = getSpec(operandType(left));
4304 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4307 if (AOP_TYPE (left) == AOP_LIT) {
4312 /* save EA bit in F1 */
4313 lbl = newiTempLabel(NULL);
4314 emitcode ("setb","F1");
4315 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4316 emitcode ("clr","F1");
4317 emitcode("","!tlabeldef",lbl->key+100);
4319 /* load up MB with right */
4321 emitcode("clr","F0");
4322 if (AOP_TYPE(right) == AOP_LIT) {
4323 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4325 emitcode("setb","F0");
4328 emitcode ("mov","mb,#!constbyte",val & 0xff);
4329 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4331 lbl = newiTempLabel(NULL);
4332 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4333 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4334 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4335 emitcode ("xch", "a,b");
4336 emitcode ("cpl","a");
4337 emitcode ("add", "a,#1");
4338 emitcode ("xch", "a,b");
4339 emitcode ("cpl", "a"); // msb
4340 emitcode ("addc", "a,#0");
4341 emitcode ("setb","F0");
4342 emitcode ("","!tlabeldef",lbl->key+100);
4343 emitcode ("mov","mb,b");
4344 emitcode ("mov","mb,a");
4347 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4348 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4350 /* load up MA with left */
4352 lbl = newiTempLabel(NULL);
4353 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4354 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4355 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4356 emitcode ("xch", "a,b");
4357 emitcode ("cpl","a");
4358 emitcode ("add", "a,#1");
4359 emitcode ("xch", "a,b");
4360 emitcode ("cpl", "a"); // msb
4361 emitcode ("addc","a,#0");
4362 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4363 emitcode ("setb","F0");
4364 emitcode ("","!tlabeldef",lbl->key+100);
4365 emitcode ("mov","ma,b");
4366 emitcode ("mov","ma,a");
4368 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4369 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4371 /* wait for multiplication to finish */
4372 lbl = newiTempLabel(NULL);
4373 emitcode("","!tlabeldef", lbl->key+100);
4374 emitcode("mov","a,mcnt1");
4375 emitcode("anl","a,#!constbyte",0x80);
4376 emitcode("jnz","!tlabel",lbl->key+100);
4378 freeAsmop (left, NULL, ic, TRUE);
4379 freeAsmop (right, NULL, ic,TRUE);
4380 aopOp(result, ic, TRUE, FALSE);
4382 /* if unsigned then simple */
4384 emitcode ("mov","a,ma");
4385 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4386 emitcode ("mov","a,ma");
4387 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4388 aopPut(AOP(result),"ma",1);
4389 aopPut(AOP(result),"ma",0);
4391 emitcode("push","ma");
4392 emitcode("push","ma");
4393 emitcode("push","ma");
4395 /* negate result if needed */
4396 lbl = newiTempLabel(NULL);
4397 emitcode("jnb","F0,!tlabel",lbl->key+100);
4398 emitcode("cpl","a");
4399 emitcode("add","a,#1");
4400 emitcode("","!tlabeldef", lbl->key+100);
4401 if (AOP_TYPE(result) == AOP_ACC)
4403 D(emitcode(";", "ACC special case."););
4404 /* We know result is the only live aop, and
4405 * it's obviously not a DPTR2, so AP is available.
4407 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4411 aopPut(AOP(result),"a",0);
4414 emitcode("pop","acc");
4415 lbl = newiTempLabel(NULL);
4416 emitcode("jnb","F0,!tlabel",lbl->key+100);
4417 emitcode("cpl","a");
4418 emitcode("addc","a,#0");
4419 emitcode("","!tlabeldef", lbl->key+100);
4420 aopPut(AOP(result),"a",1);
4421 emitcode("pop","acc");
4422 if (AOP_SIZE(result) >= 3) {
4423 lbl = newiTempLabel(NULL);
4424 emitcode("jnb","F0,!tlabel",lbl->key+100);
4425 emitcode("cpl","a");
4426 emitcode("addc","a,#0");
4427 emitcode("","!tlabeldef", lbl->key+100);
4428 aopPut(AOP(result),"a",2);
4430 emitcode("pop","acc");
4431 if (AOP_SIZE(result) >= 4) {
4432 lbl = newiTempLabel(NULL);
4433 emitcode("jnb","F0,!tlabel",lbl->key+100);
4434 emitcode("cpl","a");
4435 emitcode("addc","a,#0");
4436 emitcode("","!tlabeldef", lbl->key+100);
4437 aopPut(AOP(result),"a",3);
4439 if (AOP_TYPE(result) == AOP_ACC)
4441 /* We stashed the result away above. */
4442 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4446 freeAsmop (result, NULL, ic, TRUE);
4448 /* restore EA bit in F1 */
4449 lbl = newiTempLabel(NULL);
4450 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4451 emitcode ("setb","EA");
4452 emitcode("","!tlabeldef",lbl->key+100);
4456 /*-----------------------------------------------------------------*/
4457 /* genMult - generates code for multiplication */
4458 /*-----------------------------------------------------------------*/
4460 genMult (iCode * ic)
4462 operand *left = IC_LEFT (ic);
4463 operand *right = IC_RIGHT (ic);
4464 operand *result = IC_RESULT (ic);
4466 D (emitcode (";", "genMult "););
4468 /* assign the amsops */
4471 /* special cases first */
4473 if (AOP_TYPE (left) == AOP_CRY &&
4474 AOP_TYPE (right) == AOP_CRY)
4476 genMultbits (left, right, result, ic);
4480 /* if both are of size == 1 */
4481 if (AOP_SIZE (left) == 1 &&
4482 AOP_SIZE (right) == 1)
4484 genMultOneByte (left, right, result, ic);
4488 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4489 /* use the ds390 ARITHMETIC accel UNIT */
4490 genMultTwoByte (left, right, result, ic);
4493 /* should have been converted to function call */
4497 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4498 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4499 freeAsmop (result, NULL, ic, TRUE);
4502 /*-----------------------------------------------------------------*/
4503 /* genDivbits :- division of bits */
4504 /*-----------------------------------------------------------------*/
4506 genDivbits (operand * left,
4514 /* the result must be bit */
4515 LOAD_AB_FOR_DIV (left, right, l);
4516 emitcode ("div", "ab");
4517 emitcode ("rrc", "a");
4518 aopOp(result, ic, TRUE, FALSE);
4520 aopPut (AOP (result), "c", 0);
4523 /*-----------------------------------------------------------------*/
4524 /* genDivOneByte : 8 bit division */
4525 /*-----------------------------------------------------------------*/
4527 genDivOneByte (operand * left,
4532 sym_link *opetype = operandType (result);
4538 /* signed or unsigned */
4539 if (SPEC_USIGN (opetype))
4541 /* unsigned is easy */
4542 LOAD_AB_FOR_DIV (left, right, l);
4543 emitcode ("div", "ab");
4546 aopOp(result, ic, TRUE, FALSE);
4547 aopPut (AOP (result), "a", 0);
4550 size = AOP_SIZE (result) - 1;
4554 aopPut (AOP (result), zero, offset++);
4559 /* signed is a little bit more difficult */
4561 /* save the signs of the operands */
4562 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4564 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4565 emitcode ("push", "acc"); /* save it on the stack */
4567 /* now sign adjust for both left & right */
4568 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4570 lbl = newiTempLabel (NULL);
4571 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4572 emitcode ("cpl", "a");
4573 emitcode ("inc", "a");
4574 emitcode ("", "!tlabeldef", (lbl->key + 100));
4575 emitcode ("mov", "b,a");
4577 /* sign adjust left side */
4578 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4581 lbl = newiTempLabel (NULL);
4582 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4583 emitcode ("cpl", "a");
4584 emitcode ("inc", "a");
4585 emitcode ("", "!tlabeldef", (lbl->key + 100));
4587 /* now the division */
4588 emitcode ("nop", "; workaround for DS80C390 div bug.");
4589 emitcode ("div", "ab");
4590 /* we are interested in the lower order
4592 emitcode ("mov", "b,a");
4593 lbl = newiTempLabel (NULL);
4594 emitcode ("pop", "acc");
4595 /* if there was an over flow we don't
4596 adjust the sign of the result */
4597 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4598 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4600 emitcode ("clr", "a");
4601 emitcode ("subb", "a,b");
4602 emitcode ("mov", "b,a");
4603 emitcode ("", "!tlabeldef", (lbl->key + 100));
4605 /* now we are done */
4606 _G.accInUse++; _G.bInUse++;
4607 aopOp(result, ic, TRUE, FALSE);
4609 aopPut (AOP (result), "b", 0);
4611 size = AOP_SIZE (result) - 1;
4615 emitcode ("mov", "c,b.7");
4616 emitcode ("subb", "a,acc");
4620 aopPut (AOP (result), "a", offset++);
4622 _G.accInUse--; _G.bInUse--;
4626 /*-----------------------------------------------------------------*/
4627 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4628 /*-----------------------------------------------------------------*/
4629 static void genDivTwoByte (operand *left, operand *right,
4630 operand *result, iCode *ic)
4632 sym_link *retype = getSpec(operandType(right));
4633 sym_link *letype = getSpec(operandType(left));
4634 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4637 /* save EA bit in F1 */
4638 lbl = newiTempLabel(NULL);
4639 emitcode ("setb","F1");
4640 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4641 emitcode ("clr","F1");
4642 emitcode("","!tlabeldef",lbl->key+100);
4644 /* load up MA with left */
4646 emitcode("clr","F0");
4647 lbl = newiTempLabel(NULL);
4648 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4649 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4650 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4651 emitcode ("xch", "a,b");
4652 emitcode ("cpl","a");
4653 emitcode ("add", "a,#1");
4654 emitcode ("xch", "a,b");
4655 emitcode ("cpl", "a"); // msb
4656 emitcode ("addc","a,#0");
4657 emitcode ("setb","F0");
4658 emitcode ("","!tlabeldef",lbl->key+100);
4659 emitcode ("mov","ma,b");
4660 emitcode ("mov","ma,a");
4662 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4663 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4666 /* load up MB with right */
4668 if (AOP_TYPE(right) == AOP_LIT) {
4669 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4671 lbl = newiTempLabel(NULL);
4672 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4673 emitcode("setb","F0");
4674 emitcode ("","!tlabeldef",lbl->key+100);
4677 emitcode ("mov","mb,#!constbyte",val & 0xff);
4678 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4680 lbl = newiTempLabel(NULL);
4681 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4682 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4683 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4684 emitcode ("xch", "a,b");
4685 emitcode ("cpl","a");
4686 emitcode ("add", "a,#1");
4687 emitcode ("xch", "a,b");
4688 emitcode ("cpl", "a"); // msb
4689 emitcode ("addc", "a,#0");
4690 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4691 emitcode ("setb","F0");
4692 emitcode ("","!tlabeldef",lbl->key+100);
4693 emitcode ("mov","mb,b");
4694 emitcode ("mov","mb,a");
4697 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4698 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4701 /* wait for multiplication to finish */
4702 lbl = newiTempLabel(NULL);
4703 emitcode("","!tlabeldef", lbl->key+100);
4704 emitcode("mov","a,mcnt1");
4705 emitcode("anl","a,#!constbyte",0x80);
4706 emitcode("jnz","!tlabel",lbl->key+100);
4708 freeAsmop (left, NULL, ic, TRUE);
4709 freeAsmop (right, NULL, ic,TRUE);
4710 aopOp(result, ic, TRUE, FALSE);
4712 /* if unsigned then simple */
4714 aopPut(AOP(result),"ma",1);
4715 aopPut(AOP(result),"ma",0);
4717 emitcode("push","ma");
4719 /* negate result if needed */
4720 lbl = newiTempLabel(NULL);
4721 emitcode("jnb","F0,!tlabel",lbl->key+100);
4722 emitcode("cpl","a");
4723 emitcode("add","a,#1");
4724 emitcode("","!tlabeldef", lbl->key+100);
4725 aopPut(AOP(result),"a",0);
4726 emitcode("pop","acc");
4727 lbl = newiTempLabel(NULL);
4728 emitcode("jnb","F0,!tlabel",lbl->key+100);
4729 emitcode("cpl","a");
4730 emitcode("addc","a,#0");
4731 emitcode("","!tlabeldef", lbl->key+100);
4732 aopPut(AOP(result),"a",1);
4734 freeAsmop (result, NULL, ic, TRUE);
4735 /* restore EA bit in F1 */
4736 lbl = newiTempLabel(NULL);
4737 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4738 emitcode ("setb","EA");
4739 emitcode("","!tlabeldef",lbl->key+100);
4743 /*-----------------------------------------------------------------*/
4744 /* genDiv - generates code for division */
4745 /*-----------------------------------------------------------------*/
4749 operand *left = IC_LEFT (ic);
4750 operand *right = IC_RIGHT (ic);
4751 operand *result = IC_RESULT (ic);
4753 D (emitcode (";", "genDiv "););
4755 /* assign the amsops */
4758 /* special cases first */
4760 if (AOP_TYPE (left) == AOP_CRY &&
4761 AOP_TYPE (right) == AOP_CRY)
4763 genDivbits (left, right, result, ic);
4767 /* if both are of size == 1 */
4768 if (AOP_SIZE (left) == 1 &&
4769 AOP_SIZE (right) == 1)
4771 genDivOneByte (left, right, result, ic);
4775 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4776 /* use the ds390 ARITHMETIC accel UNIT */
4777 genDivTwoByte (left, right, result, ic);
4780 /* should have been converted to function call */
4783 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4784 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4785 freeAsmop (result, NULL, ic, TRUE);
4788 /*-----------------------------------------------------------------*/
4789 /* genModbits :- modulus of bits */
4790 /*-----------------------------------------------------------------*/
4792 genModbits (operand * left,
4800 /* the result must be bit */
4801 LOAD_AB_FOR_DIV (left, right, l);
4802 emitcode ("div", "ab");
4803 emitcode ("mov", "a,b");
4804 emitcode ("rrc", "a");
4805 aopOp(result, ic, TRUE, FALSE);
4806 aopPut (AOP (result), "c", 0);
4809 /*-----------------------------------------------------------------*/
4810 /* genModOneByte : 8 bit modulus */
4811 /*-----------------------------------------------------------------*/
4813 genModOneByte (operand * left,
4818 sym_link *opetype = operandType (result);
4822 /* signed or unsigned */
4823 if (SPEC_USIGN (opetype))
4825 /* unsigned is easy */
4826 LOAD_AB_FOR_DIV (left, right, l);
4827 emitcode ("div", "ab");
4828 aopOp(result, ic, TRUE, FALSE);
4829 aopPut (AOP (result), "b", 0);
4833 /* signed is a little bit more difficult */
4835 /* save the signs of the operands */
4836 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4839 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4840 emitcode ("push", "acc"); /* save it on the stack */
4842 /* now sign adjust for both left & right */
4843 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4846 lbl = newiTempLabel (NULL);
4847 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4848 emitcode ("cpl", "a");
4849 emitcode ("inc", "a");
4850 emitcode ("", "!tlabeldef", (lbl->key + 100));
4851 emitcode ("mov", "b,a");
4853 /* sign adjust left side */
4854 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4857 lbl = newiTempLabel (NULL);
4858 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4859 emitcode ("cpl", "a");
4860 emitcode ("inc", "a");
4861 emitcode ("", "!tlabeldef", (lbl->key + 100));
4863 /* now the multiplication */
4864 emitcode ("nop", "; workaround for DS80C390 div bug.");
4865 emitcode ("div", "ab");
4866 /* we are interested in the lower order
4868 lbl = newiTempLabel (NULL);
4869 emitcode ("pop", "acc");
4870 /* if there was an over flow we don't
4871 adjust the sign of the result */
4872 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4873 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4875 emitcode ("clr", "a");
4876 emitcode ("subb", "a,b");
4877 emitcode ("mov", "b,a");
4878 emitcode ("", "!tlabeldef", (lbl->key + 100));
4881 /* now we are done */
4882 aopOp(result, ic, TRUE, FALSE);
4883 aopPut (AOP (result), "b", 0);
4888 /*-----------------------------------------------------------------*/
4889 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
4890 /*-----------------------------------------------------------------*/
4891 static void genModTwoByte (operand *left, operand *right,
4892 operand *result, iCode *ic)
4894 sym_link *retype = getSpec(operandType(right));
4895 sym_link *letype = getSpec(operandType(left));
4896 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4899 /* load up MA with left */
4900 /* save EA bit in F1 */
4901 lbl = newiTempLabel(NULL);
4902 emitcode ("setb","F1");
4903 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4904 emitcode ("clr","F1");
4905 emitcode("","!tlabeldef",lbl->key+100);
4908 lbl = newiTempLabel(NULL);
4909 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4910 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4911 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4912 emitcode ("xch", "a,b");
4913 emitcode ("cpl","a");
4914 emitcode ("add", "a,#1");
4915 emitcode ("xch", "a,b");
4916 emitcode ("cpl", "a"); // msb
4917 emitcode ("addc","a,#0");
4918 emitcode ("","!tlabeldef",lbl->key+100);
4919 emitcode ("mov","ma,b");
4920 emitcode ("mov","ma,a");
4922 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4923 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4926 /* load up MB with right */
4928 if (AOP_TYPE(right) == AOP_LIT) {
4929 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4933 emitcode ("mov","mb,#!constbyte",val & 0xff);
4934 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4936 lbl = newiTempLabel(NULL);
4937 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4938 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4939 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4940 emitcode ("xch", "a,b");
4941 emitcode ("cpl","a");
4942 emitcode ("add", "a,#1");
4943 emitcode ("xch", "a,b");
4944 emitcode ("cpl", "a"); // msb
4945 emitcode ("addc", "a,#0");
4946 emitcode ("","!tlabeldef",lbl->key+100);
4947 emitcode ("mov","mb,b");
4948 emitcode ("mov","mb,a");
4951 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4952 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4955 /* wait for multiplication to finish */
4956 lbl = newiTempLabel(NULL);
4957 emitcode("","!tlabeldef", lbl->key+100);
4958 emitcode("mov","a,mcnt1");
4959 emitcode("anl","a,#!constbyte",0x80);
4960 emitcode("jnz","!tlabel",lbl->key+100);
4962 freeAsmop (left, NULL, ic, TRUE);
4963 freeAsmop (right, NULL, ic,TRUE);
4964 aopOp(result, ic, TRUE, FALSE);
4966 aopPut(AOP(result),"mb",1);
4967 aopPut(AOP(result),"mb",0);
4968 freeAsmop (result, NULL, ic, TRUE);
4970 /* restore EA bit in F1 */
4971 lbl = newiTempLabel(NULL);
4972 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4973 emitcode ("setb","EA");
4974 emitcode("","!tlabeldef",lbl->key+100);
4978 /*-----------------------------------------------------------------*/
4979 /* genMod - generates code for division */
4980 /*-----------------------------------------------------------------*/
4984 operand *left = IC_LEFT (ic);
4985 operand *right = IC_RIGHT (ic);
4986 operand *result = IC_RESULT (ic);
4988 D (emitcode (";", "genMod "); );
4990 /* assign the amsops */
4993 /* special cases first */
4995 if (AOP_TYPE (left) == AOP_CRY &&
4996 AOP_TYPE (right) == AOP_CRY)
4998 genModbits (left, right, result, ic);
5002 /* if both are of size == 1 */
5003 if (AOP_SIZE (left) == 1 &&
5004 AOP_SIZE (right) == 1)
5006 genModOneByte (left, right, result, ic);
5010 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5011 /* use the ds390 ARITHMETIC accel UNIT */
5012 genModTwoByte (left, right, result, ic);
5016 /* should have been converted to function call */
5020 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5021 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5022 freeAsmop (result, NULL, ic, TRUE);
5025 /*-----------------------------------------------------------------*/
5026 /* genIfxJump :- will create a jump depending on the ifx */
5027 /*-----------------------------------------------------------------*/
5029 genIfxJump (iCode * ic, char *jval)
5032 symbol *tlbl = newiTempLabel (NULL);
5035 D (emitcode (";", "genIfxJump ");
5038 /* if true label then we jump if condition
5042 jlbl = IC_TRUE (ic);
5043 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5044 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5048 /* false label is present */
5049 jlbl = IC_FALSE (ic);
5050 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5051 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5053 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5054 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5056 emitcode (inst, "!tlabel", tlbl->key + 100);
5057 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5058 emitcode ("", "!tlabeldef", tlbl->key + 100);
5060 /* mark the icode as generated */
5064 /*-----------------------------------------------------------------*/
5065 /* genCmp :- greater or less than comparison */
5066 /*-----------------------------------------------------------------*/
5068 genCmp (operand * left, operand * right,
5069 iCode * ic, iCode * ifx, int sign)
5071 int size, offset = 0;
5072 unsigned long lit = 0L;
5075 D (emitcode (";", "genCmp");
5078 result = IC_RESULT (ic);
5080 /* if left & right are bit variables */
5081 if (AOP_TYPE (left) == AOP_CRY &&
5082 AOP_TYPE (right) == AOP_CRY)
5084 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5085 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
5089 /* subtract right from left if at the
5090 end the carry flag is set then we know that
5091 left is greater than right */
5092 size = max (AOP_SIZE (left), AOP_SIZE (right));
5094 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5095 if ((size == 1) && !sign &&
5096 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5098 symbol *lbl = newiTempLabel (NULL);
5099 emitcode ("cjne", "%s,%s,!tlabel",
5100 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5101 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5103 emitcode ("", "!tlabeldef", lbl->key + 100);
5107 if (AOP_TYPE (right) == AOP_LIT)
5109 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5110 /* optimize if(x < 0) or if(x >= 0) */
5119 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5121 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5122 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5124 aopOp (result, ic, FALSE, FALSE);
5126 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5128 freeAsmop (result, NULL, ic, TRUE);
5129 genIfxJump (ifx, "acc.7");
5134 emitcode ("rlc", "a");
5136 goto release_freedLR;
5144 //emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5145 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5146 //emitcode (";", "genCmp #2");
5147 if (sign && (size == 0))
5149 //emitcode (";", "genCmp #3");
5150 emitcode ("xrl", "a,#!constbyte",0x80);
5151 if (AOP_TYPE (right) == AOP_LIT)
5153 unsigned long lit = (unsigned long)
5154 floatFromVal (AOP (right)->aopu.aop_lit);
5155 //emitcode (";", "genCmp #3.1");
5156 emitcode ("subb", "a,#!constbyte",
5157 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5161 //emitcode (";", "genCmp #3.2");
5162 if (AOP_NEEDSACC (right))
5164 emitcode ("push", "acc");
5166 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
5167 FALSE, FALSE, FALSE));
5168 emitcode ("xrl", "b,#!constbyte",0x80);
5169 if (AOP_NEEDSACC (right))
5171 emitcode ("pop", "acc");
5173 emitcode ("subb", "a,b");
5180 //emitcode (";", "genCmp #4");
5181 if (AOP_NEEDSACC (right))
5184 //emitcode (";", "genCmp #4.1");
5185 emitcode ("xch", "a, b");
5186 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
5187 emitcode ("xch", "a, b");
5192 //emitcode (";", "genCmp #4.2");
5193 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
5196 emitcode ("subb", "a,%s", s);
5203 /* Don't need the left & right operands any more; do need the result. */
5204 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5205 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5207 aopOp (result, ic, FALSE, FALSE);
5211 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5217 /* if the result is used in the next
5218 ifx conditional branch then generate
5219 code a little differently */
5222 genIfxJump (ifx, "c");
5228 /* leave the result in acc */
5230 freeAsmop (result, NULL, ic, TRUE);
5233 /*-----------------------------------------------------------------*/
5234 /* genCmpGt :- greater than comparison */
5235 /*-----------------------------------------------------------------*/
5237 genCmpGt (iCode * ic, iCode * ifx)
5239 operand *left, *right;
5240 sym_link *letype, *retype;
5243 D (emitcode (";", "genCmpGt ");
5246 left = IC_LEFT (ic);
5247 right = IC_RIGHT (ic);
5249 letype = getSpec (operandType (left));
5250 retype = getSpec (operandType (right));
5251 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5253 /* assign the left & right amsops */
5256 genCmp (right, left, ic, ifx, sign);
5259 /*-----------------------------------------------------------------*/
5260 /* genCmpLt - less than comparisons */
5261 /*-----------------------------------------------------------------*/
5263 genCmpLt (iCode * ic, iCode * ifx)
5265 operand *left, *right;
5266 sym_link *letype, *retype;
5269 D (emitcode (";", "genCmpLt "););
5271 left = IC_LEFT (ic);
5272 right = IC_RIGHT (ic);
5274 letype = getSpec (operandType (left));
5275 retype = getSpec (operandType (right));
5276 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5278 /* assign the left & right amsops */
5281 genCmp (left, right, ic, ifx, sign);
5284 /*-----------------------------------------------------------------*/
5285 /* gencjneshort - compare and jump if not equal */
5286 /*-----------------------------------------------------------------*/
5288 gencjneshort (operand * left, operand * right, symbol * lbl)
5290 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5292 unsigned long lit = 0L;
5294 D (emitcode (";", "gencjneshort");
5297 /* if the left side is a literal or
5298 if the right is in a pointer register and left
5300 if ((AOP_TYPE (left) == AOP_LIT) ||
5301 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5308 if (AOP_TYPE (right) == AOP_LIT)
5309 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5311 if (opIsGptr (left) || opIsGptr (right))
5313 /* We are comparing a generic pointer to something.
5314 * Exclude the generic type byte from the comparison.
5317 D (emitcode (";", "cjneshort: generic ptr special case.");
5322 /* if the right side is a literal then anything goes */
5323 if (AOP_TYPE (right) == AOP_LIT &&
5324 AOP_TYPE (left) != AOP_DIR)
5328 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5330 emitcode ("cjne", "a,%s,!tlabel",
5331 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5337 /* if the right side is in a register or in direct space or
5338 if the left is a pointer register & right is not */
5339 else if (AOP_TYPE (right) == AOP_REG ||
5340 AOP_TYPE (right) == AOP_DIR ||
5341 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5342 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5346 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5347 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5348 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5349 emitcode ("jnz", "!tlabel", lbl->key + 100);
5351 emitcode ("cjne", "a,%s,!tlabel",
5352 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5359 /* right is a pointer reg need both a & b */
5362 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5363 if (strcmp (l, "b"))
5364 emitcode ("mov", "b,%s", l);
5365 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5366 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5372 /*-----------------------------------------------------------------*/
5373 /* gencjne - compare and jump if not equal */
5374 /*-----------------------------------------------------------------*/
5376 gencjne (operand * left, operand * right, symbol * lbl)
5378 symbol *tlbl = newiTempLabel (NULL);
5380 D (emitcode (";", "gencjne");
5383 gencjneshort (left, right, lbl);
5385 emitcode ("mov", "a,%s", one);
5386 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5387 emitcode ("", "!tlabeldef", lbl->key + 100);
5388 emitcode ("clr", "a");
5389 emitcode ("", "!tlabeldef", tlbl->key + 100);
5392 /*-----------------------------------------------------------------*/
5393 /* genCmpEq - generates code for equal to */
5394 /*-----------------------------------------------------------------*/
5396 genCmpEq (iCode * ic, iCode * ifx)
5398 operand *left, *right, *result;
5400 D (emitcode (";", "genCmpEq ");
5404 AOP_SET_LOCALS (ic);
5406 /* if literal, literal on the right or
5407 if the right is in a pointer register and left
5409 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5410 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5412 operand *t = IC_RIGHT (ic);
5413 IC_RIGHT (ic) = IC_LEFT (ic);
5417 if (ifx && /* !AOP_SIZE(result) */
5418 OP_SYMBOL (result) &&
5419 OP_SYMBOL (result)->regType == REG_CND)
5422 /* if they are both bit variables */
5423 if (AOP_TYPE (left) == AOP_CRY &&
5424 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5426 if (AOP_TYPE (right) == AOP_LIT)
5428 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5431 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5432 emitcode ("cpl", "c");
5436 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5440 emitcode ("clr", "c");
5442 /* AOP_TYPE(right) == AOP_CRY */
5446 symbol *lbl = newiTempLabel (NULL);
5447 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5448 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5449 emitcode ("cpl", "c");
5450 emitcode ("", "!tlabeldef", (lbl->key + 100));
5452 /* if true label then we jump if condition
5454 tlbl = newiTempLabel (NULL);
5457 emitcode ("jnc", "!tlabel", tlbl->key + 100);
5458 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5462 emitcode ("jc", "!tlabel", tlbl->key + 100);
5463 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5465 emitcode ("", "!tlabeldef", tlbl->key + 100);
5469 tlbl = newiTempLabel (NULL);
5470 gencjneshort (left, right, tlbl);
5473 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5474 emitcode ("", "!tlabeldef", tlbl->key + 100);
5478 symbol *lbl = newiTempLabel (NULL);
5479 emitcode ("sjmp", "!tlabel", lbl->key + 100);
5480 emitcode ("", "!tlabeldef", tlbl->key + 100);
5481 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5482 emitcode ("", "!tlabeldef", lbl->key + 100);
5485 /* mark the icode as generated */
5488 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5489 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5493 /* if they are both bit variables */
5494 if (AOP_TYPE (left) == AOP_CRY &&
5495 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5497 if (AOP_TYPE (right) == AOP_LIT)
5499 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5502 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5503 emitcode ("cpl", "c");
5507 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5511 emitcode ("clr", "c");
5513 /* AOP_TYPE(right) == AOP_CRY */
5517 symbol *lbl = newiTempLabel (NULL);
5518 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5519 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5520 emitcode ("cpl", "c");
5521 emitcode ("", "!tlabeldef", (lbl->key + 100));
5524 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5525 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5527 aopOp (result, ic, TRUE, FALSE);
5530 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5537 genIfxJump (ifx, "c");
5540 /* if the result is used in an arithmetic operation
5541 then put the result in place */
5546 gencjne (left, right, newiTempLabel (NULL));
5548 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5549 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5551 aopOp (result, ic, TRUE, FALSE);
5553 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5555 aopPut (AOP (result), "a", 0);
5560 genIfxJump (ifx, "a");
5563 /* if the result is used in an arithmetic operation
5564 then put the result in place */
5565 if (AOP_TYPE (result) != AOP_CRY)
5567 /* leave the result in acc */
5571 freeAsmop (result, NULL, ic, TRUE);
5574 /*-----------------------------------------------------------------*/
5575 /* ifxForOp - returns the icode containing the ifx for operand */
5576 /*-----------------------------------------------------------------*/
5578 ifxForOp (operand * op, iCode * ic)
5580 /* if true symbol then needs to be assigned */
5581 if (IS_TRUE_SYMOP (op))
5584 /* if this has register type condition and
5585 the next instruction is ifx with the same operand
5586 and live to of the operand is upto the ifx only then */
5588 ic->next->op == IFX &&
5589 IC_COND (ic->next)->key == op->key &&
5590 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5595 /*-----------------------------------------------------------------*/
5596 /* hasInc - operand is incremented before any other use */
5597 /*-----------------------------------------------------------------*/
5599 hasInc (operand *op, iCode *ic, int osize)
5601 sym_link *type = operandType(op);
5602 sym_link *retype = getSpec (type);
5603 iCode *lic = ic->next;
5606 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5607 if (!IS_SYMOP(op)) return NULL;
5609 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5610 if (IS_AGGREGATE(type->next)) return NULL;
5611 if (osize != (isize = getSize(type->next))) return NULL;
5614 /* if operand of the form op = op + <sizeof *op> */
5615 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5616 isOperandEqual(IC_RESULT(lic),op) &&
5617 isOperandLiteral(IC_RIGHT(lic)) &&
5618 operandLitValue(IC_RIGHT(lic)) == isize) {
5621 /* if the operand used or deffed */
5622 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5625 /* if GOTO or IFX */
5626 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5632 /*-----------------------------------------------------------------*/
5633 /* genAndOp - for && operation */
5634 /*-----------------------------------------------------------------*/
5636 genAndOp (iCode * ic)
5638 operand *left, *right, *result;
5641 D (emitcode (";", "genAndOp "););
5643 /* note here that && operations that are in an
5644 if statement are taken away by backPatchLabels
5645 only those used in arthmetic operations remain */
5647 AOP_SET_LOCALS (ic);
5649 /* if both are bit variables */
5650 if (AOP_TYPE (left) == AOP_CRY &&
5651 AOP_TYPE (right) == AOP_CRY)
5653 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5654 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5655 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5656 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5658 aopOp (result,ic,FALSE, FALSE);
5663 tlbl = newiTempLabel (NULL);
5665 emitcode ("jz", "!tlabel", tlbl->key + 100);
5667 emitcode ("", "!tlabeldef", tlbl->key + 100);
5668 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5669 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5671 aopOp (result,ic,FALSE, FALSE);
5674 freeAsmop (result, NULL, ic, TRUE);
5678 /*-----------------------------------------------------------------*/
5679 /* genOrOp - for || operation */
5680 /*-----------------------------------------------------------------*/
5682 genOrOp (iCode * ic)
5684 operand *left, *right, *result;
5687 D (emitcode (";", "genOrOp "););
5689 /* note here that || operations that are in an
5690 if statement are taken away by backPatchLabels
5691 only those used in arthmetic operations remain */
5693 AOP_SET_LOCALS (ic);
5695 /* if both are bit variables */
5696 if (AOP_TYPE (left) == AOP_CRY &&
5697 AOP_TYPE (right) == AOP_CRY)
5699 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5700 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5701 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5702 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5704 aopOp (result,ic,FALSE, FALSE);
5710 tlbl = newiTempLabel (NULL);
5712 emitcode ("jnz", "!tlabel", tlbl->key + 100);
5714 emitcode ("", "!tlabeldef", tlbl->key + 100);
5715 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5716 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5718 aopOp (result,ic,FALSE, FALSE);
5723 freeAsmop (result, NULL, ic, TRUE);
5726 /*-----------------------------------------------------------------*/
5727 /* isLiteralBit - test if lit == 2^n */
5728 /*-----------------------------------------------------------------*/
5730 isLiteralBit (unsigned long lit)
5732 unsigned long pw[32] =
5733 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5734 0x100L, 0x200L, 0x400L, 0x800L,
5735 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5736 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5737 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5738 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5739 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5742 for (idx = 0; idx < 32; idx++)
5748 /*-----------------------------------------------------------------*/
5749 /* continueIfTrue - */
5750 /*-----------------------------------------------------------------*/
5752 continueIfTrue (iCode * ic)
5755 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5759 /*-----------------------------------------------------------------*/
5761 /*-----------------------------------------------------------------*/
5763 jumpIfTrue (iCode * ic)
5766 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5770 /*-----------------------------------------------------------------*/
5771 /* jmpTrueOrFalse - */
5772 /*-----------------------------------------------------------------*/
5774 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5776 // ugly but optimized by peephole
5779 symbol *nlbl = newiTempLabel (NULL);
5780 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
5781 emitcode ("", "!tlabeldef", tlbl->key + 100);
5782 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5783 emitcode ("", "!tlabeldef", nlbl->key + 100);
5787 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5788 emitcode ("", "!tlabeldef", tlbl->key + 100);
5793 // Generate code to perform a bit-wise logic operation
5794 // on two operands in far space (assumed to already have been
5795 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5796 // in far space. This requires pushing the result on the stack
5797 // then popping it into the result.
5799 genFarFarLogicOp(iCode *ic, char *logicOp)
5801 int size, resultSize, compSize;
5805 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5806 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5807 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5809 _startLazyDPSEvaluation();
5810 for (size = compSize; (size--); offset++)
5812 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5813 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5814 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5816 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5817 emitcode ("push", "acc");
5819 _endLazyDPSEvaluation();
5821 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5822 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5823 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5825 resultSize = AOP_SIZE(IC_RESULT(ic));
5827 ADJUST_PUSHED_RESULT(compSize, resultSize);
5829 _startLazyDPSEvaluation();
5832 emitcode ("pop", "acc");
5833 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5835 _endLazyDPSEvaluation();
5836 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5840 /*-----------------------------------------------------------------*/
5841 /* genAnd - code for and */
5842 /*-----------------------------------------------------------------*/
5844 genAnd (iCode * ic, iCode * ifx)
5846 operand *left, *right, *result;
5847 int size, offset = 0;
5848 unsigned long lit = 0L;
5853 D (emitcode (";", "genAnd "););
5855 AOP_OP_3_NOFATAL (ic, pushResult);
5856 AOP_SET_LOCALS (ic);
5860 genFarFarLogicOp(ic, "anl");
5865 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5867 AOP_TYPE (left), AOP_TYPE (right));
5868 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5870 AOP_SIZE (left), AOP_SIZE (right));
5873 /* if left is a literal & right is not then exchange them */
5874 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5875 #ifdef LOGIC_OPS_BROKEN
5876 || AOP_NEEDSACC (left)
5880 operand *tmp = right;
5885 /* if result = right then exchange them */
5886 if (sameRegs (AOP (result), AOP (right)))
5888 operand *tmp = right;
5893 /* if right is bit then exchange them */
5894 if (AOP_TYPE (right) == AOP_CRY &&
5895 AOP_TYPE (left) != AOP_CRY)
5897 operand *tmp = right;
5901 if (AOP_TYPE (right) == AOP_LIT)
5902 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5904 size = AOP_SIZE (result);
5907 // result = bit & yy;
5908 if (AOP_TYPE (left) == AOP_CRY)
5910 // c = bit & literal;
5911 if (AOP_TYPE (right) == AOP_LIT)
5915 if (size && sameRegs (AOP (result), AOP (left)))
5918 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5923 if (size && (AOP_TYPE (result) == AOP_CRY))
5925 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5928 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5933 emitcode ("clr", "c");
5938 if (AOP_TYPE (right) == AOP_CRY)
5941 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5942 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5947 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5949 emitcode ("rrc", "a");
5950 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5958 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5959 genIfxJump (ifx, "c");
5963 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5964 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5965 if ((AOP_TYPE (right) == AOP_LIT) &&
5966 (AOP_TYPE (result) == AOP_CRY) &&
5967 (AOP_TYPE (left) != AOP_CRY))
5969 int posbit = isLiteralBit (lit);
5974 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5977 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5983 sprintf (buffer, "acc.%d", posbit & 0x07);
5984 genIfxJump (ifx, buffer);
5991 symbol *tlbl = newiTempLabel (NULL);
5992 int sizel = AOP_SIZE (left);
5994 emitcode ("setb", "c");
5997 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5999 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6001 if ((posbit = isLiteralBit (bytelit)) != 0)
6002 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6005 if (bytelit != 0x0FFL)
6006 emitcode ("anl", "a,%s",
6007 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
6008 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6013 // bit = left & literal
6016 emitcode ("clr", "c");
6017 emitcode ("", "!tlabeldef", tlbl->key + 100);
6019 // if(left & literal)
6023 jmpTrueOrFalse (ifx, tlbl);
6031 /* if left is same as result */
6032 if (sameRegs (AOP (result), AOP (left)))
6034 for (; size--; offset++)
6036 if (AOP_TYPE (right) == AOP_LIT)
6038 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6040 else if (bytelit == 0)
6041 aopPut (AOP (result), zero, offset);
6042 else if (IS_AOP_PREG (result))
6044 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6045 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6046 aopPut (AOP (result), "a", offset);
6049 emitcode ("anl", "%s,%s",
6050 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6051 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6055 if (AOP_TYPE (left) == AOP_ACC)
6056 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6059 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6060 if (IS_AOP_PREG (result))
6062 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6063 aopPut (AOP (result), "a", offset);
6067 emitcode ("anl", "%s,a",
6068 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6075 // left & result in different registers
6076 if (AOP_TYPE (result) == AOP_CRY)
6079 // if(size), result in bit
6080 // if(!size && ifx), conditional oper: if(left & right)
6081 symbol *tlbl = newiTempLabel (NULL);
6082 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6084 emitcode ("setb", "c");
6087 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6088 emitcode ("anl", "a,%s",
6089 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6091 if (AOP_TYPE(left)==AOP_ACC) {
6092 emitcode("mov", "b,a");
6093 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6094 emitcode("anl", "a,b");
6096 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6097 emitcode ("anl", "a,%s",
6098 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6101 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6107 emitcode ("", "!tlabeldef", tlbl->key + 100);
6111 jmpTrueOrFalse (ifx, tlbl);
6115 for (; (size--); offset++)
6118 // result = left & right
6119 if (AOP_TYPE (right) == AOP_LIT)
6121 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6123 aopPut (AOP (result),
6124 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6128 else if (bytelit == 0)
6130 aopPut (AOP (result), zero, offset);
6133 D (emitcode (";", "better literal AND."););
6134 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6135 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6136 FALSE, FALSE, FALSE));
6141 // faster than result <- left, anl result,right
6142 // and better if result is SFR
6143 if (AOP_TYPE (left) == AOP_ACC)
6145 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
6146 FALSE, FALSE, FALSE));
6150 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6151 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6153 emitcode("mov", "b,a");
6157 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6158 emitcode ("anl", "a,%s", rOp);
6161 aopPut (AOP (result), "a", offset);
6167 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6168 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6169 freeAsmop (result, NULL, ic, TRUE);
6173 /*-----------------------------------------------------------------*/
6174 /* genOr - code for or */
6175 /*-----------------------------------------------------------------*/
6177 genOr (iCode * ic, iCode * ifx)
6179 operand *left, *right, *result;
6180 int size, offset = 0;
6181 unsigned long lit = 0L;
6184 D (emitcode (";", "genOr "););
6186 AOP_OP_3_NOFATAL (ic, pushResult);
6187 AOP_SET_LOCALS (ic);
6191 genFarFarLogicOp(ic, "orl");
6197 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6199 AOP_TYPE (left), AOP_TYPE (right));
6200 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6202 AOP_SIZE (left), AOP_SIZE (right));
6205 /* if left is a literal & right is not then exchange them */
6206 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6207 #ifdef LOGIC_OPS_BROKEN
6208 || AOP_NEEDSACC (left) // I think this is a net loss now.
6212 operand *tmp = right;
6217 /* if result = right then exchange them */
6218 if (sameRegs (AOP (result), AOP (right)))
6220 operand *tmp = right;
6225 /* if right is bit then exchange them */
6226 if (AOP_TYPE (right) == AOP_CRY &&
6227 AOP_TYPE (left) != AOP_CRY)
6229 operand *tmp = right;
6233 if (AOP_TYPE (right) == AOP_LIT)
6234 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6236 size = AOP_SIZE (result);
6240 if (AOP_TYPE (left) == AOP_CRY)
6242 if (AOP_TYPE (right) == AOP_LIT)
6244 // c = bit & literal;
6247 // lit != 0 => result = 1
6248 if (AOP_TYPE (result) == AOP_CRY)
6251 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6253 continueIfTrue (ifx);
6256 emitcode ("setb", "c");
6260 // lit == 0 => result = left
6261 if (size && sameRegs (AOP (result), AOP (left)))
6263 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6268 if (AOP_TYPE (right) == AOP_CRY)
6271 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6272 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6277 symbol *tlbl = newiTempLabel (NULL);
6278 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6279 emitcode ("setb", "c");
6280 emitcode ("jb", "%s,!tlabel",
6281 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6283 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6284 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6286 jmpTrueOrFalse (ifx, tlbl);
6292 emitcode ("", "!tlabeldef", tlbl->key + 100);
6301 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6302 genIfxJump (ifx, "c");
6306 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6307 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6308 if ((AOP_TYPE (right) == AOP_LIT) &&
6309 (AOP_TYPE (result) == AOP_CRY) &&
6310 (AOP_TYPE (left) != AOP_CRY))
6316 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6318 continueIfTrue (ifx);
6323 // lit = 0, result = boolean(left)
6325 emitcode ("setb", "c");
6329 symbol *tlbl = newiTempLabel (NULL);
6330 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6332 emitcode ("", "!tlabeldef", tlbl->key + 100);
6336 genIfxJump (ifx, "a");
6344 /* if left is same as result */
6345 if (sameRegs (AOP (result), AOP (left)))
6347 for (; size--; offset++)
6349 if (AOP_TYPE (right) == AOP_LIT)
6351 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6357 if (IS_AOP_PREG (left))
6359 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6360 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6361 aopPut (AOP (result), "a", offset);
6365 emitcode ("orl", "%s,%s",
6366 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6367 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6373 if (AOP_TYPE (left) == AOP_ACC)
6375 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6379 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6380 if (IS_AOP_PREG (left))
6382 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6383 aopPut (AOP (result), "a", offset);
6387 emitcode ("orl", "%s,a",
6388 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6396 // left & result in different registers
6397 if (AOP_TYPE (result) == AOP_CRY)
6400 // if(size), result in bit
6401 // if(!size && ifx), conditional oper: if(left | right)
6402 symbol *tlbl = newiTempLabel (NULL);
6403 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6405 emitcode ("setb", "c");
6408 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6409 emitcode ("orl", "a,%s",
6410 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6412 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6413 emitcode ("orl", "a,%s",
6414 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6416 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6422 emitcode ("", "!tlabeldef", tlbl->key + 100);
6426 jmpTrueOrFalse (ifx, tlbl);
6430 _startLazyDPSEvaluation();
6431 for (; (size--); offset++)
6434 // result = left & right
6435 if (AOP_TYPE (right) == AOP_LIT)
6437 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6439 aopPut (AOP (result),
6440 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6444 D (emitcode (";", "better literal OR."););
6445 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6446 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6447 FALSE, FALSE, FALSE));
6452 // faster than result <- left, anl result,right
6453 // and better if result is SFR
6454 if (AOP_TYPE (left) == AOP_ACC)
6456 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6457 FALSE, FALSE, FALSE));
6461 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6463 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6465 emitcode("mov", "b,a");
6469 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6470 emitcode ("orl", "a,%s", rOp);
6473 aopPut (AOP (result), "a", offset);
6475 _endLazyDPSEvaluation();
6480 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6481 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6482 freeAsmop (result, NULL, ic, TRUE);
6485 /*-----------------------------------------------------------------*/
6486 /* genXor - code for xclusive or */
6487 /*-----------------------------------------------------------------*/
6489 genXor (iCode * ic, iCode * ifx)
6491 operand *left, *right, *result;
6492 int size, offset = 0;
6493 unsigned long lit = 0L;
6496 D (emitcode (";", "genXor "););
6498 AOP_OP_3_NOFATAL (ic, pushResult);
6499 AOP_SET_LOCALS (ic);
6503 genFarFarLogicOp(ic, "xrl");
6508 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6510 AOP_TYPE (left), AOP_TYPE (right));
6511 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6513 AOP_SIZE (left), AOP_SIZE (right));
6516 /* if left is a literal & right is not ||
6517 if left needs acc & right does not */
6518 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6519 #ifdef LOGIC_OPS_BROKEN
6520 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6524 operand *tmp = right;
6529 /* if result = right then exchange them */
6530 if (sameRegs (AOP (result), AOP (right)))
6532 operand *tmp = right;
6537 /* if right is bit then exchange them */
6538 if (AOP_TYPE (right) == AOP_CRY &&
6539 AOP_TYPE (left) != AOP_CRY)
6541 operand *tmp = right;
6545 if (AOP_TYPE (right) == AOP_LIT)
6546 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6548 size = AOP_SIZE (result);
6552 if (AOP_TYPE (left) == AOP_CRY)
6554 if (AOP_TYPE (right) == AOP_LIT)
6556 // c = bit & literal;
6559 // lit>>1 != 0 => result = 1
6560 if (AOP_TYPE (result) == AOP_CRY)
6563 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6565 continueIfTrue (ifx);
6568 emitcode ("setb", "c");
6575 // lit == 0, result = left
6576 if (size && sameRegs (AOP (result), AOP (left)))
6578 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6582 // lit == 1, result = not(left)
6583 if (size && sameRegs (AOP (result), AOP (left)))
6585 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6590 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6591 emitcode ("cpl", "c");
6600 symbol *tlbl = newiTempLabel (NULL);
6601 if (AOP_TYPE (right) == AOP_CRY)
6604 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6608 int sizer = AOP_SIZE (right);
6610 // if val>>1 != 0, result = 1
6611 emitcode ("setb", "c");
6614 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6616 // test the msb of the lsb
6617 emitcode ("anl", "a,#!constbyte",0xfe);
6618 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6622 emitcode ("rrc", "a");
6624 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6625 emitcode ("cpl", "c");
6626 emitcode ("", "!tlabeldef", (tlbl->key + 100));
6633 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6634 genIfxJump (ifx, "c");
6638 if (sameRegs (AOP (result), AOP (left)))
6640 /* if left is same as result */
6641 for (; size--; offset++)
6643 if (AOP_TYPE (right) == AOP_LIT)
6645 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6647 else if (IS_AOP_PREG (left))
6649 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6650 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6651 aopPut (AOP (result), "a", offset);
6654 emitcode ("xrl", "%s,%s",
6655 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6656 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6660 if (AOP_TYPE (left) == AOP_ACC)
6661 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6664 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6665 if (IS_AOP_PREG (left))
6667 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6668 aopPut (AOP (result), "a", offset);
6671 emitcode ("xrl", "%s,a",
6672 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6679 // left & result in different registers
6680 if (AOP_TYPE (result) == AOP_CRY)
6683 // if(size), result in bit
6684 // if(!size && ifx), conditional oper: if(left ^ right)
6685 symbol *tlbl = newiTempLabel (NULL);
6686 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6689 emitcode ("setb", "c");
6692 if ((AOP_TYPE (right) == AOP_LIT) &&
6693 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6695 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6699 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6700 emitcode ("xrl", "a,%s",
6701 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6703 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6704 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6706 emitcode("mov", "b,a");
6710 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6711 emitcode ("xrl", "a,%s", rOp);
6714 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6720 emitcode ("", "!tlabeldef", tlbl->key + 100);
6724 jmpTrueOrFalse (ifx, tlbl);
6728 for (; (size--); offset++)
6731 // result = left & right
6732 if (AOP_TYPE (right) == AOP_LIT)
6734 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6736 aopPut (AOP (result),
6737 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6741 D (emitcode (";", "better literal XOR."););
6742 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6743 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6744 FALSE, FALSE, FALSE));
6748 // faster than result <- left, anl result,right
6749 // and better if result is SFR
6750 if (AOP_TYPE (left) == AOP_ACC)
6752 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6753 FALSE, FALSE, FALSE));
6757 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6758 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6760 emitcode("mov", "b,a");
6764 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6765 emitcode ("xrl", "a,%s", rOp);
6768 aopPut (AOP (result), "a", offset);
6775 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6776 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6777 freeAsmop (result, NULL, ic, TRUE);
6780 /*-----------------------------------------------------------------*/
6781 /* genInline - write the inline code out */
6782 /*-----------------------------------------------------------------*/
6784 genInline (iCode * ic)
6786 char *buffer, *bp, *bp1;
6788 D (emitcode (";", "genInline ");
6791 _G.inLine += (!options.asmpeep);
6793 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6794 strcpy (buffer, IC_INLINE (ic));
6796 /* emit each line as a code */
6821 /* emitcode("",buffer); */
6822 _G.inLine -= (!options.asmpeep);
6825 /*-----------------------------------------------------------------*/
6826 /* genRRC - rotate right with carry */
6827 /*-----------------------------------------------------------------*/
6831 operand *left, *result;
6832 int size, offset = 0;
6835 D (emitcode (";", "genRRC ");
6838 /* rotate right with carry */
6839 left = IC_LEFT (ic);
6840 result = IC_RESULT (ic);
6841 aopOp (left, ic, FALSE, FALSE);
6842 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6844 /* move it to the result */
6845 size = AOP_SIZE (result);
6849 _startLazyDPSEvaluation ();
6852 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6854 emitcode ("rrc", "a");
6855 if (AOP_SIZE (result) > 1)
6856 aopPut (AOP (result), "a", offset--);
6858 _endLazyDPSEvaluation ();
6860 /* now we need to put the carry into the
6861 highest order byte of the result */
6862 if (AOP_SIZE (result) > 1)
6864 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6867 emitcode ("mov", "acc.7,c");
6868 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6869 freeAsmop (left, NULL, ic, TRUE);
6870 freeAsmop (result, NULL, ic, TRUE);
6873 /*-----------------------------------------------------------------*/
6874 /* genRLC - generate code for rotate left with carry */
6875 /*-----------------------------------------------------------------*/
6879 operand *left, *result;
6880 int size, offset = 0;
6883 D (emitcode (";", "genRLC ");
6886 /* rotate right with carry */
6887 left = IC_LEFT (ic);
6888 result = IC_RESULT (ic);
6889 aopOp (left, ic, FALSE, FALSE);
6890 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6892 /* move it to the result */
6893 size = AOP_SIZE (result);
6897 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6899 emitcode ("add", "a,acc");
6900 if (AOP_SIZE (result) > 1)
6902 aopPut (AOP (result), "a", offset++);
6905 _startLazyDPSEvaluation ();
6908 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6910 emitcode ("rlc", "a");
6911 if (AOP_SIZE (result) > 1)
6912 aopPut (AOP (result), "a", offset++);
6914 _endLazyDPSEvaluation ();
6916 /* now we need to put the carry into the
6917 highest order byte of the result */
6918 if (AOP_SIZE (result) > 1)
6920 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6923 emitcode ("mov", "acc.0,c");
6924 aopPut (AOP (result), "a", 0);
6925 freeAsmop (left, NULL, ic, TRUE);
6926 freeAsmop (result, NULL, ic, TRUE);
6929 /*-----------------------------------------------------------------*/
6930 /* genGetHbit - generates code get highest order bit */
6931 /*-----------------------------------------------------------------*/
6933 genGetHbit (iCode * ic)
6935 operand *left, *result;
6936 left = IC_LEFT (ic);
6937 result = IC_RESULT (ic);
6938 aopOp (left, ic, FALSE, FALSE);
6939 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6941 D (emitcode (";", "genGetHbit ");
6944 /* get the highest order byte into a */
6945 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6946 if (AOP_TYPE (result) == AOP_CRY)
6948 emitcode ("rlc", "a");
6953 emitcode ("rl", "a");
6954 emitcode ("anl", "a,#1");
6959 freeAsmop (left, NULL, ic, TRUE);
6960 freeAsmop (result, NULL, ic, TRUE);
6963 /*-----------------------------------------------------------------*/
6964 /* AccRol - rotate left accumulator by known count */
6965 /*-----------------------------------------------------------------*/
6967 AccRol (int shCount)
6969 shCount &= 0x0007; // shCount : 0..7
6976 emitcode ("rl", "a");
6979 emitcode ("rl", "a");
6980 emitcode ("rl", "a");
6983 emitcode ("swap", "a");
6984 emitcode ("rr", "a");
6987 emitcode ("swap", "a");
6990 emitcode ("swap", "a");
6991 emitcode ("rl", "a");
6994 emitcode ("rr", "a");
6995 emitcode ("rr", "a");
6998 emitcode ("rr", "a");
7003 /*-----------------------------------------------------------------*/
7004 /* AccLsh - left shift accumulator by known count */
7005 /*-----------------------------------------------------------------*/
7007 AccLsh (int shCount)
7012 emitcode ("add", "a,acc");
7013 else if (shCount == 2)
7015 emitcode ("add", "a,acc");
7016 emitcode ("add", "a,acc");
7020 /* rotate left accumulator */
7022 /* and kill the lower order bits */
7023 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7028 /*-----------------------------------------------------------------*/
7029 /* AccRsh - right shift accumulator by known count */
7030 /*-----------------------------------------------------------------*/
7032 AccRsh (int shCount)
7039 emitcode ("rrc", "a");
7043 /* rotate right accumulator */
7044 AccRol (8 - shCount);
7045 /* and kill the higher order bits */
7046 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7051 #ifdef BETTER_LITERAL_SHIFT
7052 /*-----------------------------------------------------------------*/
7053 /* AccSRsh - signed right shift accumulator by known count */
7054 /*-----------------------------------------------------------------*/
7056 AccSRsh (int shCount)
7063 emitcode ("mov", "c,acc.7");
7064 emitcode ("rrc", "a");
7066 else if (shCount == 2)
7068 emitcode ("mov", "c,acc.7");
7069 emitcode ("rrc", "a");
7070 emitcode ("mov", "c,acc.7");
7071 emitcode ("rrc", "a");
7075 tlbl = newiTempLabel (NULL);
7076 /* rotate right accumulator */
7077 AccRol (8 - shCount);
7078 /* and kill the higher order bits */
7079 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7080 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7081 emitcode ("orl", "a,#!constbyte",
7082 (unsigned char) ~SRMask[shCount]);
7083 emitcode ("", "!tlabeldef", tlbl->key + 100);
7089 #ifdef BETTER_LITERAL_SHIFT
7090 /*-----------------------------------------------------------------*/
7091 /* shiftR1Left2Result - shift right one byte from left to result */
7092 /*-----------------------------------------------------------------*/
7094 shiftR1Left2Result (operand * left, int offl,
7095 operand * result, int offr,
7096 int shCount, int sign)
7098 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7099 /* shift right accumulator */
7104 aopPut (AOP (result), "a", offr);
7108 #ifdef BETTER_LITERAL_SHIFT
7109 /*-----------------------------------------------------------------*/
7110 /* shiftL1Left2Result - shift left one byte from left to result */
7111 /*-----------------------------------------------------------------*/
7113 shiftL1Left2Result (operand * left, int offl,
7114 operand * result, int offr, int shCount)
7116 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7117 /* shift left accumulator */
7119 aopPut (AOP (result), "a", offr);
7123 #ifdef BETTER_LITERAL_SHIFT
7124 /*-----------------------------------------------------------------*/
7125 /* movLeft2Result - move byte from left to result */
7126 /*-----------------------------------------------------------------*/
7128 movLeft2Result (operand * left, int offl,
7129 operand * result, int offr, int sign)
7132 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7134 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
7136 if (*l == '@' && (IS_AOP_PREG (result)))
7138 emitcode ("mov", "a,%s", l);
7139 aopPut (AOP (result), "a", offr);
7145 aopPut (AOP (result), l, offr);
7149 /* MSB sign in acc.7 ! */
7150 if (getDataSize (left) == offl + 1)
7152 emitcode ("mov", "a,%s", l);
7153 aopPut (AOP (result), "a", offr);
7161 #ifdef BETTER_LITERAL_SHIFT
7162 /*-----------------------------------------------------------------*/
7163 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7164 /*-----------------------------------------------------------------*/
7168 emitcode ("rrc", "a");
7169 emitcode ("xch", "a,%s", x);
7170 emitcode ("rrc", "a");
7171 emitcode ("xch", "a,%s", x);
7175 #ifdef BETTER_LITERAL_SHIFT
7177 /*-----------------------------------------------------------------*/
7178 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7179 /*-----------------------------------------------------------------*/
7183 emitcode ("xch", "a,%s", x);
7184 emitcode ("rlc", "a");
7185 emitcode ("xch", "a,%s", x);
7186 emitcode ("rlc", "a");
7190 #ifdef BETTER_LITERAL_SHIFT
7191 /*-----------------------------------------------------------------*/
7192 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7193 /*-----------------------------------------------------------------*/
7197 emitcode ("xch", "a,%s", x);
7198 emitcode ("add", "a,acc");
7199 emitcode ("xch", "a,%s", x);
7200 emitcode ("rlc", "a");
7204 #ifdef BETTER_LITERAL_SHIFT
7205 /*-----------------------------------------------------------------*/
7206 /* AccAXLsh - left shift a:x by known count (0..7) */
7207 /*-----------------------------------------------------------------*/
7209 AccAXLsh (char *x, int shCount)
7224 case 5: // AAAAABBB:CCCCCDDD
7226 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7228 emitcode ("anl", "a,#!constbyte",
7229 SLMask[shCount]); // BBB00000:CCCCCDDD
7231 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7233 AccRol (shCount); // DDDCCCCC:BBB00000
7235 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7237 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7239 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7241 emitcode ("anl", "a,#!constbyte",
7242 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7244 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7246 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7249 case 6: // AAAAAABB:CCCCCCDD
7250 emitcode ("anl", "a,#!constbyte",
7251 SRMask[shCount]); // 000000BB:CCCCCCDD
7252 emitcode ("mov", "c,acc.0"); // c = B
7253 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7255 AccAXRrl1 (x); // BCCCCCCD:D000000B
7256 AccAXRrl1 (x); // BBCCCCCC:DD000000
7258 emitcode("rrc","a");
7259 emitcode("xch","a,%s", x);
7260 emitcode("rrc","a");
7261 emitcode("mov","c,acc.0"); //<< get correct bit
7262 emitcode("xch","a,%s", x);
7264 emitcode("rrc","a");
7265 emitcode("xch","a,%s", x);
7266 emitcode("rrc","a");
7267 emitcode("xch","a,%s", x);
7270 case 7: // a:x <<= 7
7272 emitcode ("anl", "a,#!constbyte",
7273 SRMask[shCount]); // 0000000B:CCCCCCCD
7275 emitcode ("mov", "c,acc.0"); // c = B
7277 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7279 AccAXRrl1 (x); // BCCCCCCC:D0000000
7288 #ifdef BETTER_LITERAL_SHIFT
7290 /*-----------------------------------------------------------------*/
7291 /* AccAXRsh - right shift a:x known count (0..7) */
7292 /*-----------------------------------------------------------------*/
7294 AccAXRsh (char *x, int shCount)
7302 AccAXRrl1 (x); // 0->a:x
7307 AccAXRrl1 (x); // 0->a:x
7310 AccAXRrl1 (x); // 0->a:x
7315 case 5: // AAAAABBB:CCCCCDDD = a:x
7317 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7319 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7321 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7323 emitcode ("anl", "a,#!constbyte",
7324 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7326 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7328 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7330 emitcode ("anl", "a,#!constbyte",
7331 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7333 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7335 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7337 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7340 case 6: // AABBBBBB:CCDDDDDD
7342 emitcode ("mov", "c,acc.7");
7343 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7345 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7347 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7349 emitcode ("anl", "a,#!constbyte",
7350 SRMask[shCount]); // 000000AA:BBBBBBCC
7353 case 7: // ABBBBBBB:CDDDDDDD
7355 emitcode ("mov", "c,acc.7"); // c = A
7357 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7359 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7361 emitcode ("anl", "a,#!constbyte",
7362 SRMask[shCount]); // 0000000A:BBBBBBBC
7371 #ifdef BETTER_LITERAL_SHIFT
7372 /*-----------------------------------------------------------------*/
7373 /* AccAXRshS - right shift signed a:x known count (0..7) */
7374 /*-----------------------------------------------------------------*/
7376 AccAXRshS (char *x, int shCount)
7384 emitcode ("mov", "c,acc.7");
7385 AccAXRrl1 (x); // s->a:x
7389 emitcode ("mov", "c,acc.7");
7390 AccAXRrl1 (x); // s->a:x
7392 emitcode ("mov", "c,acc.7");
7393 AccAXRrl1 (x); // s->a:x
7398 case 5: // AAAAABBB:CCCCCDDD = a:x
7400 tlbl = newiTempLabel (NULL);
7401 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7403 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7405 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7407 emitcode ("anl", "a,#!constbyte",
7408 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7410 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7412 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7414 emitcode ("anl", "a,#!constbyte",
7415 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7417 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7419 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7421 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7423 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7424 emitcode ("orl", "a,#!constbyte",
7425 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7427 emitcode ("", "!tlabeldef", tlbl->key + 100);
7428 break; // SSSSAAAA:BBBCCCCC
7430 case 6: // AABBBBBB:CCDDDDDD
7432 tlbl = newiTempLabel (NULL);
7433 emitcode ("mov", "c,acc.7");
7434 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7436 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7438 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7440 emitcode ("anl", "a,#!constbyte",
7441 SRMask[shCount]); // 000000AA:BBBBBBCC
7443 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7444 emitcode ("orl", "a,#!constbyte",
7445 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7447 emitcode ("", "!tlabeldef", tlbl->key + 100);
7449 case 7: // ABBBBBBB:CDDDDDDD
7451 tlbl = newiTempLabel (NULL);
7452 emitcode ("mov", "c,acc.7"); // c = A
7454 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7456 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7458 emitcode ("anl", "a,#!constbyte",
7459 SRMask[shCount]); // 0000000A:BBBBBBBC
7461 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7462 emitcode ("orl", "a,#!constbyte",
7463 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7465 emitcode ("", "!tlabeldef", tlbl->key + 100);
7473 #ifdef BETTER_LITERAL_SHIFT
7475 _loadLeftIntoAx(char **lsb,
7481 // Get the initial value from left into a pair of registers.
7482 // MSB must be in A, LSB can be any register.
7484 // If the result is held in registers, it is an optimization
7485 // if the LSB can be held in the register which will hold the,
7486 // result LSB since this saves us from having to copy it into
7487 // the result following AccAXLsh.
7489 // If the result is addressed indirectly, this is not a gain.
7490 if (AOP_NEEDSACC(result))
7494 _startLazyDPSEvaluation();
7495 if (AOP_TYPE(left) == AOP_DPTR2)
7498 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7499 // get LSB in DP2_RESULT_REG.
7500 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7501 assert(!strcmp(leftByte, DP2_RESULT_REG));
7505 // get LSB into DP2_RESULT_REG
7506 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7507 if (strcmp(leftByte, DP2_RESULT_REG))
7510 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7513 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7514 assert(strcmp(leftByte, DP2_RESULT_REG));
7517 _endLazyDPSEvaluation();
7518 *lsb = DP2_RESULT_REG;
7522 if (sameRegs (AOP (result), AOP (left)) &&
7523 ((offl + MSB16) == offr))
7525 /* don't crash result[offr] */
7526 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7527 emitcode ("xch", "a,%s",
7528 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7532 movLeft2Result (left, offl, result, offr, 0);
7533 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7535 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7536 assert(strcmp(*lsb,"a"));
7541 _storeAxResults(char *lsb,
7545 _startLazyDPSEvaluation();
7546 if (AOP_NEEDSACC(result))
7548 /* We have to explicitly update the result LSB.
7550 emitcode("xch","a,%s", lsb);
7551 aopPut(AOP(result), "a", offr);
7552 emitcode("mov","a,%s", lsb);
7554 if (getDataSize (result) > 1)
7556 aopPut (AOP (result), "a", offr + MSB16);
7558 _endLazyDPSEvaluation();
7561 /*-----------------------------------------------------------------*/
7562 /* shiftL2Left2Result - shift left two bytes from left to result */
7563 /*-----------------------------------------------------------------*/
7565 shiftL2Left2Result (operand * left, int offl,
7566 operand * result, int offr, int shCount)
7570 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7572 AccAXLsh (lsb, shCount);
7574 _storeAxResults(lsb, result, offr);
7578 #ifdef BETTER_LITERAL_SHIFT
7579 /*-----------------------------------------------------------------*/
7580 /* shiftR2Left2Result - shift right two bytes from left to result */
7581 /*-----------------------------------------------------------------*/
7583 shiftR2Left2Result (operand * left, int offl,
7584 operand * result, int offr,
7585 int shCount, int sign)
7589 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7591 /* a:x >> shCount (x = lsb(result)) */
7594 AccAXRshS(lsb, shCount);
7598 AccAXRsh(lsb, shCount);
7601 _storeAxResults(lsb, result, offr);
7607 /*-----------------------------------------------------------------*/
7608 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7609 /*-----------------------------------------------------------------*/
7611 shiftLLeftOrResult (operand * left, int offl,
7612 operand * result, int offr, int shCount)
7614 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7615 /* shift left accumulator */
7617 /* or with result */
7618 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7619 /* back to result */
7620 aopPut (AOP (result), "a", offr);
7626 /*-----------------------------------------------------------------*/
7627 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7628 /*-----------------------------------------------------------------*/
7630 shiftRLeftOrResult (operand * left, int offl,
7631 operand * result, int offr, int shCount)
7633 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7634 /* shift right accumulator */
7636 /* or with result */
7637 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7638 /* back to result */
7639 aopPut (AOP (result), "a", offr);
7643 #ifdef BETTER_LITERAL_SHIFT
7644 /*-----------------------------------------------------------------*/
7645 /* genlshOne - left shift a one byte quantity by known count */
7646 /*-----------------------------------------------------------------*/
7648 genlshOne (operand * result, operand * left, int shCount)
7650 D (emitcode (";", "genlshOne "););
7651 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7655 #ifdef BETTER_LITERAL_SHIFT
7656 /*-----------------------------------------------------------------*/
7657 /* genlshTwo - left shift two bytes by known amount != 0 */
7658 /*-----------------------------------------------------------------*/
7660 genlshTwo (operand * result, operand * left, int shCount)
7664 D (emitcode (";", "genlshTwo "););
7666 size = getDataSize (result);
7668 /* if shCount >= 8 */
7673 _startLazyDPSEvaluation();
7679 _endLazyDPSEvaluation();
7680 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7681 aopPut (AOP (result), zero, LSB);
7685 movLeft2Result (left, LSB, result, MSB16, 0);
7686 aopPut (AOP (result), zero, LSB);
7687 _endLazyDPSEvaluation();
7692 aopPut (AOP (result), zero, LSB);
7693 _endLazyDPSEvaluation();
7697 /* 1 <= shCount <= 7 */
7702 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7706 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7714 /*-----------------------------------------------------------------*/
7715 /* shiftLLong - shift left one long from left to result */
7716 /* offl = LSB or MSB16 */
7717 /*-----------------------------------------------------------------*/
7719 shiftLLong (operand * left, operand * result, int offr)
7722 int size = AOP_SIZE (result);
7724 if (size >= LSB + offr)
7726 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7728 emitcode ("add", "a,acc");
7729 if (sameRegs (AOP (left), AOP (result)) &&
7730 size >= MSB16 + offr && offr != LSB)
7731 emitcode ("xch", "a,%s",
7732 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7734 aopPut (AOP (result), "a", LSB + offr);
7737 if (size >= MSB16 + offr)
7739 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7741 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7744 emitcode ("rlc", "a");
7745 if (sameRegs (AOP (left), AOP (result)) &&
7746 size >= MSB24 + offr && offr != LSB)
7747 emitcode ("xch", "a,%s",
7748 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7750 aopPut (AOP (result), "a", MSB16 + offr);
7753 if (size >= MSB24 + offr)
7755 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7757 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7760 emitcode ("rlc", "a");
7761 if (sameRegs (AOP (left), AOP (result)) &&
7762 size >= MSB32 + offr && offr != LSB)
7763 emitcode ("xch", "a,%s",
7764 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7766 aopPut (AOP (result), "a", MSB24 + offr);
7769 if (size > MSB32 + offr)
7771 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7773 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7776 emitcode ("rlc", "a");
7777 aopPut (AOP (result), "a", MSB32 + offr);
7780 aopPut (AOP (result), zero, LSB);
7786 /*-----------------------------------------------------------------*/
7787 /* genlshFour - shift four byte by a known amount != 0 */
7788 /*-----------------------------------------------------------------*/
7790 genlshFour (operand * result, operand * left, int shCount)
7794 D (emitcode (";", "genlshFour ");
7797 size = AOP_SIZE (result);
7799 /* if shifting more that 3 bytes */
7804 /* lowest order of left goes to the highest
7805 order of the destination */
7806 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7808 movLeft2Result (left, LSB, result, MSB32, 0);
7809 aopPut (AOP (result), zero, LSB);
7810 aopPut (AOP (result), zero, MSB16);
7811 aopPut (AOP (result), zero, MSB24);
7815 /* more than two bytes */
7816 else if (shCount >= 16)
7818 /* lower order two bytes goes to higher order two bytes */
7820 /* if some more remaining */
7822 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7825 movLeft2Result (left, MSB16, result, MSB32, 0);
7826 movLeft2Result (left, LSB, result, MSB24, 0);
7828 aopPut (AOP (result), zero, MSB16);
7829 aopPut (AOP (result), zero, LSB);
7833 /* if more than 1 byte */
7834 else if (shCount >= 8)
7836 /* lower order three bytes goes to higher order three bytes */
7841 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7843 movLeft2Result (left, LSB, result, MSB16, 0);
7849 movLeft2Result (left, MSB24, result, MSB32, 0);
7850 movLeft2Result (left, MSB16, result, MSB24, 0);
7851 movLeft2Result (left, LSB, result, MSB16, 0);
7852 aopPut (AOP (result), zero, LSB);
7854 else if (shCount == 1)
7855 shiftLLong (left, result, MSB16);
7858 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7859 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7860 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7861 aopPut (AOP (result), zero, LSB);
7866 /* 1 <= shCount <= 7 */
7867 else if (shCount <= 2)
7869 shiftLLong (left, result, LSB);
7871 shiftLLong (result, result, LSB);
7873 /* 3 <= shCount <= 7, optimize */
7876 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7877 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7878 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7883 #ifdef BETTER_LITERAL_SHIFT
7884 /*-----------------------------------------------------------------*/
7885 /* genLeftShiftLiteral - left shifting by known count */
7886 /*-----------------------------------------------------------------*/
7888 genLeftShiftLiteral (operand * left,
7893 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7896 size = getSize (operandType (result));
7898 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7900 /* We only handle certain easy cases so far. */
7902 && (shCount < (size * 8))
7906 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7910 freeAsmop (right, NULL, ic, TRUE);
7912 aopOp(left, ic, FALSE, FALSE);
7913 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7916 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7918 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7919 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7921 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7924 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7926 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7927 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7929 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7935 emitcode ("; shift left ", "result %d, left %d", size,
7939 /* I suppose that the left size >= result size */
7942 _startLazyDPSEvaluation();
7945 movLeft2Result (left, size, result, size, 0);
7947 _endLazyDPSEvaluation();
7949 else if (shCount >= (size * 8))
7951 _startLazyDPSEvaluation();
7954 aopPut (AOP (result), zero, size);
7956 _endLazyDPSEvaluation();
7963 genlshOne (result, left, shCount);
7967 genlshTwo (result, left, shCount);
7971 genlshFour (result, left, shCount);
7975 fprintf(stderr, "*** ack! mystery literal shift!\n");
7979 freeAsmop (left, NULL, ic, TRUE);
7980 freeAsmop (result, NULL, ic, TRUE);
7985 /*-----------------------------------------------------------------*/
7986 /* genLeftShift - generates code for left shifting */
7987 /*-----------------------------------------------------------------*/
7989 genLeftShift (iCode * ic)
7991 operand *left, *right, *result;
7994 symbol *tlbl, *tlbl1;
7996 D (emitcode (";", "genLeftShift "););
7998 right = IC_RIGHT (ic);
7999 left = IC_LEFT (ic);
8000 result = IC_RESULT (ic);
8002 aopOp (right, ic, FALSE, FALSE);
8005 #ifdef BETTER_LITERAL_SHIFT
8006 /* if the shift count is known then do it
8007 as efficiently as possible */
8008 if (AOP_TYPE (right) == AOP_LIT)
8010 if (genLeftShiftLiteral (left, right, result, ic))
8017 /* shift count is unknown then we have to form
8018 a loop get the loop count in B : Note: we take
8019 only the lower order byte since shifting
8020 more that 32 bits make no sense anyway, ( the
8021 largest size of an object can be only 32 bits ) */
8023 if (AOP_TYPE (right) == AOP_LIT)
8025 /* Really should be handled by genLeftShiftLiteral,
8026 * but since I'm too lazy to fix that today, at least we can make
8027 * some small improvement.
8029 emitcode("mov", "b,#!constbyte",
8030 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8034 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8035 emitcode ("inc", "b");
8037 freeAsmop (right, NULL, ic, TRUE);
8038 aopOp (left, ic, FALSE, FALSE);
8039 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8041 /* now move the left to the result if they are not the
8043 if (!sameRegs (AOP (left), AOP (result)) &&
8044 AOP_SIZE (result) > 1)
8047 size = AOP_SIZE (result);
8049 _startLazyDPSEvaluation ();
8052 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8053 if (*l == '@' && (IS_AOP_PREG (result)))
8056 emitcode ("mov", "a,%s", l);
8057 aopPut (AOP (result), "a", offset);
8060 aopPut (AOP (result), l, offset);
8063 _endLazyDPSEvaluation ();
8066 tlbl = newiTempLabel (NULL);
8067 size = AOP_SIZE (result);
8069 tlbl1 = newiTempLabel (NULL);
8071 /* if it is only one byte then */
8074 symbol *tlbl1 = newiTempLabel (NULL);
8076 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8078 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8079 emitcode ("", "!tlabeldef", tlbl->key + 100);
8080 emitcode ("add", "a,acc");
8081 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8082 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8083 aopPut (AOP (result), "a", 0);
8087 reAdjustPreg (AOP (result));
8089 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8090 emitcode ("", "!tlabeldef", tlbl->key + 100);
8091 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8093 emitcode ("add", "a,acc");
8094 aopPut (AOP (result), "a", offset++);
8095 _startLazyDPSEvaluation ();
8098 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8100 emitcode ("rlc", "a");
8101 aopPut (AOP (result), "a", offset++);
8103 _endLazyDPSEvaluation ();
8104 reAdjustPreg (AOP (result));
8106 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8107 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8109 freeAsmop (left, NULL, ic, TRUE);
8110 freeAsmop (result, NULL, ic, TRUE);
8113 #ifdef BETTER_LITERAL_SHIFT
8114 /*-----------------------------------------------------------------*/
8115 /* genrshOne - right shift a one byte quantity by known count */
8116 /*-----------------------------------------------------------------*/
8118 genrshOne (operand * result, operand * left,
8119 int shCount, int sign)
8121 D (emitcode (";", "genrshOne"););
8122 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8126 #ifdef BETTER_LITERAL_SHIFT
8127 /*-----------------------------------------------------------------*/
8128 /* genrshTwo - right shift two bytes by known amount != 0 */
8129 /*-----------------------------------------------------------------*/
8131 genrshTwo (operand * result, operand * left,
8132 int shCount, int sign)
8134 D (emitcode (";", "genrshTwo"););
8136 /* if shCount >= 8 */
8140 _startLazyDPSEvaluation();
8143 shiftR1Left2Result (left, MSB16, result, LSB,
8148 movLeft2Result (left, MSB16, result, LSB, sign);
8150 addSign (result, MSB16, sign);
8151 _endLazyDPSEvaluation();
8154 /* 1 <= shCount <= 7 */
8157 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8164 /*-----------------------------------------------------------------*/
8165 /* shiftRLong - shift right one long from left to result */
8166 /* offl = LSB or MSB16 */
8167 /*-----------------------------------------------------------------*/
8169 shiftRLong (operand * left, int offl,
8170 operand * result, int sign)
8172 int isSameRegs=sameRegs(AOP(left),AOP(result));
8174 if (isSameRegs && offl>1) {
8175 // we are in big trouble, but this shouldn't happen
8176 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8179 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
8184 emitcode ("rlc", "a");
8185 emitcode ("subb", "a,acc");
8186 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
8188 aopPut (AOP(result), zero, MSB32);
8193 emitcode ("clr", "c");
8195 emitcode ("mov", "c,acc.7");
8198 emitcode ("rrc", "a");
8200 if (isSameRegs && offl==MSB16) {
8201 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
8203 aopPut (AOP (result), "a", MSB32);
8204 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
8207 emitcode ("rrc", "a");
8208 if (isSameRegs && offl==1) {
8209 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
8211 aopPut (AOP (result), "a", MSB24);
8212 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
8214 emitcode ("rrc", "a");
8215 aopPut (AOP (result), "a", MSB16 - offl);
8219 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
8220 emitcode ("rrc", "a");
8221 aopPut (AOP (result), "a", LSB);
8228 /*-----------------------------------------------------------------*/
8229 /* genrshFour - shift four byte by a known amount != 0 */
8230 /*-----------------------------------------------------------------*/
8232 genrshFour (operand * result, operand * left,
8233 int shCount, int sign)
8235 D (emitcode (";", "genrshFour");
8238 /* if shifting more that 3 bytes */
8243 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8245 movLeft2Result (left, MSB32, result, LSB, sign);
8246 addSign (result, MSB16, sign);
8248 else if (shCount >= 16)
8252 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8255 movLeft2Result (left, MSB24, result, LSB, 0);
8256 movLeft2Result (left, MSB32, result, MSB16, sign);
8258 addSign (result, MSB24, sign);
8260 else if (shCount >= 8)
8264 shiftRLong (left, MSB16, result, sign);
8265 else if (shCount == 0)
8267 movLeft2Result (left, MSB16, result, LSB, 0);
8268 movLeft2Result (left, MSB24, result, MSB16, 0);
8269 movLeft2Result (left, MSB32, result, MSB24, sign);
8270 addSign (result, MSB32, sign);
8274 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8275 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8276 /* the last shift is signed */
8277 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8278 addSign (result, MSB32, sign);
8282 { /* 1 <= shCount <= 7 */
8285 shiftRLong (left, LSB, result, sign);
8287 shiftRLong (result, LSB, result, sign);
8291 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8292 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8293 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8299 #ifdef BETTER_LITERAL_SHIFT
8300 /*-----------------------------------------------------------------*/
8301 /* genRightShiftLiteral - right shifting by known count */
8302 /*-----------------------------------------------------------------*/
8304 genRightShiftLiteral (operand * left,
8310 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8313 size = getSize (operandType (result));
8315 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8317 /* We only handle certain easy cases so far. */
8319 && (shCount < (size * 8))
8323 D(emitcode (";", "genRightShiftLiteral wimping out"););
8327 freeAsmop (right, NULL, ic, TRUE);
8329 aopOp (left, ic, FALSE, FALSE);
8330 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8333 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8337 /* test the LEFT size !!! */
8339 /* I suppose that the left size >= result size */
8342 size = getDataSize (result);
8343 _startLazyDPSEvaluation();
8346 movLeft2Result (left, size, result, size, 0);
8348 _endLazyDPSEvaluation();
8350 else if (shCount >= (size * 8))
8354 /* get sign in acc.7 */
8355 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8357 addSign (result, LSB, sign);
8364 genrshOne (result, left, shCount, sign);
8368 genrshTwo (result, left, shCount, sign);
8372 genrshFour (result, left, shCount, sign);
8379 freeAsmop (left, NULL, ic, TRUE);
8380 freeAsmop (result, NULL, ic, TRUE);
8386 /*-----------------------------------------------------------------*/
8387 /* genSignedRightShift - right shift of signed number */
8388 /*-----------------------------------------------------------------*/
8390 genSignedRightShift (iCode * ic)
8392 operand *right, *left, *result;
8395 symbol *tlbl, *tlbl1;
8397 D (emitcode (";", "genSignedRightShift "););
8399 /* we do it the hard way put the shift count in b
8400 and loop thru preserving the sign */
8402 right = IC_RIGHT (ic);
8403 left = IC_LEFT (ic);
8404 result = IC_RESULT (ic);
8406 aopOp (right, ic, FALSE, FALSE);
8408 #ifdef BETTER_LITERAL_SHIFT
8409 if (AOP_TYPE (right) == AOP_LIT)
8411 if (genRightShiftLiteral (left, right, result, ic, 1))
8417 /* shift count is unknown then we have to form
8418 a loop get the loop count in B : Note: we take
8419 only the lower order byte since shifting
8420 more that 32 bits make no sense anyway, ( the
8421 largest size of an object can be only 32 bits ) */
8423 if (AOP_TYPE (right) == AOP_LIT)
8425 /* Really should be handled by genRightShiftLiteral,
8426 * but since I'm too lazy to fix that today, at least we can make
8427 * some small improvement.
8429 emitcode("mov", "b,#!constbyte",
8430 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8434 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8435 emitcode ("inc", "b");
8437 freeAsmop (right, NULL, ic, TRUE);
8438 aopOp (left, ic, FALSE, FALSE);
8439 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8441 /* now move the left to the result if they are not the
8443 if (!sameRegs (AOP (left), AOP (result)) &&
8444 AOP_SIZE (result) > 1)
8447 size = AOP_SIZE (result);
8449 _startLazyDPSEvaluation ();
8452 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8453 if (*l == '@' && IS_AOP_PREG (result))
8456 emitcode ("mov", "a,%s", l);
8457 aopPut (AOP (result), "a", offset);
8460 aopPut (AOP (result), l, offset);
8463 _endLazyDPSEvaluation ();
8466 /* mov the highest order bit to OVR */
8467 tlbl = newiTempLabel (NULL);
8468 tlbl1 = newiTempLabel (NULL);
8470 size = AOP_SIZE (result);
8472 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8473 emitcode ("rlc", "a");
8474 emitcode ("mov", "ov,c");
8475 /* if it is only one byte then */
8478 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8480 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8481 emitcode ("", "!tlabeldef", tlbl->key + 100);
8482 emitcode ("mov", "c,ov");
8483 emitcode ("rrc", "a");
8484 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8485 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8486 aopPut (AOP (result), "a", 0);
8490 reAdjustPreg (AOP (result));
8491 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8492 emitcode ("", "!tlabeldef", tlbl->key + 100);
8493 emitcode ("mov", "c,ov");
8494 _startLazyDPSEvaluation ();
8497 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8499 emitcode ("rrc", "a");
8500 aopPut (AOP (result), "a", offset--);
8502 _endLazyDPSEvaluation ();
8503 reAdjustPreg (AOP (result));
8504 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8505 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8508 freeAsmop (left, NULL, ic, TRUE);
8509 freeAsmop (result, NULL, ic, TRUE);
8512 /*-----------------------------------------------------------------*/
8513 /* genRightShift - generate code for right shifting */
8514 /*-----------------------------------------------------------------*/
8516 genRightShift (iCode * ic)
8518 operand *right, *left, *result;
8522 symbol *tlbl, *tlbl1;
8524 D (emitcode (";", "genRightShift "););
8526 /* if signed then we do it the hard way preserve the
8527 sign bit moving it inwards */
8528 retype = getSpec (operandType (IC_RESULT (ic)));
8530 if (!SPEC_USIGN (retype))
8532 genSignedRightShift (ic);
8536 /* signed & unsigned types are treated the same : i.e. the
8537 signed is NOT propagated inwards : quoting from the
8538 ANSI - standard : "for E1 >> E2, is equivalent to division
8539 by 2**E2 if unsigned or if it has a non-negative value,
8540 otherwise the result is implementation defined ", MY definition
8541 is that the sign does not get propagated */
8543 right = IC_RIGHT (ic);
8544 left = IC_LEFT (ic);
8545 result = IC_RESULT (ic);
8547 aopOp (right, ic, FALSE, FALSE);
8549 #ifdef BETTER_LITERAL_SHIFT
8550 /* if the shift count is known then do it
8551 as efficiently as possible */
8552 if (AOP_TYPE (right) == AOP_LIT)
8554 if (genRightShiftLiteral (left, right, result, ic, 0))
8561 /* shift count is unknown then we have to form
8562 a loop get the loop count in B : Note: we take
8563 only the lower order byte since shifting
8564 more that 32 bits make no sense anyway, ( the
8565 largest size of an object can be only 32 bits ) */
8567 if (AOP_TYPE (right) == AOP_LIT)
8569 /* Really should be handled by genRightShiftLiteral,
8570 * but since I'm too lazy to fix that today, at least we can make
8571 * some small improvement.
8573 emitcode("mov", "b,#!constbyte",
8574 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8578 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8579 emitcode ("inc", "b");
8581 freeAsmop (right, NULL, ic, TRUE);
8582 aopOp (left, ic, FALSE, FALSE);
8583 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8585 /* now move the left to the result if they are not the
8587 if (!sameRegs (AOP (left), AOP (result)) &&
8588 AOP_SIZE (result) > 1)
8591 size = AOP_SIZE (result);
8593 _startLazyDPSEvaluation ();
8596 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8597 if (*l == '@' && IS_AOP_PREG (result))
8600 emitcode ("mov", "a,%s", l);
8601 aopPut (AOP (result), "a", offset);
8604 aopPut (AOP (result), l, offset);
8607 _endLazyDPSEvaluation ();
8610 tlbl = newiTempLabel (NULL);
8611 tlbl1 = newiTempLabel (NULL);
8612 size = AOP_SIZE (result);
8615 /* if it is only one byte then */
8618 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8620 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8621 emitcode ("", "!tlabeldef", tlbl->key + 100);
8623 emitcode ("rrc", "a");
8624 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8625 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8626 aopPut (AOP (result), "a", 0);
8630 reAdjustPreg (AOP (result));
8631 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8632 emitcode ("", "!tlabeldef", tlbl->key + 100);
8634 _startLazyDPSEvaluation ();
8637 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8639 emitcode ("rrc", "a");
8640 aopPut (AOP (result), "a", offset--);
8642 _endLazyDPSEvaluation ();
8643 reAdjustPreg (AOP (result));
8645 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8646 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8649 freeAsmop (left, NULL, ic, TRUE);
8650 freeAsmop (result, NULL, ic, TRUE);
8653 /*-----------------------------------------------------------------*/
8654 /* genUnpackBits - generates code for unpacking bits */
8655 /*-----------------------------------------------------------------*/
8657 genUnpackBits (operand * result, char *rname, int ptype)
8664 D (emitcode (";", "genUnpackBits ");
8667 etype = getSpec (operandType (result));
8669 /* read the first byte */
8675 emitcode ("mov", "a,@%s", rname);
8679 emitcode ("movx", "a,@%s", rname);
8683 emitcode ("movx", "a,@dptr");
8687 emitcode ("clr", "a");
8688 emitcode ("movc", "a,@a+dptr");
8692 emitcode ("lcall", "__gptrget");
8696 /* if we have bitdisplacement then it fits */
8697 /* into this byte completely or if length is */
8698 /* less than a byte */
8699 if ((shCnt = SPEC_BSTR (etype)) ||
8700 (SPEC_BLEN (etype) <= 8))
8703 /* shift right acc */
8706 emitcode ("anl", "a,#!constbyte",
8707 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8708 aopPut (AOP (result), "a", offset);
8712 /* bit field did not fit in a byte */
8713 rlen = SPEC_BLEN (etype) - 8;
8714 aopPut (AOP (result), "a", offset++);
8723 emitcode ("inc", "%s", rname);
8724 emitcode ("mov", "a,@%s", rname);
8728 emitcode ("inc", "%s", rname);
8729 emitcode ("movx", "a,@%s", rname);
8733 emitcode ("inc", "dptr");
8734 emitcode ("movx", "a,@dptr");
8738 emitcode ("clr", "a");
8739 emitcode ("inc", "dptr");
8740 emitcode ("movc", "a,@a+dptr");
8744 emitcode ("inc", "dptr");
8745 emitcode ("lcall", "__gptrget");
8750 /* if we are done */
8754 aopPut (AOP (result), "a", offset++);
8760 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
8761 aopPut (AOP (result), "a", offset);
8768 /*-----------------------------------------------------------------*/
8769 /* genDataPointerGet - generates code when ptr offset is known */
8770 /*-----------------------------------------------------------------*/
8772 genDataPointerGet (operand * left,
8778 int size, offset = 0;
8779 aopOp (result, ic, TRUE, FALSE);
8781 /* get the string representation of the name */
8782 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8783 size = AOP_SIZE (result);
8784 _startLazyDPSEvaluation ();
8788 sprintf (buffer, "(%s + %d)", l + 1, offset);
8790 sprintf (buffer, "%s", l + 1);
8791 aopPut (AOP (result), buffer, offset++);
8793 _endLazyDPSEvaluation ();
8795 freeAsmop (left, NULL, ic, TRUE);
8796 freeAsmop (result, NULL, ic, TRUE);
8799 /*-----------------------------------------------------------------*/
8800 /* genNearPointerGet - emitcode for near pointer fetch */
8801 /*-----------------------------------------------------------------*/
8803 genNearPointerGet (operand * left,
8811 sym_link *rtype, *retype, *letype;
8812 sym_link *ltype = operandType (left);
8815 rtype = operandType (result);
8816 retype = getSpec (rtype);
8817 letype = getSpec (ltype);
8819 aopOp (left, ic, FALSE, FALSE);
8821 /* if left is rematerialisable and
8822 result is not bit variable type and
8823 the left is pointer to data space i.e
8824 lower 128 bytes of space */
8825 if (AOP_TYPE (left) == AOP_IMMD &&
8826 !IS_BITVAR (retype) &&
8827 !IS_BITVAR (letype) &&
8828 DCL_TYPE (ltype) == POINTER)
8830 genDataPointerGet (left, result, ic);
8834 /* if the value is already in a pointer register
8835 then don't need anything more */
8836 if (!AOP_INPREG (AOP (left)))
8838 /* otherwise get a free pointer register */
8840 preg = getFreePtr (ic, &aop, FALSE);
8841 emitcode ("mov", "%s,%s",
8843 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8847 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8849 freeAsmop (left, NULL, ic, TRUE);
8850 aopOp (result, ic, FALSE, FALSE);
8852 /* if bitfield then unpack the bits */
8853 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8854 genUnpackBits (result, rname, POINTER);
8857 /* we have can just get the values */
8858 int size = AOP_SIZE (result);
8863 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8866 emitcode ("mov", "a,@%s", rname);
8867 aopPut (AOP (result), "a", offset);
8871 sprintf (buffer, "@%s", rname);
8872 aopPut (AOP (result), buffer, offset);
8876 emitcode ("inc", "%s", rname);
8880 /* now some housekeeping stuff */
8883 /* we had to allocate for this iCode */
8884 if (pi) { /* post increment present */
8885 aopPut(AOP ( left ),rname,0);
8887 freeAsmop (NULL, aop, ic, TRUE);
8891 /* we did not allocate which means left
8892 already in a pointer register, then
8893 if size > 0 && this could be used again
8894 we have to point it back to where it
8896 if (AOP_SIZE (result) > 1 &&
8897 !OP_SYMBOL (left)->remat &&
8898 (OP_SYMBOL (left)->liveTo > ic->seq ||
8902 int size = AOP_SIZE (result) - 1;
8904 emitcode ("dec", "%s", rname);
8909 freeAsmop (result, NULL, ic, TRUE);
8910 if (pi) pi->generated = 1;
8913 /*-----------------------------------------------------------------*/
8914 /* genPagedPointerGet - emitcode for paged pointer fetch */
8915 /*-----------------------------------------------------------------*/
8917 genPagedPointerGet (operand * left,
8925 sym_link *rtype, *retype, *letype;
8927 rtype = operandType (result);
8928 retype = getSpec (rtype);
8929 letype = getSpec (operandType (left));
8930 aopOp (left, ic, FALSE, FALSE);
8932 /* if the value is already in a pointer register
8933 then don't need anything more */
8934 if (!AOP_INPREG (AOP (left)))
8936 /* otherwise get a free pointer register */
8938 preg = getFreePtr (ic, &aop, FALSE);
8939 emitcode ("mov", "%s,%s",
8941 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8945 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8947 freeAsmop (left, NULL, ic, TRUE);
8948 aopOp (result, ic, FALSE, FALSE);
8950 /* if bitfield then unpack the bits */
8951 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8952 genUnpackBits (result, rname, PPOINTER);
8955 /* we have can just get the values */
8956 int size = AOP_SIZE (result);
8962 emitcode ("movx", "a,@%s", rname);
8963 aopPut (AOP (result), "a", offset);
8968 emitcode ("inc", "%s", rname);
8972 /* now some housekeeping stuff */
8975 /* we had to allocate for this iCode */
8976 if (pi) aopPut ( AOP (left), rname, 0);
8977 freeAsmop (NULL, aop, ic, TRUE);
8981 /* we did not allocate which means left
8982 already in a pointer register, then
8983 if size > 0 && this could be used again
8984 we have to point it back to where it
8986 if (AOP_SIZE (result) > 1 &&
8987 !OP_SYMBOL (left)->remat &&
8988 (OP_SYMBOL (left)->liveTo > ic->seq ||
8992 int size = AOP_SIZE (result) - 1;
8994 emitcode ("dec", "%s", rname);
8999 freeAsmop (result, NULL, ic, TRUE);
9000 if (pi) pi->generated = 1;
9003 /*-----------------------------------------------------------------*/
9004 /* genFarPointerGet - gget value from far space */
9005 /*-----------------------------------------------------------------*/
9007 genFarPointerGet (operand * left,
9008 operand * result, iCode * ic, iCode *pi)
9010 int size, offset, dopi=1;
9011 sym_link *retype = getSpec (operandType (result));
9012 sym_link *letype = getSpec (operandType (left));
9013 D (emitcode (";", "genFarPointerGet");
9016 aopOp (left, ic, FALSE, FALSE);
9018 /* if the operand is already in dptr
9019 then we do nothing else we move the value to dptr */
9020 if (AOP_TYPE (left) != AOP_STR)
9022 /* if this is remateriazable */
9023 if (AOP_TYPE (left) == AOP_IMMD)
9025 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9029 /* we need to get it byte by byte */
9030 _startLazyDPSEvaluation ();
9031 if (AOP_TYPE (left) != AOP_DPTR)
9033 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9034 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9035 if (options.model == MODEL_FLAT24)
9036 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9040 /* We need to generate a load to DPTR indirect through DPTR. */
9041 D (emitcode (";", "genFarPointerGet -- indirection special case.");
9043 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9044 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9045 if (options.model == MODEL_FLAT24)
9046 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9047 emitcode ("pop", "dph");
9048 emitcode ("pop", "dpl");
9051 _endLazyDPSEvaluation ();
9054 /* so dptr know contains the address */
9055 aopOp (result, ic, FALSE, TRUE);
9057 /* if bit then unpack */
9058 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9059 genUnpackBits (result, "dptr", FPOINTER);
9062 size = AOP_SIZE (result);
9065 _startLazyDPSEvaluation ();
9072 emitcode ("movx", "a,@dptr");
9073 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9074 emitcode ("inc", "dptr");
9076 aopPut (AOP (result), "a", offset++);
9078 _endLazyDPSEvaluation ();
9080 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9081 aopPut ( AOP (left), "dpl", 0);
9082 aopPut ( AOP (left), "dph", 1);
9083 if (options.model == MODEL_FLAT24)
9084 aopPut ( AOP (left), "dpx", 2);
9086 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9087 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9089 size = AOP_SIZE (result) - 1;
9090 while (size--) emitcode ("lcall","__decdptr");
9093 freeAsmop (left, NULL, ic, TRUE);
9094 freeAsmop (result, NULL, ic, TRUE);
9097 /*-----------------------------------------------------------------*/
9098 /* emitcodePointerGet - gget value from code space */
9099 /*-----------------------------------------------------------------*/
9101 emitcodePointerGet (operand * left,
9102 operand * result, iCode * ic, iCode *pi)
9104 int size, offset, dopi=1;
9105 sym_link *retype = getSpec (operandType (result));
9107 aopOp (left, ic, FALSE, FALSE);
9109 /* if the operand is already in dptr
9110 then we do nothing else we move the value to dptr */
9111 if (AOP_TYPE (left) != AOP_STR)
9113 /* if this is remateriazable */
9114 if (AOP_TYPE (left) == AOP_IMMD)
9116 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9119 { /* we need to get it byte by byte */
9120 _startLazyDPSEvaluation ();
9121 if (AOP_TYPE (left) != AOP_DPTR)
9123 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9124 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9125 if (options.model == MODEL_FLAT24)
9126 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9130 /* We need to generate a load to DPTR indirect through DPTR. */
9131 D (emitcode (";", "gencodePointerGet -- indirection special case.");
9133 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9134 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9135 if (options.model == MODEL_FLAT24)
9136 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9137 emitcode ("pop", "dph");
9138 emitcode ("pop", "dpl");
9141 _endLazyDPSEvaluation ();
9144 /* so dptr know contains the address */
9145 aopOp (result, ic, FALSE, TRUE);
9147 /* if bit then unpack */
9148 if (IS_BITVAR (retype))
9149 genUnpackBits (result, "dptr", CPOINTER);
9152 size = AOP_SIZE (result);
9155 _startLazyDPSEvaluation ();
9161 emitcode ("clr", "a");
9162 emitcode ("movc", "a,@a+dptr");
9163 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9164 emitcode ("inc", "dptr");
9165 aopPut (AOP (result), "a", offset++);
9167 _endLazyDPSEvaluation ();
9169 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9170 aopPut ( AOP (left), "dpl", 0);
9171 aopPut ( AOP (left), "dph", 1);
9172 if (options.model == MODEL_FLAT24)
9173 aopPut ( AOP (left), "dpx", 2);
9175 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9176 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9178 size = AOP_SIZE (result) - 1;
9179 while (size--) emitcode ("lcall","__decdptr");
9182 freeAsmop (left, NULL, ic, TRUE);
9183 freeAsmop (result, NULL, ic, TRUE);
9186 /*-----------------------------------------------------------------*/
9187 /* genGenPointerGet - gget value from generic pointer space */
9188 /*-----------------------------------------------------------------*/
9190 genGenPointerGet (operand * left,
9191 operand * result, iCode * ic, iCode * pi)
9194 sym_link *retype = getSpec (operandType (result));
9195 sym_link *letype = getSpec (operandType (left));
9197 D (emitcode (";", "genGenPointerGet "); );
9199 aopOp (left, ic, FALSE, (OP_SYMBOL(left)->ruonly ? FALSE : TRUE));
9201 /* if the operand is already in dptr
9202 then we do nothing else we move the value to dptr */
9203 if (AOP_TYPE (left) != AOP_STR)
9205 /* if this is remateriazable */
9206 if (AOP_TYPE (left) == AOP_IMMD)
9208 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9209 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9210 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
9212 emitcode ("mov", "b,#%d", pointerCode (retype));
9215 { /* we need to get it byte by byte */
9216 _startLazyDPSEvaluation ();
9217 if (AOP(left)->type==AOP_DPTR2) {
9219 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
9222 emitcode ("mov", "dpl,%s", l);
9223 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
9226 emitcode ("mov", "dph,%s", l);
9227 if (options.model == MODEL_FLAT24) {
9228 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
9231 emitcode ("mov", "dpx,%s", l);
9232 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9234 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9237 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
9238 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
9239 if (options.model == MODEL_FLAT24) {
9240 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9241 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9243 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9246 _endLazyDPSEvaluation ();
9249 /* so dptr know contains the address */
9250 aopOp (result, ic, FALSE, TRUE);
9252 /* if bit then unpack */
9253 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9254 genUnpackBits (result, "dptr", GPOINTER);
9257 size = AOP_SIZE (result);
9262 emitcode ("lcall", "__gptrget");
9263 aopPut (AOP (result), "a", offset++);
9264 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9265 emitcode ("inc", "dptr");
9269 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9270 aopPut ( AOP (left), "dpl", 0);
9271 aopPut ( AOP (left), "dph", 1);
9272 if (options.model == MODEL_FLAT24) {
9273 aopPut ( AOP (left), "dpx", 2);
9274 aopPut ( AOP (left), "b", 3);
9275 } else aopPut ( AOP (left), "b", 2);
9277 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9278 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9280 size = AOP_SIZE (result) - 1;
9281 while (size--) emitcode ("lcall","__decdptr");
9284 freeAsmop (left, NULL, ic, TRUE);
9285 freeAsmop (result, NULL, ic, TRUE);
9288 /*-----------------------------------------------------------------*/
9289 /* genPointerGet - generate code for pointer get */
9290 /*-----------------------------------------------------------------*/
9292 genPointerGet (iCode * ic, iCode *pi)
9294 operand *left, *result;
9295 sym_link *type, *etype;
9298 D (emitcode (";", "genPointerGet ");
9301 left = IC_LEFT (ic);
9302 result = IC_RESULT (ic);
9304 /* depending on the type of pointer we need to
9305 move it to the correct pointer register */
9306 type = operandType (left);
9307 etype = getSpec (type);
9308 /* if left is of type of pointer then it is simple */
9309 if (IS_PTR (type) && !IS_FUNC (type->next))
9310 p_type = DCL_TYPE (type);
9313 /* we have to go by the storage class */
9314 p_type = PTR_TYPE (SPEC_OCLS (etype));
9316 /* special case when cast remat */
9317 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9318 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9319 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9320 type = type = operandType (left);
9321 p_type = DCL_TYPE (type);
9323 /* now that we have the pointer type we assign
9324 the pointer values */
9330 genNearPointerGet (left, result, ic, pi);
9334 genPagedPointerGet (left, result, ic, pi);
9338 genFarPointerGet (left, result, ic, pi);
9342 emitcodePointerGet (left, result, ic, pi);
9346 genGenPointerGet (left, result, ic, pi);
9352 /*-----------------------------------------------------------------*/
9353 /* genPackBits - generates code for packed bit storage */
9354 /*-----------------------------------------------------------------*/
9356 genPackBits (sym_link * etype,
9358 char *rname, int p_type)
9366 blen = SPEC_BLEN (etype);
9367 bstr = SPEC_BSTR (etype);
9369 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9372 /* if the bit lenth is less than or */
9373 /* it exactly fits a byte then */
9374 if (SPEC_BLEN (etype) <= 8)
9376 shCount = SPEC_BSTR (etype);
9378 /* shift left acc */
9381 if (SPEC_BLEN (etype) < 8)
9382 { /* if smaller than a byte */
9388 emitcode ("mov", "b,a");
9389 emitcode ("mov", "a,@%s", rname);
9393 emitcode ("mov", "b,a");
9394 emitcode ("movx", "a,@dptr");
9398 emitcode ("push", "b");
9399 emitcode ("push", "acc");
9400 emitcode ("lcall", "__gptrget");
9401 emitcode ("pop", "b");
9405 emitcode ("anl", "a,#!constbyte", (unsigned char)
9406 ((unsigned char) (0xFF << (blen + bstr)) |
9407 (unsigned char) (0xFF >> (8 - bstr))));
9408 emitcode ("orl", "a,b");
9409 if (p_type == GPOINTER)
9410 emitcode ("pop", "b");
9417 emitcode ("mov", "@%s,a", rname);
9421 emitcode ("movx", "@dptr,a");
9425 emitcode ("lcall", "__gptrput");
9430 if (SPEC_BLEN (etype) <= 8)
9433 emitcode ("inc", "%s", rname);
9434 rLen = SPEC_BLEN (etype);
9436 /* now generate for lengths greater than one byte */
9440 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9452 emitcode ("mov", "@%s,a", rname);
9455 emitcode ("mov", "@%s,%s", rname, l);
9460 emitcode ("movx", "@dptr,a");
9465 emitcode ("lcall", "__gptrput");
9468 emitcode ("inc", "%s", rname);
9473 /* last last was not complete */
9476 /* save the byte & read byte */
9480 emitcode ("mov", "b,a");
9481 emitcode ("mov", "a,@%s", rname);
9485 emitcode ("mov", "b,a");
9486 emitcode ("movx", "a,@dptr");
9490 emitcode ("push", "b");
9491 emitcode ("push", "acc");
9492 emitcode ("lcall", "__gptrget");
9493 emitcode ("pop", "b");
9497 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9498 emitcode ("orl", "a,b");
9501 if (p_type == GPOINTER)
9502 emitcode ("pop", "b");
9508 emitcode ("mov", "@%s,a", rname);
9512 emitcode ("movx", "@dptr,a");
9516 emitcode ("lcall", "__gptrput");
9520 /*-----------------------------------------------------------------*/
9521 /* genDataPointerSet - remat pointer to data space */
9522 /*-----------------------------------------------------------------*/
9524 genDataPointerSet (operand * right,
9528 int size, offset = 0;
9529 char *l, buffer[256];
9531 aopOp (right, ic, FALSE, FALSE);
9533 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9534 size = AOP_SIZE (right);
9538 sprintf (buffer, "(%s + %d)", l + 1, offset);
9540 sprintf (buffer, "%s", l + 1);
9541 emitcode ("mov", "%s,%s", buffer,
9542 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9545 freeAsmop (right, NULL, ic, TRUE);
9546 freeAsmop (result, NULL, ic, TRUE);
9549 /*-----------------------------------------------------------------*/
9550 /* genNearPointerSet - emitcode for near pointer put */
9551 /*-----------------------------------------------------------------*/
9553 genNearPointerSet (operand * right,
9561 sym_link *retype, *letype;
9562 sym_link *ptype = operandType (result);
9564 retype = getSpec (operandType (right));
9565 letype = getSpec (ptype);
9567 aopOp (result, ic, FALSE, FALSE);
9569 /* if the result is rematerializable &
9570 in data space & not a bit variable */
9571 if (AOP_TYPE (result) == AOP_IMMD &&
9572 DCL_TYPE (ptype) == POINTER &&
9573 !IS_BITVAR (retype) &&
9574 !IS_BITVAR (letype))
9576 genDataPointerSet (right, result, ic);
9580 /* if the value is already in a pointer register
9581 then don't need anything more */
9582 if (!AOP_INPREG (AOP (result)))
9584 /* otherwise get a free pointer register */
9586 preg = getFreePtr (ic, &aop, FALSE);
9587 emitcode ("mov", "%s,%s",
9589 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9593 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9595 aopOp (right, ic, FALSE, FALSE);
9597 /* if bitfield then unpack the bits */
9598 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9599 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9602 /* we have can just get the values */
9603 int size = AOP_SIZE (right);
9608 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9612 emitcode ("mov", "@%s,a", rname);
9615 emitcode ("mov", "@%s,%s", rname, l);
9617 emitcode ("inc", "%s", rname);
9622 /* now some housekeeping stuff */
9625 /* we had to allocate for this iCode */
9626 if (pi) aopPut (AOP (result),rname,0);
9627 freeAsmop (NULL, aop, ic, TRUE);
9631 /* we did not allocate which means left
9632 already in a pointer register, then
9633 if size > 0 && this could be used again
9634 we have to point it back to where it
9636 if (AOP_SIZE (right) > 1 &&
9637 !OP_SYMBOL (result)->remat &&
9638 (OP_SYMBOL (result)->liveTo > ic->seq ||
9642 int size = AOP_SIZE (right) - 1;
9644 emitcode ("dec", "%s", rname);
9649 if (pi) pi->generated = 1;
9650 freeAsmop (result, NULL, ic, TRUE);
9651 freeAsmop (right, NULL, ic, TRUE);
9656 /*-----------------------------------------------------------------*/
9657 /* genPagedPointerSet - emitcode for Paged pointer put */
9658 /*-----------------------------------------------------------------*/
9660 genPagedPointerSet (operand * right,
9668 sym_link *retype, *letype;
9670 retype = getSpec (operandType (right));
9671 letype = getSpec (operandType (result));
9673 aopOp (result, ic, FALSE, FALSE);
9675 /* if the value is already in a pointer register
9676 then don't need anything more */
9677 if (!AOP_INPREG (AOP (result)))
9679 /* otherwise get a free pointer register */
9681 preg = getFreePtr (ic, &aop, FALSE);
9682 emitcode ("mov", "%s,%s",
9684 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9688 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9690 aopOp (right, ic, FALSE, FALSE);
9692 /* if bitfield then unpack the bits */
9693 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9694 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9697 /* we have can just get the values */
9698 int size = AOP_SIZE (right);
9703 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9706 emitcode ("movx", "@%s,a", rname);
9709 emitcode ("inc", "%s", rname);
9715 /* now some housekeeping stuff */
9718 if (pi) aopPut (AOP (result),rname,0);
9719 /* we had to allocate for this iCode */
9720 freeAsmop (NULL, aop, ic, TRUE);
9724 /* we did not allocate which means left
9725 already in a pointer register, then
9726 if size > 0 && this could be used again
9727 we have to point it back to where it
9729 if (AOP_SIZE (right) > 1 &&
9730 !OP_SYMBOL (result)->remat &&
9731 (OP_SYMBOL (result)->liveTo > ic->seq ||
9735 int size = AOP_SIZE (right) - 1;
9737 emitcode ("dec", "%s", rname);
9742 if (pi) pi->generated = 1;
9743 freeAsmop (result, NULL, ic, TRUE);
9744 freeAsmop (right, NULL, ic, TRUE);
9749 /*-----------------------------------------------------------------*/
9750 /* genFarPointerSet - set value from far space */
9751 /*-----------------------------------------------------------------*/
9753 genFarPointerSet (operand * right,
9754 operand * result, iCode * ic, iCode *pi)
9756 int size, offset, dopi=1;
9757 sym_link *retype = getSpec (operandType (right));
9758 sym_link *letype = getSpec (operandType (result));
9760 aopOp (result, ic, FALSE, FALSE);
9762 /* if the operand is already in dptr
9763 then we do nothing else we move the value to dptr */
9764 if (AOP_TYPE (result) != AOP_STR)
9766 /* if this is remateriazable */
9767 if (AOP_TYPE (result) == AOP_IMMD)
9768 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9771 /* we need to get it byte by byte */
9772 _startLazyDPSEvaluation ();
9773 if (AOP_TYPE (result) != AOP_DPTR)
9775 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9776 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9777 if (options.model == MODEL_FLAT24)
9778 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9782 /* We need to generate a load to DPTR indirect through DPTR. */
9783 D (emitcode (";", "genFarPointerSet -- indirection special case.");
9785 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9786 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9787 if (options.model == MODEL_FLAT24)
9788 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9789 emitcode ("pop", "dph");
9790 emitcode ("pop", "dpl");
9793 _endLazyDPSEvaluation ();
9796 /* so dptr know contains the address */
9797 aopOp (right, ic, FALSE, TRUE);
9799 /* if bit then unpack */
9800 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9801 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9804 size = AOP_SIZE (right);
9807 _startLazyDPSEvaluation ();
9810 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9816 emitcode ("movx", "@dptr,a");
9817 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
9818 emitcode ("inc", "dptr");
9820 _endLazyDPSEvaluation ();
9823 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
9824 aopPut (AOP(result),"dpl",0);
9825 aopPut (AOP(result),"dph",1);
9826 if (options.model == MODEL_FLAT24)
9827 aopPut (AOP(result),"dpx",2);
9829 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9830 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9832 size = AOP_SIZE (right) - 1;
9833 while (size--) emitcode ("lcall","__decdptr");
9835 freeAsmop (result, NULL, ic, TRUE);
9836 freeAsmop (right, NULL, ic, TRUE);
9839 /*-----------------------------------------------------------------*/
9840 /* genGenPointerSet - set value from generic pointer space */
9841 /*-----------------------------------------------------------------*/
9843 genGenPointerSet (operand * right,
9844 operand * result, iCode * ic, iCode *pi)
9847 sym_link *retype = getSpec (operandType (right));
9848 sym_link *letype = getSpec (operandType (result));
9850 aopOp (result, ic, FALSE, OP_SYMBOL(result)->ruonly ? FALSE : TRUE);
9852 /* if the operand is already in dptr
9853 then we do nothing else we move the value to dptr */
9854 if (AOP_TYPE (result) != AOP_STR)
9856 _startLazyDPSEvaluation ();
9857 /* if this is remateriazable */
9858 if (AOP_TYPE (result) == AOP_IMMD)
9860 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9861 if (AOP(result)->aopu.aop_immd.from_cast_remat)
9862 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
9864 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9867 { /* we need to get it byte by byte */
9868 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9869 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9870 if (options.model == MODEL_FLAT24) {
9871 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9872 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9874 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9877 _endLazyDPSEvaluation ();
9879 /* so dptr know contains the address */
9880 aopOp (right, ic, FALSE, TRUE);
9882 /* if bit then unpack */
9883 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9884 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9887 size = AOP_SIZE (right);
9890 _startLazyDPSEvaluation ();
9893 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9899 emitcode ("lcall", "__gptrput");
9900 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
9901 emitcode ("inc", "dptr");
9903 _endLazyDPSEvaluation ();
9906 if (pi && AOP_TYPE (result) != AOP_IMMD) {
9907 aopPut (AOP(result),"dpl",0);
9908 aopPut (AOP(result),"dph",1);
9909 if (options.model == MODEL_FLAT24) {
9910 aopPut (AOP(result),"dpx",2);
9911 aopPut (AOP(result),"b",3);
9913 aopPut (AOP(result),"b",2);
9916 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9917 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9919 size = AOP_SIZE (right) - 1;
9920 while (size--) emitcode ("lcall","__decdptr");
9922 freeAsmop (result, NULL, ic, TRUE);
9923 freeAsmop (right, NULL, ic, TRUE);
9926 /*-----------------------------------------------------------------*/
9927 /* genPointerSet - stores the value into a pointer location */
9928 /*-----------------------------------------------------------------*/
9930 genPointerSet (iCode * ic, iCode *pi)
9932 operand *right, *result;
9933 sym_link *type, *etype;
9936 D (emitcode (";", "genPointerSet ");
9939 right = IC_RIGHT (ic);
9940 result = IC_RESULT (ic);
9942 /* depending on the type of pointer we need to
9943 move it to the correct pointer register */
9944 type = operandType (result);
9945 etype = getSpec (type);
9946 /* if left is of type of pointer then it is simple */
9947 if (IS_PTR (type) && !IS_FUNC (type->next))
9949 p_type = DCL_TYPE (type);
9953 /* we have to go by the storage class */
9954 p_type = PTR_TYPE (SPEC_OCLS (etype));
9956 /* special case when cast remat */
9957 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9958 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9959 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9960 type = type = operandType (result);
9961 p_type = DCL_TYPE (type);
9964 /* now that we have the pointer type we assign
9965 the pointer values */
9971 genNearPointerSet (right, result, ic, pi);
9975 genPagedPointerSet (right, result, ic, pi);
9979 genFarPointerSet (right, result, ic, pi);
9983 genGenPointerSet (right, result, ic, pi);
9989 /*-----------------------------------------------------------------*/
9990 /* genIfx - generate code for Ifx statement */
9991 /*-----------------------------------------------------------------*/
9993 genIfx (iCode * ic, iCode * popIc)
9995 operand *cond = IC_COND (ic);
9998 D (emitcode (";", "genIfx "););
10000 aopOp (cond, ic, FALSE, FALSE);
10002 /* get the value into acc */
10003 if (AOP_TYPE (cond) != AOP_CRY)
10007 /* the result is now in the accumulator */
10008 freeAsmop (cond, NULL, ic, TRUE);
10010 /* if there was something to be popped then do it */
10014 /* if the condition is a bit variable */
10015 if (isbit && IS_ITEMP (cond) &&
10017 genIfxJump (ic, SPIL_LOC (cond)->rname);
10018 else if (isbit && !IS_ITEMP (cond))
10019 genIfxJump (ic, OP_SYMBOL (cond)->rname);
10021 genIfxJump (ic, "a");
10026 /*-----------------------------------------------------------------*/
10027 /* genAddrOf - generates code for address of */
10028 /*-----------------------------------------------------------------*/
10030 genAddrOf (iCode * ic)
10032 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10035 D (emitcode (";", "genAddrOf ");
10038 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10040 /* if the operand is on the stack then we
10041 need to get the stack offset of this
10043 if (sym->onStack) {
10045 /* if 10 bit stack */
10046 if (options.stack10bit) {
10048 tsprintf(buff,"#!constbyte",(options.stack_loc >> 16) & 0xff);
10049 /* if it has an offset then we need to compute it */
10050 emitcode ("subb", "a,#!constbyte",
10051 -((sym->stack < 0) ?
10052 ((short) (sym->stack - _G.nRegsSaved)) :
10053 ((short) sym->stack)) & 0xff);
10054 emitcode ("mov","b,a");
10055 emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ?
10056 ((short) (sym->stack - _G.nRegsSaved)) :
10057 ((short) sym->stack)) >> 8) & 0xff);
10059 emitcode ("mov", "a,_bpx");
10060 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
10061 ((char) (sym->stack - _G.nRegsSaved)) :
10062 ((char) sym->stack )) & 0xff);
10063 emitcode ("mov", "b,a");
10064 emitcode ("mov", "a,_bpx+1");
10065 emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ?
10066 ((short) (sym->stack - _G.nRegsSaved)) :
10067 ((short) sym->stack )) >> 8) & 0xff);
10068 aopPut (AOP (IC_RESULT (ic)), "b", 0);
10069 aopPut (AOP (IC_RESULT (ic)), "a", 1);
10070 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10072 /* we can just move _bp */
10073 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10074 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10075 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10078 /* if it has an offset then we need to compute it */
10080 emitcode ("mov", "a,_bp");
10081 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10082 aopPut (AOP (IC_RESULT (ic)), "a", 0);
10084 /* we can just move _bp */
10085 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10087 /* fill the result with zero */
10088 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10091 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10093 "*** warning: pointer to stack var truncated.\n");
10098 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10104 /* object not on stack then we need the name */
10105 size = AOP_SIZE (IC_RESULT (ic));
10110 char s[SDCC_NAME_MAX];
10114 tsprintf(s,"!his",sym->rname);
10117 tsprintf(s,"!hihis",sym->rname);
10120 tsprintf(s,"!hihihis",sym->rname);
10122 default: /* should not need this (just in case) */
10123 sprintf (s, "#(%s >> %d)",
10128 sprintf (s, "#%s", sym->rname);
10129 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10133 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10137 /*-----------------------------------------------------------------*/
10138 /* genArrayInit - generates code for address of */
10139 /*-----------------------------------------------------------------*/
10141 genArrayInit (iCode * ic)
10143 literalList *iLoop;
10145 int elementSize = 0, eIndex;
10146 unsigned val, lastVal;
10148 operand *left=IC_LEFT(ic);
10150 D (emitcode (";", "genArrayInit "););
10152 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10154 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10156 // Load immediate value into DPTR.
10157 emitcode("mov", "dptr, %s",
10158 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
10160 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10163 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10164 "Unexpected operand to genArrayInit.\n");
10167 // a regression because of SDCCcse.c:1.52
10168 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
10169 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
10170 if (options.model == MODEL_FLAT24)
10171 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
10175 type = operandType(IC_LEFT(ic));
10177 if (type && type->next)
10179 elementSize = getSize(type->next);
10183 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10184 "can't determine element size in genArrayInit.\n");
10188 iLoop = IC_ARRAYILIST(ic);
10193 bool firstpass = TRUE;
10195 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10196 iLoop->count, (int)iLoop->literalValue, elementSize);
10202 symbol *tlbl = NULL;
10204 count = ix > 256 ? 256 : ix;
10208 tlbl = newiTempLabel (NULL);
10209 if (firstpass || (count & 0xff))
10211 emitcode("mov", "b, #!constbyte", count & 0xff);
10214 emitcode ("", "!tlabeldef", tlbl->key + 100);
10219 for (eIndex = 0; eIndex < elementSize; eIndex++)
10221 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10222 if (val != lastVal)
10224 emitcode("mov", "a, #!constbyte", val);
10228 emitcode("movx", "@dptr, a");
10229 emitcode("inc", "dptr");
10234 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10240 iLoop = iLoop->next;
10243 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10246 /*-----------------------------------------------------------------*/
10247 /* genFarFarAssign - assignment when both are in far space */
10248 /*-----------------------------------------------------------------*/
10250 genFarFarAssign (operand * result, operand * right, iCode * ic)
10252 int size = AOP_SIZE (right);
10254 symbol *rSym = NULL;
10258 /* quick & easy case. */
10259 D(emitcode(";","genFarFarAssign (1 byte case)"););
10260 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
10261 freeAsmop (right, NULL, ic, FALSE);
10262 /* now assign DPTR to result */
10264 aopOp(result, ic, FALSE, FALSE);
10266 aopPut(AOP(result), "a", 0);
10267 freeAsmop(result, NULL, ic, FALSE);
10271 /* See if we've got an underlying symbol to abuse. */
10272 if (IS_SYMOP(result) && OP_SYMBOL(result))
10274 if (IS_TRUE_SYMOP(result))
10276 rSym = OP_SYMBOL(result);
10278 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10280 rSym = OP_SYMBOL(result)->usl.spillLoc;
10284 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10286 /* We can use the '390 auto-toggle feature to good effect here. */
10288 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10289 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10290 emitcode ("mov", "dptr,#%s", rSym->rname);
10291 /* DP2 = result, DP1 = right, DP1 is current. */
10294 emitcode("movx", "a,@dptr");
10295 emitcode("movx", "@dptr,a");
10298 emitcode("inc", "dptr");
10299 emitcode("inc", "dptr");
10302 emitcode("mov", "dps,#0");
10303 freeAsmop (right, NULL, ic, FALSE);
10305 some alternative code for processors without auto-toggle
10306 no time to test now, so later well put in...kpb
10307 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10308 emitcode("mov", "dps,#1"); /* Select DPTR2. */
10309 emitcode ("mov", "dptr,#%s", rSym->rname);
10310 /* DP2 = result, DP1 = right, DP1 is current. */
10314 emitcode("movx", "a,@dptr");
10316 emitcode("inc", "dptr");
10317 emitcode("inc", "dps");
10318 emitcode("movx", "@dptr,a");
10320 emitcode("inc", "dptr");
10321 emitcode("inc", "dps");
10323 emitcode("mov", "dps,#0");
10324 freeAsmop (right, NULL, ic, FALSE);
10329 D (emitcode (";", "genFarFarAssign"););
10330 aopOp (result, ic, TRUE, TRUE);
10332 _startLazyDPSEvaluation ();
10336 aopPut (AOP (result),
10337 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10340 _endLazyDPSEvaluation ();
10341 freeAsmop (result, NULL, ic, FALSE);
10342 freeAsmop (right, NULL, ic, FALSE);
10346 /*-----------------------------------------------------------------*/
10347 /* genAssign - generate code for assignment */
10348 /*-----------------------------------------------------------------*/
10350 genAssign (iCode * ic)
10352 operand *result, *right;
10354 unsigned long lit = 0L;
10356 D (emitcode (";", "genAssign ");
10359 result = IC_RESULT (ic);
10360 right = IC_RIGHT (ic);
10362 /* if they are the same */
10363 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10366 aopOp (right, ic, FALSE, FALSE);
10368 emitcode (";", "genAssign: resultIsFar = %s",
10369 isOperandInFarSpace (result) ?
10372 /* special case both in far space */
10373 if ((AOP_TYPE (right) == AOP_DPTR ||
10374 AOP_TYPE (right) == AOP_DPTR2) &&
10375 /* IS_TRUE_SYMOP(result) && */
10376 isOperandInFarSpace (result))
10378 genFarFarAssign (result, right, ic);
10382 aopOp (result, ic, TRUE, FALSE);
10384 /* if they are the same registers */
10385 if (sameRegs (AOP (right), AOP (result)))
10388 /* if the result is a bit */
10389 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10391 /* if the right size is a literal then
10392 we know what the value is */
10393 if (AOP_TYPE (right) == AOP_LIT)
10395 if (((int) operandLitValue (right)))
10396 aopPut (AOP (result), one, 0);
10398 aopPut (AOP (result), zero, 0);
10402 /* the right is also a bit variable */
10403 if (AOP_TYPE (right) == AOP_CRY)
10405 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10406 aopPut (AOP (result), "c", 0);
10410 /* we need to or */
10412 aopPut (AOP (result), "a", 0);
10416 /* bit variables done */
10418 size = AOP_SIZE (result);
10420 if (AOP_TYPE (right) == AOP_LIT)
10421 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10424 (AOP_TYPE (result) != AOP_REG) &&
10425 (AOP_TYPE (right) == AOP_LIT) &&
10426 !IS_FLOAT (operandType (right)))
10428 _startLazyDPSEvaluation ();
10429 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10431 aopPut (AOP (result),
10432 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10437 /* And now fill the rest with zeros. */
10440 emitcode ("clr", "a");
10444 aopPut (AOP (result), "a", offset++);
10446 _endLazyDPSEvaluation ();
10450 _startLazyDPSEvaluation ();
10453 aopPut (AOP (result),
10454 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10458 _endLazyDPSEvaluation ();
10462 freeAsmop (right, NULL, ic, FALSE);
10463 freeAsmop (result, NULL, ic, TRUE);
10466 /*-----------------------------------------------------------------*/
10467 /* genJumpTab - generates code for jump table */
10468 /*-----------------------------------------------------------------*/
10470 genJumpTab (iCode * ic)
10475 D (emitcode (";", "genJumpTab ");
10478 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10479 /* get the condition into accumulator */
10480 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10482 /* multiply by four! */
10483 emitcode ("add", "a,acc");
10484 emitcode ("add", "a,acc");
10485 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10487 jtab = newiTempLabel (NULL);
10488 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10489 emitcode ("jmp", "@a+dptr");
10490 emitcode ("", "!tlabeldef", jtab->key + 100);
10491 /* now generate the jump labels */
10492 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10493 jtab = setNextItem (IC_JTLABELS (ic)))
10494 emitcode ("ljmp", "!tlabel", jtab->key + 100);
10498 /*-----------------------------------------------------------------*/
10499 /* genCast - gen code for casting */
10500 /*-----------------------------------------------------------------*/
10502 genCast (iCode * ic)
10504 operand *result = IC_RESULT (ic);
10505 sym_link *ctype = operandType (IC_LEFT (ic));
10506 sym_link *rtype = operandType (IC_RIGHT (ic));
10507 operand *right = IC_RIGHT (ic);
10510 D (emitcode (";", "genCast ");
10513 /* if they are equivalent then do nothing */
10514 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10517 aopOp (right, ic, FALSE, FALSE);
10518 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10520 /* if the result is a bit */
10521 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10522 if (IS_BITVAR(OP_SYMBOL(result)->type))
10524 /* if the right size is a literal then
10525 we know what the value is */
10526 if (AOP_TYPE (right) == AOP_LIT)
10528 if (((int) operandLitValue (right)))
10529 aopPut (AOP (result), one, 0);
10531 aopPut (AOP (result), zero, 0);
10536 /* the right is also a bit variable */
10537 if (AOP_TYPE (right) == AOP_CRY)
10539 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10540 aopPut (AOP (result), "c", 0);
10544 /* we need to or */
10546 aopPut (AOP (result), "a", 0);
10550 /* if they are the same size : or less */
10551 if (AOP_SIZE (result) <= AOP_SIZE (right))
10554 /* if they are in the same place */
10555 if (sameRegs (AOP (right), AOP (result)))
10558 /* if they in different places then copy */
10559 size = AOP_SIZE (result);
10561 _startLazyDPSEvaluation ();
10564 aopPut (AOP (result),
10565 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10569 _endLazyDPSEvaluation ();
10574 /* if the result is of type pointer */
10575 if (IS_PTR (ctype))
10579 sym_link *type = operandType (right);
10581 /* pointer to generic pointer */
10582 if (IS_GENPTR (ctype))
10588 p_type = DCL_TYPE (type);
10592 #if OLD_CAST_BEHAVIOR
10593 /* KV: we are converting a non-pointer type to
10594 * a generic pointer. This (ifdef'd out) code
10595 * says that the resulting generic pointer
10596 * should have the same class as the storage
10597 * location of the non-pointer variable.
10599 * For example, converting an int (which happens
10600 * to be stored in DATA space) to a pointer results
10601 * in a DATA generic pointer; if the original int
10602 * in XDATA space, so will be the resulting pointer.
10604 * I don't like that behavior, and thus this change:
10605 * all such conversions will be forced to XDATA and
10606 * throw a warning. If you want some non-XDATA
10607 * type, or you want to suppress the warning, you
10608 * must go through an intermediate cast, like so:
10610 * char _generic *gp = (char _xdata *)(intVar);
10612 sym_link *etype = getSpec (type);
10614 /* we have to go by the storage class */
10615 if (SPEC_OCLS (etype) != generic)
10617 p_type = PTR_TYPE (SPEC_OCLS (etype));
10622 /* Converting unknown class (i.e. register variable)
10623 * to generic pointer. This is not good, but
10624 * we'll make a guess (and throw a warning).
10627 werror (W_INT_TO_GEN_PTR_CAST);
10631 /* the first two bytes are known */
10632 size = GPTRSIZE - 1;
10634 _startLazyDPSEvaluation ();
10637 aopPut (AOP (result),
10638 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10642 _endLazyDPSEvaluation ();
10644 /* the last byte depending on type */
10662 /* this should never happen */
10663 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10664 "got unknown pointer type");
10667 aopPut (AOP (result), l, GPTRSIZE - 1);
10671 /* just copy the pointers */
10672 size = AOP_SIZE (result);
10674 _startLazyDPSEvaluation ();
10677 aopPut (AOP (result),
10678 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10682 _endLazyDPSEvaluation ();
10686 /* so we now know that the size of destination is greater
10687 than the size of the source */
10688 /* we move to result for the size of source */
10689 size = AOP_SIZE (right);
10691 _startLazyDPSEvaluation ();
10694 aopPut (AOP (result),
10695 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10699 _endLazyDPSEvaluation ();
10701 /* now depending on the sign of the source && destination */
10702 size = AOP_SIZE (result) - AOP_SIZE (right);
10703 /* if unsigned or not an integral type */
10704 /* also, if the source is a bit, we don't need to sign extend, because
10705 * it can't possibly have set the sign bit.
10707 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10711 aopPut (AOP (result), zero, offset++);
10716 /* we need to extend the sign :{ */
10717 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10718 FALSE, FALSE, TRUE);
10720 emitcode ("rlc", "a");
10721 emitcode ("subb", "a,acc");
10723 aopPut (AOP (result), "a", offset++);
10726 /* we are done hurray !!!! */
10729 freeAsmop (right, NULL, ic, TRUE);
10730 freeAsmop (result, NULL, ic, TRUE);
10734 /*-----------------------------------------------------------------*/
10735 /* genDjnz - generate decrement & jump if not zero instrucion */
10736 /*-----------------------------------------------------------------*/
10738 genDjnz (iCode * ic, iCode * ifx)
10740 symbol *lbl, *lbl1;
10744 /* if the if condition has a false label
10745 then we cannot save */
10746 if (IC_FALSE (ifx))
10749 /* if the minus is not of the form
10751 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10752 !IS_OP_LITERAL (IC_RIGHT (ic)))
10755 if (operandLitValue (IC_RIGHT (ic)) != 1)
10758 /* if the size of this greater than one then no
10760 if (getSize (operandType (IC_RESULT (ic))) > 1)
10763 /* otherwise we can save BIG */
10764 D(emitcode(";", "genDjnz"););
10766 lbl = newiTempLabel (NULL);
10767 lbl1 = newiTempLabel (NULL);
10769 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10771 if (AOP_NEEDSACC(IC_RESULT(ic)))
10773 /* If the result is accessed indirectly via
10774 * the accumulator, we must explicitly write
10775 * it back after the decrement.
10777 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10779 if (strcmp(rByte, "a"))
10781 /* Something is hopelessly wrong */
10782 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10783 __FILE__, __LINE__);
10784 /* We can just give up; the generated code will be inefficient,
10785 * but what the hey.
10787 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10790 emitcode ("dec", "%s", rByte);
10791 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10792 emitcode ("jnz", "!tlabel", lbl->key + 100);
10794 else if (IS_AOP_PREG (IC_RESULT (ic)))
10796 emitcode ("dec", "%s",
10797 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10798 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10799 emitcode ("jnz", "!tlabel", lbl->key + 100);
10803 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10806 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
10807 emitcode ("", "!tlabeldef", lbl->key + 100);
10808 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
10809 emitcode ("", "!tlabeldef", lbl1->key + 100);
10811 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10812 ifx->generated = 1;
10816 /*-----------------------------------------------------------------*/
10817 /* genReceive - generate code for a receive iCode */
10818 /*-----------------------------------------------------------------*/
10820 genReceive (iCode * ic)
10823 D (emitcode (";", "genReceive ");
10826 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10827 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10828 IS_TRUE_SYMOP (IC_RESULT (ic))))
10830 int size = getSize (operandType (IC_RESULT (ic)));
10831 int offset = fReturnSizeDS390 - size;
10834 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10835 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10838 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10839 size = AOP_SIZE (IC_RESULT (ic));
10843 emitcode ("pop", "acc");
10844 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10851 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10853 assignResultValue (IC_RESULT (ic));
10856 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10859 /*-----------------------------------------------------------------*/
10860 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
10861 /*-----------------------------------------------------------------*/
10862 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
10864 operand *from , *to , *count;
10869 /* we know it has to be 3 parameters */
10870 assert (nparms == 3);
10872 rsave = newBitVect(16);
10873 /* save DPTR if it needs to be saved */
10874 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
10875 if (bitVectBitValue(ic->rMask,i))
10876 rsave = bitVectSetBit(rsave,i);
10878 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
10879 ds390_rUmaskForOp (IC_RESULT(ic))));
10886 aopOp (from, ic->next, FALSE, FALSE);
10888 /* get from into DPTR1 */
10889 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
10890 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
10891 if (options.model == MODEL_FLAT24) {
10892 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
10895 freeAsmop (from, NULL, ic, FALSE);
10896 aopOp (to, ic, FALSE, FALSE);
10897 /* get "to" into DPTR */
10898 /* if the operand is already in dptr
10899 then we do nothing else we move the value to dptr */
10900 if (AOP_TYPE (to) != AOP_STR) {
10901 /* if already in DPTR then we need to push */
10902 if (AOP_TYPE(to) == AOP_DPTR) {
10903 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
10904 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
10905 if (options.model == MODEL_FLAT24)
10906 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10907 emitcode ("pop", "dph");
10908 emitcode ("pop", "dpl");
10910 _startLazyDPSEvaluation ();
10911 /* if this is remateriazable */
10912 if (AOP_TYPE (to) == AOP_IMMD) {
10913 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
10914 } else { /* we need to get it byte by byte */
10915 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
10916 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
10917 if (options.model == MODEL_FLAT24) {
10918 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10921 _endLazyDPSEvaluation ();
10924 freeAsmop (to, NULL, ic, FALSE);
10926 aopOp (count, ic->next->next, FALSE,FALSE);
10927 lbl =newiTempLabel(NULL);
10929 /* now for the actual copy */
10930 if (AOP_TYPE(count) == AOP_LIT &&
10931 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
10932 emitcode (";","OH JOY auto increment with djnz (very fast)");
10933 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10934 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
10935 emitcode ("","!tlabeldef",lbl->key+100);
10937 emitcode ("clr","a");
10938 emitcode ("movc", "a,@a+dptr");
10940 emitcode ("movx", "a,@dptr");
10941 emitcode ("movx", "@dptr,a");
10942 emitcode ("inc", "dptr");
10943 emitcode ("inc", "dptr");
10944 emitcode ("djnz","b,!tlabel",lbl->key+100);
10946 symbol *lbl1 = newiTempLabel(NULL);
10948 emitcode (";"," Auto increment but no djnz");
10949 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
10950 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
10951 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10952 emitcode ("","!tlabeldef",lbl->key+100);
10954 emitcode ("clr","a");
10955 emitcode ("movc", "a,@a+dptr");
10957 emitcode ("movx", "a,@dptr");
10958 emitcode ("movx", "@dptr,a");
10959 emitcode ("inc", "dptr");
10960 emitcode ("inc", "dptr");
10961 emitcode ("mov","a,b");
10962 emitcode ("orl","a,_ap");
10963 emitcode ("jz","!tlabel",lbl1->key+100);
10964 emitcode ("mov","a,_ap");
10965 emitcode ("add","a,#!constbyte",0xFF);
10966 emitcode ("mov","_ap,a");
10967 emitcode ("mov","a,b");
10968 emitcode ("addc","a,#!constbyte",0xFF);
10969 emitcode ("mov","b,a");
10970 emitcode ("sjmp","!tlabel",lbl->key+100);
10971 emitcode ("","!tlabeldef",lbl1->key+100);
10973 emitcode ("mov", "dps,#0");
10974 freeAsmop (count, NULL, ic, FALSE);
10975 unsavermask(rsave);
10979 /*-----------------------------------------------------------------*/
10980 /* genMemsetX - gencode for memSetX data */
10981 /*-----------------------------------------------------------------*/
10982 static void genMemsetX(iCode *ic, int nparms, operand **parms)
10984 operand *to , *val , *count;
10988 bitVect *rsave = NULL;
10990 /* we know it has to be 3 parameters */
10991 assert (nparms == 3);
10997 /* save DPTR if it needs to be saved */
10998 rsave = newBitVect(16);
10999 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11000 if (bitVectBitValue(ic->rMask,i))
11001 rsave = bitVectSetBit(rsave,i);
11003 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11004 ds390_rUmaskForOp (IC_RESULT(ic))));
11007 aopOp (to, ic, FALSE, FALSE);
11008 /* get "to" into DPTR */
11009 /* if the operand is already in dptr
11010 then we do nothing else we move the value to dptr */
11011 if (AOP_TYPE (to) != AOP_STR) {
11012 /* if already in DPTR then we need to push */
11013 if (AOP_TYPE(to) == AOP_DPTR) {
11014 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11015 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11016 if (options.model == MODEL_FLAT24)
11017 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11018 emitcode ("pop", "dph");
11019 emitcode ("pop", "dpl");
11021 _startLazyDPSEvaluation ();
11022 /* if this is remateriazable */
11023 if (AOP_TYPE (to) == AOP_IMMD) {
11024 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11025 } else { /* we need to get it byte by byte */
11026 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11027 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11028 if (options.model == MODEL_FLAT24) {
11029 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11032 _endLazyDPSEvaluation ();
11035 freeAsmop (to, NULL, ic, FALSE);
11037 aopOp (val, ic->next->next, FALSE,FALSE);
11038 aopOp (count, ic->next->next, FALSE,FALSE);
11039 lbl =newiTempLabel(NULL);
11040 /* now for the actual copy */
11041 if (AOP_TYPE(count) == AOP_LIT &&
11042 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11043 l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11044 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11046 emitcode ("","!tlabeldef",lbl->key+100);
11047 emitcode ("movx", "@dptr,a");
11048 emitcode ("inc", "dptr");
11049 emitcode ("djnz","b,!tlabel",lbl->key+100);
11051 symbol *lbl1 = newiTempLabel(NULL);
11053 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11054 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11055 emitcode ("","!tlabeldef",lbl->key+100);
11056 l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11058 emitcode ("movx", "a,@dptr");
11059 emitcode ("inc", "dptr");
11060 emitcode ("mov","a,b");
11061 emitcode ("orl","a,_ap");
11062 emitcode ("jz","!tlabel",lbl1->key+100);
11063 emitcode ("mov","a,_ap");
11064 emitcode ("add","a,#!constbyte",0xFF);
11065 emitcode ("mov","_ap,a");
11066 emitcode ("mov","a,b");
11067 emitcode ("addc","a,#!constbyte",0xFF);
11068 emitcode ("mov","b,a");
11069 emitcode ("sjmp","!tlabel",lbl->key+100);
11070 emitcode ("","!tlabeldef",lbl1->key+100);
11072 freeAsmop (count, NULL, ic, FALSE);
11073 unsavermask(rsave);
11076 /*-----------------------------------------------------------------*/
11077 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11078 /*-----------------------------------------------------------------*/
11079 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11082 operand *pnum, *result;
11085 assert (nparms==1);
11086 /* save registers that need to be saved */
11087 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11088 ds390_rUmaskForOp (IC_RESULT(ic))));
11091 aopOp (pnum, ic, FALSE, FALSE);
11092 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11093 freeAsmop (pnum, NULL, ic, FALSE);
11094 emitcode ("lcall","NatLib_LoadPrimitive");
11095 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11096 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
11097 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11098 for (i = (size-1) ; i >= 0 ; i-- ) {
11099 emitcode ("push","a%s",javaRet[i]);
11101 for (i=0; i < size ; i++ ) {
11102 emitcode ("pop","a%s",aopGet(AOP(result),i,FALSE,FALSE,FALSE));
11105 for (i = 0 ; i < size ; i++ ) {
11106 aopPut(AOP(result),javaRet[i],i);
11109 freeAsmop (result, NULL, ic, FALSE);
11110 unsavermask(rsave);
11113 /*-----------------------------------------------------------------*/
11114 /* genNatLibLoadPointer - calls TINI api function to load pointer */
11115 /*-----------------------------------------------------------------*/
11116 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11119 operand *pnum, *result;
11123 assert (nparms==1);
11124 /* save registers that need to be saved */
11125 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11126 ds390_rUmaskForOp (IC_RESULT(ic))));
11129 aopOp (pnum, ic, FALSE, FALSE);
11130 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11131 freeAsmop (pnum, NULL, ic, FALSE);
11132 emitcode ("lcall","NatLib_LoadPointer");
11133 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11134 if (AOP_TYPE(result)!=AOP_STR) {
11135 for (i = 0 ; i < size ; i++ ) {
11136 aopPut(AOP(result),fReturn[i],i);
11139 freeAsmop (result, NULL, ic, FALSE);
11140 unsavermask(rsave);
11143 /*-----------------------------------------------------------------*/
11144 /* genNatLibInstallStateBlock - */
11145 /*-----------------------------------------------------------------*/
11146 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
11147 operand **parms, const char *name)
11150 operand *psb, *handle;
11151 assert (nparms==2);
11153 /* save registers that need to be saved */
11154 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11155 ds390_rUmaskForOp (IC_RESULT(ic))));
11159 /* put pointer to state block into DPTR1 */
11160 aopOp (psb, ic, FALSE, FALSE);
11161 if (AOP_TYPE (psb) == AOP_IMMD) {
11162 emitcode ("mov","dps,#1");
11163 emitcode ("mov", "dptr,%s", aopGet (AOP (psb), 0, TRUE, FALSE, FALSE));
11164 emitcode ("mov","dps,#0");
11166 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,FALSE));
11167 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,FALSE));
11168 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,FALSE));
11170 freeAsmop (psb, NULL, ic, FALSE);
11172 /* put libraryID into DPTR */
11173 emitcode ("mov","dptr,#LibraryID");
11175 /* put handle into r3:r2 */
11176 aopOp (handle, ic, FALSE, FALSE);
11177 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11178 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11179 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11180 emitcode ("pop","ar3");
11181 emitcode ("pop","ar2");
11183 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11184 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11186 freeAsmop (psb, NULL, ic, FALSE);
11188 /* make the call */
11189 emitcode ("lcall","NatLib_Install%sStateBlock",name);
11191 /* put return value into place*/
11193 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
11195 aopPut(AOP(IC_RESULT(ic)),"a",0);
11196 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11197 unsavermask(rsave);
11200 /*-----------------------------------------------------------------*/
11201 /* genNatLibRemoveStateBlock - */
11202 /*-----------------------------------------------------------------*/
11203 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
11209 /* save registers that need to be saved */
11210 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11211 ds390_rUmaskForOp (IC_RESULT(ic))));
11213 /* put libraryID into DPTR */
11214 emitcode ("mov","dptr,#LibraryID");
11215 /* make the call */
11216 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11217 unsavermask(rsave);
11220 /*-----------------------------------------------------------------*/
11221 /* genNatLibGetStateBlock - */
11222 /*-----------------------------------------------------------------*/
11223 static void genNatLibGetStateBlock(iCode *ic,int nparms,
11224 operand **parms,const char *name)
11227 symbol *lbl = newiTempLabel(NULL);
11230 /* save registers that need to be saved */
11231 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11232 ds390_rUmaskForOp (IC_RESULT(ic))));
11234 /* put libraryID into DPTR */
11235 emitcode ("mov","dptr,#LibraryID");
11236 /* make the call */
11237 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11238 emitcode ("jnz","!tlabel",lbl->key+100);
11240 /* put return value into place */
11241 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11242 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11243 emitcode ("push","ar3");
11244 emitcode ("push","ar2");
11245 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11246 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11248 aopPut(AOP(IC_RESULT(ic)),"r2",0);
11249 aopPut(AOP(IC_RESULT(ic)),"r3",1);
11251 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11252 emitcode ("","!tlabeldef",lbl->key+100);
11253 unsavermask(rsave);
11256 /*-----------------------------------------------------------------*/
11257 /* genMMMalloc - */
11258 /*-----------------------------------------------------------------*/
11259 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
11260 int size, const char *name)
11265 symbol *lbl = newiTempLabel(NULL);
11267 assert (nparms == 1);
11268 /* save registers that need to be saved */
11269 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11270 ds390_rUmaskForOp (IC_RESULT(ic))));
11273 aopOp (bsize,ic,FALSE,FALSE);
11275 /* put the size in R4-R2 */
11276 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
11277 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
11278 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
11280 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
11281 emitcode("pop","ar4");
11283 emitcode("pop","ar3");
11284 emitcode("pop","ar2");
11286 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
11287 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
11289 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
11292 freeAsmop (bsize, NULL, ic, FALSE);
11294 /* make the call */
11295 emitcode ("lcall","MM_%s",name);
11296 emitcode ("jz","!tlabel",lbl->key+100);
11297 emitcode ("mov","r2,#!constbyte",0xff);
11298 emitcode ("mov","r3,#!constbyte",0xff);
11299 emitcode ("","!tlabeldef",lbl->key+100);
11300 /* we don't care about the pointer : we just save the handle */
11301 rsym = OP_SYMBOL(IC_RESULT(ic));
11302 if (rsym->liveFrom != rsym->liveTo) {
11303 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11304 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11305 emitcode ("push","ar3");
11306 emitcode ("push","ar2");
11307 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11308 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11310 aopPut(AOP(IC_RESULT(ic)),"r2",0);
11311 aopPut(AOP(IC_RESULT(ic)),"r3",1);
11313 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11315 unsavermask(rsave);
11318 /*-----------------------------------------------------------------*/
11320 /*-----------------------------------------------------------------*/
11321 static void genMMDeref (iCode *ic,int nparms, operand **parms)
11326 assert (nparms == 1);
11327 /* save registers that need to be saved */
11328 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11329 ds390_rUmaskForOp (IC_RESULT(ic))));
11332 aopOp (handle,ic,FALSE,FALSE);
11334 /* put the size in R4-R2 */
11335 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11336 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11337 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11338 emitcode("pop","ar3");
11339 emitcode("pop","ar2");
11341 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11342 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11344 freeAsmop (handle, NULL, ic, FALSE);
11346 /* make the call */
11347 emitcode ("lcall","MM_Deref");
11350 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11351 if (rsym->liveFrom != rsym->liveTo) {
11352 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11353 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
11354 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
11355 aopPut(AOP(IC_RESULT(ic)),"dph",1);
11356 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
11360 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11361 unsavermask(rsave);
11364 /*-----------------------------------------------------------------*/
11365 /* genMMUnrestrictedPersist - */
11366 /*-----------------------------------------------------------------*/
11367 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
11372 assert (nparms == 1);
11373 /* save registers that need to be saved */
11374 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11375 ds390_rUmaskForOp (IC_RESULT(ic))));
11378 aopOp (handle,ic,FALSE,FALSE);
11380 /* put the size in R3-R2 */
11381 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11382 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11383 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11384 emitcode("pop","ar3");
11385 emitcode("pop","ar2");
11387 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11388 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11390 freeAsmop (handle, NULL, ic, FALSE);
11392 /* make the call */
11393 emitcode ("lcall","MM_UnrestrictedPersist");
11396 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11397 if (rsym->liveFrom != rsym->liveTo) {
11398 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11399 aopPut(AOP(IC_RESULT(ic)),"a",0);
11400 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11403 unsavermask(rsave);
11406 /*-----------------------------------------------------------------*/
11407 /* genSystemExecJavaProcess - */
11408 /*-----------------------------------------------------------------*/
11409 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
11412 operand *handle, *pp;
11414 assert (nparms==2);
11415 /* save registers that need to be saved */
11416 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11417 ds390_rUmaskForOp (IC_RESULT(ic))));
11422 /* put the handle in R3-R2 */
11423 aopOp (handle,ic,FALSE,FALSE);
11424 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11425 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11426 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11427 emitcode("pop","ar3");
11428 emitcode("pop","ar2");
11430 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11431 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11433 freeAsmop (handle, NULL, ic, FALSE);
11435 /* put pointer in DPTR */
11436 aopOp (pp,ic,FALSE,FALSE);
11437 if (AOP_TYPE(pp) == AOP_IMMD) {
11438 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));
11439 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
11440 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
11441 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
11442 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
11444 freeAsmop (handle, NULL, ic, FALSE);
11446 /* make the call */
11447 emitcode ("lcall","System_ExecJavaProcess");
11449 /* put result in place */
11451 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11452 if (rsym->liveFrom != rsym->liveTo) {
11453 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11454 aopPut(AOP(IC_RESULT(ic)),"a",0);
11455 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11459 unsavermask(rsave);
11462 /*-----------------------------------------------------------------*/
11463 /* genSystemRTCRegisters - */
11464 /*-----------------------------------------------------------------*/
11465 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
11471 assert (nparms==1);
11472 /* save registers that need to be saved */
11473 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11474 ds390_rUmaskForOp (IC_RESULT(ic))));
11477 /* put pointer in DPTR */
11478 aopOp (pp,ic,FALSE,FALSE);
11479 if (AOP_TYPE (pp) == AOP_IMMD) {
11480 emitcode ("mov","dps,#1");
11481 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));
11482 emitcode ("mov","dps,#0");
11484 emitcode ("mov","dpl1,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
11485 emitcode ("mov","dph1,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
11486 emitcode ("mov","dpx1,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
11488 freeAsmop (pp, NULL, ic, FALSE);
11490 /* make the call */
11491 emitcode ("lcall","System_%sRTCRegisters",name);
11493 unsavermask(rsave);
11496 /*-----------------------------------------------------------------*/
11497 /* genSystemThreadSleep - */
11498 /*-----------------------------------------------------------------*/
11499 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
11504 assert (nparms==1);
11505 /* save registers that need to be saved */
11506 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11507 ds390_rUmaskForOp (IC_RESULT(ic))));
11510 aopOp(to,ic,FALSE,FALSE);
11511 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
11512 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
11513 emitcode ("push","%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
11514 emitcode ("push","%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
11515 emitcode ("push","%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
11516 emitcode ("push","%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
11517 emitcode ("pop","ar3");
11518 emitcode ("pop","ar2");
11519 emitcode ("pop","ar1");
11520 emitcode ("pop","ar0");
11522 emitcode ("mov","r0,%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
11523 emitcode ("mov","r1,%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
11524 emitcode ("mov","r2,%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
11525 emitcode ("mov","r3,%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
11527 freeAsmop (to, NULL, ic, FALSE);
11529 /* suspend in acc */
11531 aopOp(s,ic,FALSE,FALSE);
11532 emitcode ("mov","a,%s",aopGet(AOP(s),0,FALSE,TRUE,FALSE));
11533 freeAsmop (s, NULL, ic, FALSE);
11535 /* make the call */
11536 emitcode ("lcall","System_%s",name);
11538 unsavermask(rsave);
11541 /*-----------------------------------------------------------------*/
11542 /* genSystemThreadResume - */
11543 /*-----------------------------------------------------------------*/
11544 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
11549 assert (nparms==2);
11550 /* save registers that need to be saved */
11551 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11552 ds390_rUmaskForOp (IC_RESULT(ic))));
11558 aopOp(pid,ic,FALSE,FALSE);
11559 emitcode ("mov","r0,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
11560 freeAsmop (pid, NULL, ic, FALSE);
11563 aopOp(tid,ic,FALSE,FALSE);
11564 emitcode ("mov","a,%s",aopGet(AOP(tid),0,FALSE,TRUE,FALSE));
11565 freeAsmop (tid, NULL, ic, FALSE);
11567 emitcode ("lcall","System_ThreadResume");
11569 /* put result into place */
11571 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11572 if (rsym->liveFrom != rsym->liveTo) {
11573 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11574 aopPut(AOP(IC_RESULT(ic)),"a",0);
11575 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11578 unsavermask(rsave);
11581 /*-----------------------------------------------------------------*/
11582 /* genSystemProcessResume - */
11583 /*-----------------------------------------------------------------*/
11584 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
11589 assert (nparms==1);
11590 /* save registers that need to be saved */
11591 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11592 ds390_rUmaskForOp (IC_RESULT(ic))));
11597 aopOp(pid,ic,FALSE,FALSE);
11598 emitcode ("mov","a,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
11599 freeAsmop (pid, NULL, ic, FALSE);
11601 emitcode ("lcall","System_ProcessResume");
11603 unsavermask(rsave);
11606 /*-----------------------------------------------------------------*/
11608 /*-----------------------------------------------------------------*/
11609 static void genSystem (iCode *ic,int nparms,char *name)
11611 assert(nparms == 0);
11613 emitcode ("lcall","System_%s",name);
11616 /*-----------------------------------------------------------------*/
11617 /* genSystemPoll - */
11618 /*-----------------------------------------------------------------*/
11619 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
11624 assert (nparms==1);
11625 /* save registers that need to be saved */
11626 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11627 ds390_rUmaskForOp (IC_RESULT(ic))));
11630 aopOp (fp,ic,FALSE,FALSE);
11631 if (AOP_TYPE (fp) == AOP_IMMD) {
11632 emitcode ("mov", "dptr,%s", aopGet (AOP (fp), 0, TRUE, FALSE, FALSE));
11633 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
11634 emitcode ("mov","dpl,%s",aopGet(AOP(fp),0,FALSE,FALSE,FALSE));
11635 emitcode ("mov","dph,%s",aopGet(AOP(fp),1,FALSE,FALSE,FALSE));
11636 emitcode ("mov","dpx,%s",aopGet(AOP(fp),2,FALSE,FALSE,FALSE));
11638 freeAsmop (fp, NULL, ic, FALSE);
11640 emitcode ("lcall","System_%sPoll",name);
11642 /* put result into place */
11644 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11645 if (rsym->liveFrom != rsym->liveTo) {
11646 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11647 aopPut(AOP(IC_RESULT(ic)),"a",0);
11648 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11651 unsavermask(rsave);
11654 /*-----------------------------------------------------------------*/
11655 /* genSystemGetCurrentID - */
11656 /*-----------------------------------------------------------------*/
11657 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
11659 assert (nparms==0);
11661 emitcode ("lcall","System_GetCurrent%sId",name);
11662 /* put result into place */
11664 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11665 if (rsym->liveFrom != rsym->liveTo) {
11666 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11667 aopPut(AOP(IC_RESULT(ic)),"a",0);
11668 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11673 /*-----------------------------------------------------------------*/
11674 /* genBuiltIn - calls the appropriate function to generating code */
11675 /* for a built in function */
11676 /*-----------------------------------------------------------------*/
11677 static void genBuiltIn (iCode *ic)
11679 operand *bi_parms[MAX_BUILTIN_ARGS];
11684 /* get all the arguments for a built in function */
11685 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
11687 /* which function is it */
11688 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
11689 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
11690 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
11691 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
11692 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
11693 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
11694 genMemsetX(bi_iCode,nbi_parms,bi_parms);
11695 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
11696 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
11697 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
11698 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
11699 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
11700 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
11701 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
11702 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
11703 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
11704 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
11705 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
11706 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
11707 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
11708 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
11709 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
11710 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
11711 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
11712 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
11713 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
11714 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
11715 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
11716 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
11717 } else if (strcmp(bif->name,"MM_Malloc")==0) {
11718 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
11719 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
11720 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
11721 } else if (strcmp(bif->name,"MM_Free")==0) {
11722 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
11723 } else if (strcmp(bif->name,"MM_Deref")==0) {
11724 genMMDeref(bi_iCode,nbi_parms,bi_parms);
11725 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
11726 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
11727 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
11728 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
11729 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
11730 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
11731 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
11732 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
11733 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
11734 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
11735 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
11736 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
11737 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
11738 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
11739 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
11740 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
11741 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
11742 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
11743 } else if (strcmp(bif->name,"System_SaveThread")==0) {
11744 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
11745 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
11746 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
11747 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
11748 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
11749 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
11750 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
11751 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
11752 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
11753 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
11754 genSystem(bi_iCode,nbi_parms,"ProcessYield");
11755 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
11756 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
11757 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
11758 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
11759 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
11760 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
11761 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
11762 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
11763 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
11764 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
11766 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
11772 /*-----------------------------------------------------------------*/
11773 /* gen390Code - generate code for Dallas 390 based controllers */
11774 /*-----------------------------------------------------------------*/
11776 gen390Code (iCode * lic)
11781 lineHead = lineCurr = NULL;
11783 if (options.model == MODEL_FLAT24) {
11784 fReturnSizeDS390 = 5;
11785 fReturn = fReturn24;
11787 fReturnSizeDS390 = 4;
11788 fReturn = fReturn16;
11789 options.stack10bit=0;
11792 /* print the allocation information */
11794 printAllocInfo (currFunc, codeOutFile);
11796 /* if debug information required */
11797 if (options.debug && currFunc)
11799 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
11801 if (IS_STATIC (currFunc->etype))
11802 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
11804 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
11807 /* stack pointer name */
11808 if (options.useXstack)
11814 for (ic = lic; ic; ic = ic->next)
11817 if (ic->lineno && cln != ic->lineno)
11822 emitcode ("", "C$%s$%d$%d$%d ==.",
11823 FileBaseName (ic->filename), ic->lineno,
11824 ic->level, ic->block);
11827 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
11828 printCLine(ic->filename, ic->lineno));
11831 /* if the result is marked as
11832 spilt and rematerializable or code for
11833 this has already been generated then
11835 if (resultRemat (ic) || ic->generated)
11838 /* depending on the operation */
11858 /* IPOP happens only when trying to restore a
11859 spilt live range, if there is an ifx statement
11860 following this pop then the if statement might
11861 be using some of the registers being popped which
11862 would destory the contents of the register so
11863 we need to check for this condition and handle it */
11865 ic->next->op == IFX &&
11866 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11867 genIfx (ic->next, ic);
11885 genEndFunction (ic);
11905 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11922 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11926 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11933 /* note these two are xlated by algebraic equivalence
11934 during parsing SDCC.y */
11935 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11936 "got '>=' or '<=' shouldn't have come here");
11940 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11952 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11956 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11960 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11984 genRightShift (ic);
11987 case GET_VALUE_AT_ADDRESS:
11988 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
11992 if (POINTER_SET (ic))
11993 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
12019 if (ic->builtinSEND) genBuiltIn(ic);
12020 else addSet (&_G.sendSet, ic);
12033 /* now we are ready to call the
12034 peep hole optimizer */
12035 if (!options.nopeep)
12036 peepHole (&lineHead);
12038 /* now do the actual printing */
12039 printLine (lineHead, codeOutFile);