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 (ic->op == LABEL && IC_LABEL (ic)->key == key)
3321 /* printf("findLabelBackwards = %d\n", count); */
3329 /*-----------------------------------------------------------------*/
3330 /* genPlusIncr :- does addition with increment if possible */
3331 /*-----------------------------------------------------------------*/
3333 genPlusIncr (iCode * ic)
3335 unsigned int icount;
3336 unsigned int size = getDataSize (IC_RESULT (ic));
3338 /* will try to generate an increment */
3339 /* if the right side is not a literal
3341 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3344 /* if the literal value of the right hand side
3345 is greater than 4 then it is not worth it */
3346 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3349 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3350 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3352 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3356 /* if increment 16 bits in register */
3358 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3359 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3360 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3368 /* If the next instruction is a goto and the goto target
3369 * is <= 5 instructions previous to this, we can generate
3370 * jumps straight to that target.
3372 if (ic->next && ic->next->op == GOTO
3373 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3376 emitcode (";", "tail increment optimized (range %d)", labelRange);
3377 tlbl = IC_LABEL (ic->next);
3382 tlbl = newiTempLabel (NULL);
3385 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3386 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3387 IS_AOP_PREG (IC_RESULT (ic)))
3388 emitcode ("cjne", "%s,#0,!tlabel"
3389 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3393 emitcode ("clr", "a");
3394 emitcode ("cjne", "a,%s,!tlabel"
3395 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3399 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3402 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3403 IS_AOP_PREG (IC_RESULT (ic)))
3404 emitcode ("cjne", "%s,#0,!tlabel"
3405 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3408 emitcode ("cjne", "a,%s,!tlabel"
3409 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3412 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3416 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3417 IS_AOP_PREG (IC_RESULT (ic)))
3418 emitcode ("cjne", "%s,#0,!tlabel"
3419 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3423 emitcode ("cjne", "a,%s,!tlabel"
3424 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3427 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3432 emitcode ("", "!tlabeldef", tlbl->key + 100);
3437 /* if the sizes are greater than 1 then we cannot */
3438 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3439 AOP_SIZE (IC_LEFT (ic)) > 1)
3442 /* we can if the aops of the left & result match or
3443 if they are in registers and the registers are the
3446 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3447 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3448 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3453 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3454 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3455 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3460 _startLazyDPSEvaluation ();
3463 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3465 _endLazyDPSEvaluation ();
3474 /*-----------------------------------------------------------------*/
3475 /* outBitAcc - output a bit in acc */
3476 /*-----------------------------------------------------------------*/
3478 outBitAcc (operand * result)
3480 symbol *tlbl = newiTempLabel (NULL);
3481 /* if the result is a bit */
3482 if (AOP_TYPE (result) == AOP_CRY)
3484 aopPut (AOP (result), "a", 0);
3488 emitcode ("jz", "!tlabel", tlbl->key + 100);
3489 emitcode ("mov", "a,%s", one);
3490 emitcode ("", "!tlabeldef", tlbl->key + 100);
3495 /*-----------------------------------------------------------------*/
3496 /* genPlusBits - generates code for addition of two bits */
3497 /*-----------------------------------------------------------------*/
3499 genPlusBits (iCode * ic)
3501 D (emitcode (";", "genPlusBits ");
3503 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3505 symbol *lbl = newiTempLabel (NULL);
3506 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3507 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3508 emitcode ("cpl", "c");
3509 emitcode ("", "!tlabeldef", (lbl->key + 100));
3510 outBitC (IC_RESULT (ic));
3514 emitcode ("clr", "a");
3515 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3516 emitcode ("rlc", "a");
3517 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3518 emitcode ("addc", "a,#0");
3519 outAcc (IC_RESULT (ic));
3524 adjustArithmeticResult (iCode * ic)
3526 if (opIsGptr (IC_RESULT (ic)) &&
3527 opIsGptr (IC_LEFT (ic)) &&
3528 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3530 aopPut (AOP (IC_RESULT (ic)),
3531 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3535 if (opIsGptr (IC_RESULT (ic)) &&
3536 opIsGptr (IC_RIGHT (ic)) &&
3537 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3539 aopPut (AOP (IC_RESULT (ic)),
3540 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3544 if (opIsGptr (IC_RESULT (ic)) &&
3545 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3546 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3547 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3548 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3551 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3552 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3556 #if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
3557 // Please don't bring it back without a really good reason.
3558 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3559 // (because all three operands are in far space).
3560 #define AOP_OP_3(ic) \
3561 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3562 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3563 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3564 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3565 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3566 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3568 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3570 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3574 // Macro to aopOp all three operands of an ic. If this cannot be done,
3575 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3576 // will be set TRUE. The caller must then handle the case specially, noting
3577 // that the IC_RESULT operand is not aopOp'd.
3578 #define AOP_OP_3_NOFATAL(ic, rc) \
3579 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3580 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR) || \
3581 ((OP_SYMBOL(IC_RESULT(ic))->ruonly) && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))); \
3582 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3583 (isOperandInFarSpace(IC_RESULT(ic)) || (OP_SYMBOL(IC_RESULT(ic))->ruonly && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic))))) \
3585 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3590 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3591 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3593 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3594 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3596 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3598 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3602 // aopOp the left & right operands of an ic.
3603 #define AOP_OP_2(ic) \
3604 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3605 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3607 // convienience macro.
3608 #define AOP_SET_LOCALS(ic) \
3609 left = IC_LEFT(ic); \
3610 right = IC_RIGHT(ic); \
3611 result = IC_RESULT(ic);
3614 // Given an integer value of pushedSize bytes on the stack,
3615 // adjust it to be resultSize bytes, either by discarding
3616 // the most significant bytes or by zero-padding.
3618 // On exit from this macro, pushedSize will have been adjusted to
3619 // equal resultSize, and ACC may be trashed.
3620 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3621 /* If the pushed data is bigger than the result, \
3622 * simply discard unused bytes. Icky, but works. \
3624 while (pushedSize > resultSize) \
3626 D (emitcode (";", "discarding unused result byte."););\
3627 emitcode ("pop", "acc"); \
3630 if (pushedSize < resultSize) \
3632 emitcode ("clr", "a"); \
3633 /* Conversly, we haven't pushed enough here. \
3634 * just zero-pad, and all is well. \
3636 while (pushedSize < resultSize) \
3638 emitcode("push", "acc"); \
3642 assert(pushedSize == resultSize);
3644 /*-----------------------------------------------------------------*/
3645 /* genPlus - generates code for addition */
3646 /*-----------------------------------------------------------------*/
3648 genPlus (iCode * ic)
3650 int size, offset = 0;
3651 bool pushResult = FALSE;
3654 D (emitcode (";", "genPlus "););
3656 /* special cases :- */
3657 if ( IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly &&
3658 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3659 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3660 size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3662 while (size--) emitcode ("inc","dptr");
3664 emitcode ("mov","a,dpl");
3665 emitcode ("add","a,#!constbyte",size & 0xff);
3666 emitcode ("mov","dpl,a");
3667 emitcode ("mov","a,dph");
3668 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3669 emitcode ("mov","dph,a");
3670 emitcode ("mov","a,dpx");
3671 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3672 emitcode ("mov","dpx,a");
3674 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3677 if ( IS_SYMOP(IC_LEFT(ic)) &&
3678 OP_SYMBOL(IC_LEFT(ic))->remat &&
3679 isOperandInFarSpace(IC_RIGHT(ic))) {
3680 operand *op = IC_RIGHT(ic);
3681 IC_RIGHT(ic) = IC_LEFT(ic);
3685 AOP_OP_3_NOFATAL (ic, pushResult);
3688 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3693 /* if literal, literal on the right or
3694 if left requires ACC or right is already
3696 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3697 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3698 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3700 operand *t = IC_RIGHT (ic);
3701 IC_RIGHT (ic) = IC_LEFT (ic);
3703 emitcode (";", "Swapped plus args.");
3706 /* if both left & right are in bit
3708 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3709 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3715 /* if left in bit space & right literal */
3716 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3717 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3719 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3720 /* if result in bit space */
3721 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3723 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3724 emitcode ("cpl", "c");
3725 outBitC (IC_RESULT (ic));
3729 size = getDataSize (IC_RESULT (ic));
3730 _startLazyDPSEvaluation ();
3733 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3734 emitcode ("addc", "a,#0");
3735 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3737 _endLazyDPSEvaluation ();
3742 /* if I can do an increment instead
3743 of add then GOOD for ME */
3744 if (genPlusIncr (ic) == TRUE)
3746 emitcode (";", "did genPlusIncr");
3751 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3753 _startLazyDPSEvaluation ();
3756 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3758 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3760 emitcode ("add", "a,%s",
3761 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3763 emitcode ("addc", "a,%s",
3764 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3768 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3770 /* right is going to use ACC or we would have taken the
3773 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3775 D(emitcode(";", "+ AOP_ACC special case."););
3776 emitcode("xch", "a, %s", DP2_RESULT_REG);
3778 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3781 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3784 emitcode("add", "a, %s", DP2_RESULT_REG);
3788 emitcode ("add", "a,%s",
3789 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3794 emitcode ("addc", "a,%s",
3795 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3800 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3804 emitcode ("push", "acc");
3808 _endLazyDPSEvaluation ();
3812 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3814 size = getDataSize (IC_LEFT (ic));
3815 rSize = getDataSize (IC_RESULT (ic));
3817 ADJUST_PUSHED_RESULT(size, rSize);
3819 _startLazyDPSEvaluation ();
3822 emitcode ("pop", "acc");
3823 aopPut (AOP (IC_RESULT (ic)), "a", size);
3825 _endLazyDPSEvaluation ();
3828 adjustArithmeticResult (ic);
3831 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3832 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3833 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3836 /*-----------------------------------------------------------------*/
3837 /* genMinusDec :- does subtraction with deccrement if possible */
3838 /*-----------------------------------------------------------------*/
3840 genMinusDec (iCode * ic)
3842 unsigned int icount;
3843 unsigned int size = getDataSize (IC_RESULT (ic));
3845 /* will try to generate an increment */
3846 /* if the right side is not a literal
3848 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3851 /* if the literal value of the right hand side
3852 is greater than 4 then it is not worth it */
3853 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3856 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3857 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3859 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3863 /* if decrement 16 bits in register */
3864 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3865 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3866 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3874 /* If the next instruction is a goto and the goto target
3875 * is <= 5 instructions previous to this, we can generate
3876 * jumps straight to that target.
3878 if (ic->next && ic->next->op == GOTO
3879 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3882 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3883 tlbl = IC_LABEL (ic->next);
3888 tlbl = newiTempLabel (NULL);
3892 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3893 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3894 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3895 IS_AOP_PREG (IC_RESULT (ic)))
3896 emitcode ("cjne", "%s,#!constbyte,!tlabel"
3897 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE), 0xff
3901 emitcode ("mov", "a,#!constbyte",0xff);
3902 emitcode ("cjne", "a,%s,!tlabel"
3903 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3906 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3909 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3910 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3911 IS_AOP_PREG (IC_RESULT (ic)))
3912 emitcode ("cjne", "%s,#!constbyte,!tlabel"
3913 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE),0xff
3917 emitcode ("cjne", "a,%s,!tlabel"
3918 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3921 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3925 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3926 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3927 IS_AOP_PREG (IC_RESULT (ic)))
3928 emitcode ("cjne", "%s,#!constbyte,!tlabel"
3929 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE),0xff
3933 emitcode ("cjne", "a,%s,!tlabel"
3934 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3937 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3941 emitcode ("", "!tlabeldef", tlbl->key + 100);
3946 /* if the sizes are greater than 1 then we cannot */
3947 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3948 AOP_SIZE (IC_LEFT (ic)) > 1)
3951 /* we can if the aops of the left & result match or
3952 if they are in registers and the registers are the
3955 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3956 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3957 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3960 _startLazyDPSEvaluation ();
3963 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3965 _endLazyDPSEvaluation ();
3973 /*-----------------------------------------------------------------*/
3974 /* addSign - complete with sign */
3975 /*-----------------------------------------------------------------*/
3977 addSign (operand * result, int offset, int sign)
3979 int size = (getDataSize (result) - offset);
3982 _startLazyDPSEvaluation();
3985 emitcode ("rlc", "a");
3986 emitcode ("subb", "a,acc");
3989 aopPut (AOP (result), "a", offset++);
3996 aopPut (AOP (result), zero, offset++);
3999 _endLazyDPSEvaluation();
4003 /*-----------------------------------------------------------------*/
4004 /* genMinusBits - generates code for subtraction of two bits */
4005 /*-----------------------------------------------------------------*/
4007 genMinusBits (iCode * ic)
4009 symbol *lbl = newiTempLabel (NULL);
4011 D (emitcode (";", "genMinusBits "););
4013 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4015 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4016 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4017 emitcode ("cpl", "c");
4018 emitcode ("", "!tlabeldef", (lbl->key + 100));
4019 outBitC (IC_RESULT (ic));
4023 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4024 emitcode ("subb", "a,acc");
4025 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4026 emitcode ("inc", "a");
4027 emitcode ("", "!tlabeldef", (lbl->key + 100));
4028 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4029 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4033 /*-----------------------------------------------------------------*/
4034 /* genMinus - generates code for subtraction */
4035 /*-----------------------------------------------------------------*/
4037 genMinus (iCode * ic)
4039 int size, offset = 0;
4041 unsigned long lit = 0L;
4042 bool pushResult = FALSE;
4044 D (emitcode (";", "genMinus "););
4046 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
4047 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
4048 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
4049 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
4055 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
4057 /* special cases :- */
4058 /* if both left & right are in bit space */
4059 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4060 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4066 /* if I can do an decrement instead
4067 of subtract then GOOD for ME */
4068 if (genMinusDec (ic) == TRUE)
4073 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4075 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4081 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4086 /* if literal, add a,#-lit, else normal subb */
4087 _startLazyDPSEvaluation ();
4090 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
4091 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4092 emitcode ("subb", "a,%s",
4093 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4096 /* first add without previous c */
4098 if (!size && lit==-1) {
4099 emitcode ("dec", "a");
4101 emitcode ("add", "a,#!constbyte",
4102 (unsigned int) (lit & 0x0FFL));
4105 emitcode ("addc", "a,#!constbyte",
4106 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4112 emitcode ("push", "acc");
4116 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4120 _endLazyDPSEvaluation ();
4124 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4126 size = getDataSize (IC_LEFT (ic));
4127 rSize = getDataSize (IC_RESULT (ic));
4129 ADJUST_PUSHED_RESULT(size, rSize);
4131 _startLazyDPSEvaluation ();
4134 emitcode ("pop", "acc");
4135 aopPut (AOP (IC_RESULT (ic)), "a", size);
4137 _endLazyDPSEvaluation ();
4140 adjustArithmeticResult (ic);
4143 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4144 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4145 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4149 /*-----------------------------------------------------------------*/
4150 /* genMultbits :- multiplication of bits */
4151 /*-----------------------------------------------------------------*/
4153 genMultbits (operand * left,
4158 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4159 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4160 aopOp(result, ic, TRUE, FALSE);
4165 /*-----------------------------------------------------------------*/
4166 /* genMultOneByte : 8*8=8/16 bit multiplication */
4167 /*-----------------------------------------------------------------*/
4169 genMultOneByte (operand * left,
4174 sym_link *opetype = operandType (result);
4178 /* (if two literals: the value is computed before) */
4179 /* if one literal, literal on the right */
4180 if (AOP_TYPE (left) == AOP_LIT)
4185 emitcode (";", "swapped left and right");
4188 if (SPEC_USIGN(opetype)
4189 // ignore the sign of left and right, what else can we do?
4190 || (SPEC_USIGN(operandType(left)) &&
4191 SPEC_USIGN(operandType(right)))) {
4192 // just an unsigned 8*8=8/16 multiply
4193 //emitcode (";","unsigned");
4194 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4195 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4196 emitcode ("mul", "ab");
4198 _G.accInUse++; _G.bInUse++;
4199 aopOp(result, ic, TRUE, FALSE);
4201 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4203 // this should never happen
4204 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4205 AOP_SIZE(result), __FILE__, lineno);
4209 aopPut (AOP (result), "a", 0);
4210 _G.accInUse--; _G.bInUse--;
4211 if (AOP_SIZE(result)==2)
4213 aopPut (AOP (result), "b", 1);
4218 // we have to do a signed multiply
4220 emitcode (";", "signed");
4221 emitcode ("clr", "F0"); // reset sign flag
4222 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4224 lbl=newiTempLabel(NULL);
4225 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4226 // left side is negative, 8-bit two's complement, this fails for -128
4227 emitcode ("setb", "F0"); // set sign flag
4228 emitcode ("cpl", "a");
4229 emitcode ("inc", "a");
4231 emitcode ("", "!tlabeldef", lbl->key+100);
4234 if (AOP_TYPE(right)==AOP_LIT) {
4235 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4236 /* AND literal negative */
4237 if ((int) val < 0) {
4238 emitcode ("cpl", "F0"); // complement sign flag
4239 emitcode ("mov", "b,#!constbyte", -val);
4241 emitcode ("mov", "b,#!constbyte", val);
4244 lbl=newiTempLabel(NULL);
4245 emitcode ("mov", "b,a");
4246 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4247 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4248 // right side is negative, 8-bit two's complement
4249 emitcode ("cpl", "F0"); // complement sign flag
4250 emitcode ("cpl", "a");
4251 emitcode ("inc", "a");
4252 emitcode ("", "!tlabeldef", lbl->key+100);
4254 emitcode ("mul", "ab");
4256 _G.accInUse++;_G.bInUse++;
4257 aopOp(result, ic, TRUE, FALSE);
4259 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4261 // this should never happen
4262 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4263 AOP_SIZE(result), __FILE__, lineno);
4267 lbl=newiTempLabel(NULL);
4268 emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4269 // only ONE op was negative, we have to do a 8/16-bit two's complement
4270 emitcode ("cpl", "a"); // lsb
4271 if (AOP_SIZE(result)==1) {
4272 emitcode ("inc", "a");
4274 emitcode ("add", "a,#1");
4275 emitcode ("xch", "a,b");
4276 emitcode ("cpl", "a"); // msb
4277 emitcode ("addc", "a,#0");
4278 emitcode ("xch", "a,b");
4281 emitcode ("", "!tlabeldef", lbl->key+100);
4282 aopPut (AOP (result), "a", 0);
4283 _G.accInUse--;_G.bInUse--;
4284 if (AOP_SIZE(result)==2) {
4285 aopPut (AOP (result), "b", 1);
4289 /*-----------------------------------------------------------------*/
4290 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4291 /*-----------------------------------------------------------------*/
4292 static void genMultTwoByte (operand *left, operand *right,
4293 operand *result, iCode *ic)
4295 sym_link *retype = getSpec(operandType(right));
4296 sym_link *letype = getSpec(operandType(left));
4297 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4300 if (AOP_TYPE (left) == AOP_LIT) {
4305 /* save EA bit in F1 */
4306 lbl = newiTempLabel(NULL);
4307 emitcode ("setb","F1");
4308 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4309 emitcode ("clr","F1");
4310 emitcode("","!tlabeldef",lbl->key+100);
4312 /* load up MB with right */
4314 emitcode("clr","F0");
4315 if (AOP_TYPE(right) == AOP_LIT) {
4316 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4318 emitcode("setb","F0");
4321 emitcode ("mov","mb,#!constbyte",val & 0xff);
4322 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4324 lbl = newiTempLabel(NULL);
4325 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4326 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4327 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4328 emitcode ("xch", "a,b");
4329 emitcode ("cpl","a");
4330 emitcode ("add", "a,#1");
4331 emitcode ("xch", "a,b");
4332 emitcode ("cpl", "a"); // msb
4333 emitcode ("addc", "a,#0");
4334 emitcode ("setb","F0");
4335 emitcode ("","!tlabeldef",lbl->key+100);
4336 emitcode ("mov","mb,b");
4337 emitcode ("mov","mb,a");
4340 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4341 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4343 /* load up MA with left */
4345 lbl = newiTempLabel(NULL);
4346 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4347 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4348 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4349 emitcode ("xch", "a,b");
4350 emitcode ("cpl","a");
4351 emitcode ("add", "a,#1");
4352 emitcode ("xch", "a,b");
4353 emitcode ("cpl", "a"); // msb
4354 emitcode ("addc","a,#0");
4355 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4356 emitcode ("setb","F0");
4357 emitcode ("","!tlabeldef",lbl->key+100);
4358 emitcode ("mov","ma,b");
4359 emitcode ("mov","ma,a");
4361 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4362 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4364 /* wait for multiplication to finish */
4365 lbl = newiTempLabel(NULL);
4366 emitcode("","!tlabeldef", lbl->key+100);
4367 emitcode("mov","a,mcnt1");
4368 emitcode("anl","a,#!constbyte",0x80);
4369 emitcode("jnz","!tlabel",lbl->key+100);
4371 freeAsmop (left, NULL, ic, TRUE);
4372 freeAsmop (right, NULL, ic,TRUE);
4373 aopOp(result, ic, TRUE, FALSE);
4375 /* if unsigned then simple */
4377 emitcode ("mov","a,ma");
4378 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4379 emitcode ("mov","a,ma");
4380 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4381 aopPut(AOP(result),"ma",1);
4382 aopPut(AOP(result),"ma",0);
4384 emitcode("push","ma");
4385 emitcode("push","ma");
4386 emitcode("push","ma");
4388 /* negate result if needed */
4389 lbl = newiTempLabel(NULL);
4390 emitcode("jnb","F0,!tlabel",lbl->key+100);
4391 emitcode("cpl","a");
4392 emitcode("add","a,#1");
4393 emitcode("","!tlabeldef", lbl->key+100);
4394 if (AOP_TYPE(result) == AOP_ACC)
4396 D(emitcode(";", "ACC special case."););
4397 /* We know result is the only live aop, and
4398 * it's obviously not a DPTR2, so AP is available.
4400 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4404 aopPut(AOP(result),"a",0);
4407 emitcode("pop","acc");
4408 lbl = newiTempLabel(NULL);
4409 emitcode("jnb","F0,!tlabel",lbl->key+100);
4410 emitcode("cpl","a");
4411 emitcode("addc","a,#0");
4412 emitcode("","!tlabeldef", lbl->key+100);
4413 aopPut(AOP(result),"a",1);
4414 emitcode("pop","acc");
4415 if (AOP_SIZE(result) >= 3) {
4416 lbl = newiTempLabel(NULL);
4417 emitcode("jnb","F0,!tlabel",lbl->key+100);
4418 emitcode("cpl","a");
4419 emitcode("addc","a,#0");
4420 emitcode("","!tlabeldef", lbl->key+100);
4421 aopPut(AOP(result),"a",2);
4423 emitcode("pop","acc");
4424 if (AOP_SIZE(result) >= 4) {
4425 lbl = newiTempLabel(NULL);
4426 emitcode("jnb","F0,!tlabel",lbl->key+100);
4427 emitcode("cpl","a");
4428 emitcode("addc","a,#0");
4429 emitcode("","!tlabeldef", lbl->key+100);
4430 aopPut(AOP(result),"a",3);
4432 if (AOP_TYPE(result) == AOP_ACC)
4434 /* We stashed the result away above. */
4435 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4439 freeAsmop (result, NULL, ic, TRUE);
4441 /* restore EA bit in F1 */
4442 lbl = newiTempLabel(NULL);
4443 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4444 emitcode ("setb","EA");
4445 emitcode("","!tlabeldef",lbl->key+100);
4449 /*-----------------------------------------------------------------*/
4450 /* genMult - generates code for multiplication */
4451 /*-----------------------------------------------------------------*/
4453 genMult (iCode * ic)
4455 operand *left = IC_LEFT (ic);
4456 operand *right = IC_RIGHT (ic);
4457 operand *result = IC_RESULT (ic);
4459 D (emitcode (";", "genMult "););
4461 /* assign the amsops */
4464 /* special cases first */
4466 if (AOP_TYPE (left) == AOP_CRY &&
4467 AOP_TYPE (right) == AOP_CRY)
4469 genMultbits (left, right, result, ic);
4473 /* if both are of size == 1 */
4474 if (AOP_SIZE (left) == 1 &&
4475 AOP_SIZE (right) == 1)
4477 genMultOneByte (left, right, result, ic);
4481 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4482 /* use the ds390 ARITHMETIC accel UNIT */
4483 genMultTwoByte (left, right, result, ic);
4486 /* should have been converted to function call */
4490 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4491 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4492 freeAsmop (result, NULL, ic, TRUE);
4495 /*-----------------------------------------------------------------*/
4496 /* genDivbits :- division of bits */
4497 /*-----------------------------------------------------------------*/
4499 genDivbits (operand * left,
4507 /* the result must be bit */
4508 LOAD_AB_FOR_DIV (left, right, l);
4509 emitcode ("div", "ab");
4510 emitcode ("rrc", "a");
4511 aopOp(result, ic, TRUE, FALSE);
4513 aopPut (AOP (result), "c", 0);
4516 /*-----------------------------------------------------------------*/
4517 /* genDivOneByte : 8 bit division */
4518 /*-----------------------------------------------------------------*/
4520 genDivOneByte (operand * left,
4525 sym_link *opetype = operandType (result);
4531 /* signed or unsigned */
4532 if (SPEC_USIGN (opetype))
4534 /* unsigned is easy */
4535 LOAD_AB_FOR_DIV (left, right, l);
4536 emitcode ("div", "ab");
4539 aopOp(result, ic, TRUE, FALSE);
4540 aopPut (AOP (result), "a", 0);
4543 size = AOP_SIZE (result) - 1;
4547 aopPut (AOP (result), zero, offset++);
4552 /* signed is a little bit more difficult */
4554 /* save the signs of the operands */
4555 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4557 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4558 emitcode ("push", "acc"); /* save it on the stack */
4560 /* now sign adjust for both left & right */
4561 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4563 lbl = newiTempLabel (NULL);
4564 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4565 emitcode ("cpl", "a");
4566 emitcode ("inc", "a");
4567 emitcode ("", "!tlabeldef", (lbl->key + 100));
4568 emitcode ("mov", "b,a");
4570 /* sign adjust left side */
4571 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4574 lbl = newiTempLabel (NULL);
4575 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4576 emitcode ("cpl", "a");
4577 emitcode ("inc", "a");
4578 emitcode ("", "!tlabeldef", (lbl->key + 100));
4580 /* now the division */
4581 emitcode ("nop", "; workaround for DS80C390 div bug.");
4582 emitcode ("div", "ab");
4583 /* we are interested in the lower order
4585 emitcode ("mov", "b,a");
4586 lbl = newiTempLabel (NULL);
4587 emitcode ("pop", "acc");
4588 /* if there was an over flow we don't
4589 adjust the sign of the result */
4590 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4591 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4593 emitcode ("clr", "a");
4594 emitcode ("subb", "a,b");
4595 emitcode ("mov", "b,a");
4596 emitcode ("", "!tlabeldef", (lbl->key + 100));
4598 /* now we are done */
4599 _G.accInUse++; _G.bInUse++;
4600 aopOp(result, ic, TRUE, FALSE);
4602 aopPut (AOP (result), "b", 0);
4604 size = AOP_SIZE (result) - 1;
4608 emitcode ("mov", "c,b.7");
4609 emitcode ("subb", "a,acc");
4613 aopPut (AOP (result), "a", offset++);
4615 _G.accInUse--; _G.bInUse--;
4619 /*-----------------------------------------------------------------*/
4620 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4621 /*-----------------------------------------------------------------*/
4622 static void genDivTwoByte (operand *left, operand *right,
4623 operand *result, iCode *ic)
4625 sym_link *retype = getSpec(operandType(right));
4626 sym_link *letype = getSpec(operandType(left));
4627 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4630 /* save EA bit in F1 */
4631 lbl = newiTempLabel(NULL);
4632 emitcode ("setb","F1");
4633 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4634 emitcode ("clr","F1");
4635 emitcode("","!tlabeldef",lbl->key+100);
4637 /* load up MA with left */
4639 emitcode("clr","F0");
4640 lbl = newiTempLabel(NULL);
4641 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4642 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4643 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4644 emitcode ("xch", "a,b");
4645 emitcode ("cpl","a");
4646 emitcode ("add", "a,#1");
4647 emitcode ("xch", "a,b");
4648 emitcode ("cpl", "a"); // msb
4649 emitcode ("addc","a,#0");
4650 emitcode ("setb","F0");
4651 emitcode ("","!tlabeldef",lbl->key+100);
4652 emitcode ("mov","ma,b");
4653 emitcode ("mov","ma,a");
4655 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4656 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4659 /* load up MB with right */
4661 if (AOP_TYPE(right) == AOP_LIT) {
4662 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4664 lbl = newiTempLabel(NULL);
4665 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4666 emitcode("setb","F0");
4667 emitcode ("","!tlabeldef",lbl->key+100);
4670 emitcode ("mov","mb,#!constbyte",val & 0xff);
4671 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4673 lbl = newiTempLabel(NULL);
4674 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4675 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4676 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4677 emitcode ("xch", "a,b");
4678 emitcode ("cpl","a");
4679 emitcode ("add", "a,#1");
4680 emitcode ("xch", "a,b");
4681 emitcode ("cpl", "a"); // msb
4682 emitcode ("addc", "a,#0");
4683 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4684 emitcode ("setb","F0");
4685 emitcode ("","!tlabeldef",lbl->key+100);
4686 emitcode ("mov","mb,b");
4687 emitcode ("mov","mb,a");
4690 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4691 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4694 /* wait for multiplication to finish */
4695 lbl = newiTempLabel(NULL);
4696 emitcode("","!tlabeldef", lbl->key+100);
4697 emitcode("mov","a,mcnt1");
4698 emitcode("anl","a,#!constbyte",0x80);
4699 emitcode("jnz","!tlabel",lbl->key+100);
4701 freeAsmop (left, NULL, ic, TRUE);
4702 freeAsmop (right, NULL, ic,TRUE);
4703 aopOp(result, ic, TRUE, FALSE);
4705 /* if unsigned then simple */
4707 aopPut(AOP(result),"ma",1);
4708 aopPut(AOP(result),"ma",0);
4710 emitcode("push","ma");
4712 /* negate result if needed */
4713 lbl = newiTempLabel(NULL);
4714 emitcode("jnb","F0,!tlabel",lbl->key+100);
4715 emitcode("cpl","a");
4716 emitcode("add","a,#1");
4717 emitcode("","!tlabeldef", lbl->key+100);
4718 aopPut(AOP(result),"a",0);
4719 emitcode("pop","acc");
4720 lbl = newiTempLabel(NULL);
4721 emitcode("jnb","F0,!tlabel",lbl->key+100);
4722 emitcode("cpl","a");
4723 emitcode("addc","a,#0");
4724 emitcode("","!tlabeldef", lbl->key+100);
4725 aopPut(AOP(result),"a",1);
4727 freeAsmop (result, NULL, ic, TRUE);
4728 /* restore EA bit in F1 */
4729 lbl = newiTempLabel(NULL);
4730 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4731 emitcode ("setb","EA");
4732 emitcode("","!tlabeldef",lbl->key+100);
4736 /*-----------------------------------------------------------------*/
4737 /* genDiv - generates code for division */
4738 /*-----------------------------------------------------------------*/
4742 operand *left = IC_LEFT (ic);
4743 operand *right = IC_RIGHT (ic);
4744 operand *result = IC_RESULT (ic);
4746 D (emitcode (";", "genDiv "););
4748 /* assign the amsops */
4751 /* special cases first */
4753 if (AOP_TYPE (left) == AOP_CRY &&
4754 AOP_TYPE (right) == AOP_CRY)
4756 genDivbits (left, right, result, ic);
4760 /* if both are of size == 1 */
4761 if (AOP_SIZE (left) == 1 &&
4762 AOP_SIZE (right) == 1)
4764 genDivOneByte (left, right, result, ic);
4768 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4769 /* use the ds390 ARITHMETIC accel UNIT */
4770 genDivTwoByte (left, right, result, ic);
4773 /* should have been converted to function call */
4776 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4777 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4778 freeAsmop (result, NULL, ic, TRUE);
4781 /*-----------------------------------------------------------------*/
4782 /* genModbits :- modulus of bits */
4783 /*-----------------------------------------------------------------*/
4785 genModbits (operand * left,
4793 /* the result must be bit */
4794 LOAD_AB_FOR_DIV (left, right, l);
4795 emitcode ("div", "ab");
4796 emitcode ("mov", "a,b");
4797 emitcode ("rrc", "a");
4798 aopOp(result, ic, TRUE, FALSE);
4799 aopPut (AOP (result), "c", 0);
4802 /*-----------------------------------------------------------------*/
4803 /* genModOneByte : 8 bit modulus */
4804 /*-----------------------------------------------------------------*/
4806 genModOneByte (operand * left,
4811 sym_link *opetype = operandType (result);
4815 /* signed or unsigned */
4816 if (SPEC_USIGN (opetype))
4818 /* unsigned is easy */
4819 LOAD_AB_FOR_DIV (left, right, l);
4820 emitcode ("div", "ab");
4821 aopOp(result, ic, TRUE, FALSE);
4822 aopPut (AOP (result), "b", 0);
4826 /* signed is a little bit more difficult */
4828 /* save the signs of the operands */
4829 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4832 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4833 emitcode ("push", "acc"); /* save it on the stack */
4835 /* now sign adjust for both left & right */
4836 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4839 lbl = newiTempLabel (NULL);
4840 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4841 emitcode ("cpl", "a");
4842 emitcode ("inc", "a");
4843 emitcode ("", "!tlabeldef", (lbl->key + 100));
4844 emitcode ("mov", "b,a");
4846 /* sign adjust left side */
4847 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4850 lbl = newiTempLabel (NULL);
4851 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4852 emitcode ("cpl", "a");
4853 emitcode ("inc", "a");
4854 emitcode ("", "!tlabeldef", (lbl->key + 100));
4856 /* now the multiplication */
4857 emitcode ("nop", "; workaround for DS80C390 div bug.");
4858 emitcode ("div", "ab");
4859 /* we are interested in the lower order
4861 lbl = newiTempLabel (NULL);
4862 emitcode ("pop", "acc");
4863 /* if there was an over flow we don't
4864 adjust the sign of the result */
4865 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4866 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4868 emitcode ("clr", "a");
4869 emitcode ("subb", "a,b");
4870 emitcode ("mov", "b,a");
4871 emitcode ("", "!tlabeldef", (lbl->key + 100));
4874 /* now we are done */
4875 aopOp(result, ic, TRUE, FALSE);
4876 aopPut (AOP (result), "b", 0);
4881 /*-----------------------------------------------------------------*/
4882 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
4883 /*-----------------------------------------------------------------*/
4884 static void genModTwoByte (operand *left, operand *right,
4885 operand *result, iCode *ic)
4887 sym_link *retype = getSpec(operandType(right));
4888 sym_link *letype = getSpec(operandType(left));
4889 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4892 /* load up MA with left */
4893 /* save EA bit in F1 */
4894 lbl = newiTempLabel(NULL);
4895 emitcode ("setb","F1");
4896 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4897 emitcode ("clr","F1");
4898 emitcode("","!tlabeldef",lbl->key+100);
4901 lbl = newiTempLabel(NULL);
4902 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4903 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4904 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4905 emitcode ("xch", "a,b");
4906 emitcode ("cpl","a");
4907 emitcode ("add", "a,#1");
4908 emitcode ("xch", "a,b");
4909 emitcode ("cpl", "a"); // msb
4910 emitcode ("addc","a,#0");
4911 emitcode ("","!tlabeldef",lbl->key+100);
4912 emitcode ("mov","ma,b");
4913 emitcode ("mov","ma,a");
4915 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4916 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4919 /* load up MB with right */
4921 if (AOP_TYPE(right) == AOP_LIT) {
4922 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4926 emitcode ("mov","mb,#!constbyte",val & 0xff);
4927 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4929 lbl = newiTempLabel(NULL);
4930 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4931 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4932 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4933 emitcode ("xch", "a,b");
4934 emitcode ("cpl","a");
4935 emitcode ("add", "a,#1");
4936 emitcode ("xch", "a,b");
4937 emitcode ("cpl", "a"); // msb
4938 emitcode ("addc", "a,#0");
4939 emitcode ("","!tlabeldef",lbl->key+100);
4940 emitcode ("mov","mb,b");
4941 emitcode ("mov","mb,a");
4944 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4945 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4948 /* wait for multiplication to finish */
4949 lbl = newiTempLabel(NULL);
4950 emitcode("","!tlabeldef", lbl->key+100);
4951 emitcode("mov","a,mcnt1");
4952 emitcode("anl","a,#!constbyte",0x80);
4953 emitcode("jnz","!tlabel",lbl->key+100);
4955 freeAsmop (left, NULL, ic, TRUE);
4956 freeAsmop (right, NULL, ic,TRUE);
4957 aopOp(result, ic, TRUE, FALSE);
4959 aopPut(AOP(result),"mb",1);
4960 aopPut(AOP(result),"mb",0);
4961 freeAsmop (result, NULL, ic, TRUE);
4963 /* restore EA bit in F1 */
4964 lbl = newiTempLabel(NULL);
4965 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4966 emitcode ("setb","EA");
4967 emitcode("","!tlabeldef",lbl->key+100);
4971 /*-----------------------------------------------------------------*/
4972 /* genMod - generates code for division */
4973 /*-----------------------------------------------------------------*/
4977 operand *left = IC_LEFT (ic);
4978 operand *right = IC_RIGHT (ic);
4979 operand *result = IC_RESULT (ic);
4981 D (emitcode (";", "genMod "); );
4983 /* assign the amsops */
4986 /* special cases first */
4988 if (AOP_TYPE (left) == AOP_CRY &&
4989 AOP_TYPE (right) == AOP_CRY)
4991 genModbits (left, right, result, ic);
4995 /* if both are of size == 1 */
4996 if (AOP_SIZE (left) == 1 &&
4997 AOP_SIZE (right) == 1)
4999 genModOneByte (left, right, result, ic);
5003 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5004 /* use the ds390 ARITHMETIC accel UNIT */
5005 genModTwoByte (left, right, result, ic);
5009 /* should have been converted to function call */
5013 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5014 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5015 freeAsmop (result, NULL, ic, TRUE);
5018 /*-----------------------------------------------------------------*/
5019 /* genIfxJump :- will create a jump depending on the ifx */
5020 /*-----------------------------------------------------------------*/
5022 genIfxJump (iCode * ic, char *jval)
5025 symbol *tlbl = newiTempLabel (NULL);
5028 D (emitcode (";", "genIfxJump ");
5031 /* if true label then we jump if condition
5035 jlbl = IC_TRUE (ic);
5036 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5037 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5041 /* false label is present */
5042 jlbl = IC_FALSE (ic);
5043 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5044 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5046 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5047 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5049 emitcode (inst, "!tlabel", tlbl->key + 100);
5050 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5051 emitcode ("", "!tlabeldef", tlbl->key + 100);
5053 /* mark the icode as generated */
5057 /*-----------------------------------------------------------------*/
5058 /* genCmp :- greater or less than comparison */
5059 /*-----------------------------------------------------------------*/
5061 genCmp (operand * left, operand * right,
5062 iCode * ic, iCode * ifx, int sign)
5064 int size, offset = 0;
5065 unsigned long lit = 0L;
5068 D (emitcode (";", "genCmp");
5071 result = IC_RESULT (ic);
5073 /* if left & right are bit variables */
5074 if (AOP_TYPE (left) == AOP_CRY &&
5075 AOP_TYPE (right) == AOP_CRY)
5077 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5078 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
5082 /* subtract right from left if at the
5083 end the carry flag is set then we know that
5084 left is greater than right */
5085 size = max (AOP_SIZE (left), AOP_SIZE (right));
5087 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5088 if ((size == 1) && !sign &&
5089 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5091 symbol *lbl = newiTempLabel (NULL);
5092 emitcode ("cjne", "%s,%s,!tlabel",
5093 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5094 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5096 emitcode ("", "!tlabeldef", lbl->key + 100);
5100 if (AOP_TYPE (right) == AOP_LIT)
5102 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5103 /* optimize if(x < 0) or if(x >= 0) */
5112 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5114 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5115 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5117 aopOp (result, ic, FALSE, FALSE);
5119 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5121 freeAsmop (result, NULL, ic, TRUE);
5122 genIfxJump (ifx, "acc.7");
5127 emitcode ("rlc", "a");
5129 goto release_freedLR;
5137 //emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5138 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5139 //emitcode (";", "genCmp #2");
5140 if (sign && (size == 0))
5142 //emitcode (";", "genCmp #3");
5143 emitcode ("xrl", "a,#!constbyte",0x80);
5144 if (AOP_TYPE (right) == AOP_LIT)
5146 unsigned long lit = (unsigned long)
5147 floatFromVal (AOP (right)->aopu.aop_lit);
5148 //emitcode (";", "genCmp #3.1");
5149 emitcode ("subb", "a,#!constbyte",
5150 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5154 //emitcode (";", "genCmp #3.2");
5155 if (AOP_NEEDSACC (right))
5157 emitcode ("push", "acc");
5159 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
5160 FALSE, FALSE, FALSE));
5161 emitcode ("xrl", "b,#!constbyte",0x80);
5162 if (AOP_NEEDSACC (right))
5164 emitcode ("pop", "acc");
5166 emitcode ("subb", "a,b");
5173 //emitcode (";", "genCmp #4");
5174 if (AOP_NEEDSACC (right))
5177 //emitcode (";", "genCmp #4.1");
5178 emitcode ("xch", "a, b");
5179 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
5180 emitcode ("xch", "a, b");
5185 //emitcode (";", "genCmp #4.2");
5186 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
5189 emitcode ("subb", "a,%s", s);
5196 /* Don't need the left & right operands any more; do need the result. */
5197 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5198 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5200 aopOp (result, ic, FALSE, FALSE);
5204 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5210 /* if the result is used in the next
5211 ifx conditional branch then generate
5212 code a little differently */
5215 genIfxJump (ifx, "c");
5221 /* leave the result in acc */
5223 freeAsmop (result, NULL, ic, TRUE);
5226 /*-----------------------------------------------------------------*/
5227 /* genCmpGt :- greater than comparison */
5228 /*-----------------------------------------------------------------*/
5230 genCmpGt (iCode * ic, iCode * ifx)
5232 operand *left, *right;
5233 sym_link *letype, *retype;
5236 D (emitcode (";", "genCmpGt ");
5239 left = IC_LEFT (ic);
5240 right = IC_RIGHT (ic);
5242 letype = getSpec (operandType (left));
5243 retype = getSpec (operandType (right));
5244 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5246 /* assign the left & right amsops */
5249 genCmp (right, left, ic, ifx, sign);
5252 /*-----------------------------------------------------------------*/
5253 /* genCmpLt - less than comparisons */
5254 /*-----------------------------------------------------------------*/
5256 genCmpLt (iCode * ic, iCode * ifx)
5258 operand *left, *right;
5259 sym_link *letype, *retype;
5262 D (emitcode (";", "genCmpLt "););
5264 left = IC_LEFT (ic);
5265 right = IC_RIGHT (ic);
5267 letype = getSpec (operandType (left));
5268 retype = getSpec (operandType (right));
5269 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5271 /* assign the left & right amsops */
5274 genCmp (left, right, ic, ifx, sign);
5277 /*-----------------------------------------------------------------*/
5278 /* gencjneshort - compare and jump if not equal */
5279 /*-----------------------------------------------------------------*/
5281 gencjneshort (operand * left, operand * right, symbol * lbl)
5283 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5285 unsigned long lit = 0L;
5287 D (emitcode (";", "gencjneshort");
5290 /* if the left side is a literal or
5291 if the right is in a pointer register and left
5293 if ((AOP_TYPE (left) == AOP_LIT) ||
5294 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5301 if (AOP_TYPE (right) == AOP_LIT)
5302 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5304 if (opIsGptr (left) || opIsGptr (right))
5306 /* We are comparing a generic pointer to something.
5307 * Exclude the generic type byte from the comparison.
5310 D (emitcode (";", "cjneshort: generic ptr special case.");
5315 /* if the right side is a literal then anything goes */
5316 if (AOP_TYPE (right) == AOP_LIT &&
5317 AOP_TYPE (left) != AOP_DIR)
5321 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5323 emitcode ("cjne", "a,%s,!tlabel",
5324 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5330 /* if the right side is in a register or in direct space or
5331 if the left is a pointer register & right is not */
5332 else if (AOP_TYPE (right) == AOP_REG ||
5333 AOP_TYPE (right) == AOP_DIR ||
5334 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5335 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5339 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5340 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5341 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5342 emitcode ("jnz", "!tlabel", lbl->key + 100);
5344 emitcode ("cjne", "a,%s,!tlabel",
5345 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5352 /* right is a pointer reg need both a & b */
5355 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5356 if (strcmp (l, "b"))
5357 emitcode ("mov", "b,%s", l);
5358 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5359 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5365 /*-----------------------------------------------------------------*/
5366 /* gencjne - compare and jump if not equal */
5367 /*-----------------------------------------------------------------*/
5369 gencjne (operand * left, operand * right, symbol * lbl)
5371 symbol *tlbl = newiTempLabel (NULL);
5373 D (emitcode (";", "gencjne");
5376 gencjneshort (left, right, lbl);
5378 emitcode ("mov", "a,%s", one);
5379 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5380 emitcode ("", "!tlabeldef", lbl->key + 100);
5381 emitcode ("clr", "a");
5382 emitcode ("", "!tlabeldef", tlbl->key + 100);
5385 /*-----------------------------------------------------------------*/
5386 /* genCmpEq - generates code for equal to */
5387 /*-----------------------------------------------------------------*/
5389 genCmpEq (iCode * ic, iCode * ifx)
5391 operand *left, *right, *result;
5393 D (emitcode (";", "genCmpEq ");
5397 AOP_SET_LOCALS (ic);
5399 /* if literal, literal on the right or
5400 if the right is in a pointer register and left
5402 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5403 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5405 operand *t = IC_RIGHT (ic);
5406 IC_RIGHT (ic) = IC_LEFT (ic);
5410 if (ifx && /* !AOP_SIZE(result) */
5411 OP_SYMBOL (result) &&
5412 OP_SYMBOL (result)->regType == REG_CND)
5415 /* if they are both bit variables */
5416 if (AOP_TYPE (left) == AOP_CRY &&
5417 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5419 if (AOP_TYPE (right) == AOP_LIT)
5421 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5424 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5425 emitcode ("cpl", "c");
5429 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5433 emitcode ("clr", "c");
5435 /* AOP_TYPE(right) == AOP_CRY */
5439 symbol *lbl = newiTempLabel (NULL);
5440 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5441 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5442 emitcode ("cpl", "c");
5443 emitcode ("", "!tlabeldef", (lbl->key + 100));
5445 /* if true label then we jump if condition
5447 tlbl = newiTempLabel (NULL);
5450 emitcode ("jnc", "!tlabel", tlbl->key + 100);
5451 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5455 emitcode ("jc", "!tlabel", tlbl->key + 100);
5456 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5458 emitcode ("", "!tlabeldef", tlbl->key + 100);
5462 tlbl = newiTempLabel (NULL);
5463 gencjneshort (left, right, tlbl);
5466 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5467 emitcode ("", "!tlabeldef", tlbl->key + 100);
5471 symbol *lbl = newiTempLabel (NULL);
5472 emitcode ("sjmp", "!tlabel", lbl->key + 100);
5473 emitcode ("", "!tlabeldef", tlbl->key + 100);
5474 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5475 emitcode ("", "!tlabeldef", lbl->key + 100);
5478 /* mark the icode as generated */
5481 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5482 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5486 /* if they are both bit variables */
5487 if (AOP_TYPE (left) == AOP_CRY &&
5488 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5490 if (AOP_TYPE (right) == AOP_LIT)
5492 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5495 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5496 emitcode ("cpl", "c");
5500 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5504 emitcode ("clr", "c");
5506 /* AOP_TYPE(right) == AOP_CRY */
5510 symbol *lbl = newiTempLabel (NULL);
5511 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5512 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5513 emitcode ("cpl", "c");
5514 emitcode ("", "!tlabeldef", (lbl->key + 100));
5517 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5518 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5520 aopOp (result, ic, TRUE, FALSE);
5523 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5530 genIfxJump (ifx, "c");
5533 /* if the result is used in an arithmetic operation
5534 then put the result in place */
5539 gencjne (left, right, newiTempLabel (NULL));
5541 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5542 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5544 aopOp (result, ic, TRUE, FALSE);
5546 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5548 aopPut (AOP (result), "a", 0);
5553 genIfxJump (ifx, "a");
5556 /* if the result is used in an arithmetic operation
5557 then put the result in place */
5558 if (AOP_TYPE (result) != AOP_CRY)
5560 /* leave the result in acc */
5564 freeAsmop (result, NULL, ic, TRUE);
5567 /*-----------------------------------------------------------------*/
5568 /* ifxForOp - returns the icode containing the ifx for operand */
5569 /*-----------------------------------------------------------------*/
5571 ifxForOp (operand * op, iCode * ic)
5573 /* if true symbol then needs to be assigned */
5574 if (IS_TRUE_SYMOP (op))
5577 /* if this has register type condition and
5578 the next instruction is ifx with the same operand
5579 and live to of the operand is upto the ifx only then */
5581 ic->next->op == IFX &&
5582 IC_COND (ic->next)->key == op->key &&
5583 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5588 /*-----------------------------------------------------------------*/
5589 /* hasInc - operand is incremented before any other use */
5590 /*-----------------------------------------------------------------*/
5592 hasInc (operand *op, iCode *ic, int osize)
5594 sym_link *type = operandType(op);
5595 sym_link *retype = getSpec (type);
5596 iCode *lic = ic->next;
5599 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5600 if (!IS_SYMOP(op)) return NULL;
5602 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5603 if (IS_AGGREGATE(type->next)) return NULL;
5604 if (osize != (isize = getSize(type->next))) return NULL;
5607 /* if operand of the form op = op + <sizeof *op> */
5608 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5609 isOperandEqual(IC_RESULT(lic),op) &&
5610 isOperandLiteral(IC_RIGHT(lic)) &&
5611 operandLitValue(IC_RIGHT(lic)) == isize) {
5614 /* if the operand used or deffed */
5615 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5618 /* if GOTO or IFX */
5619 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5625 /*-----------------------------------------------------------------*/
5626 /* genAndOp - for && operation */
5627 /*-----------------------------------------------------------------*/
5629 genAndOp (iCode * ic)
5631 operand *left, *right, *result;
5634 D (emitcode (";", "genAndOp "););
5636 /* note here that && operations that are in an
5637 if statement are taken away by backPatchLabels
5638 only those used in arthmetic operations remain */
5640 AOP_SET_LOCALS (ic);
5642 /* if both are bit variables */
5643 if (AOP_TYPE (left) == AOP_CRY &&
5644 AOP_TYPE (right) == AOP_CRY)
5646 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5647 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5648 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5649 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5651 aopOp (result,ic,FALSE, FALSE);
5656 tlbl = newiTempLabel (NULL);
5658 emitcode ("jz", "!tlabel", tlbl->key + 100);
5660 emitcode ("", "!tlabeldef", tlbl->key + 100);
5661 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5662 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5664 aopOp (result,ic,FALSE, FALSE);
5667 freeAsmop (result, NULL, ic, TRUE);
5671 /*-----------------------------------------------------------------*/
5672 /* genOrOp - for || operation */
5673 /*-----------------------------------------------------------------*/
5675 genOrOp (iCode * ic)
5677 operand *left, *right, *result;
5680 D (emitcode (";", "genOrOp "););
5682 /* note here that || operations that are in an
5683 if statement are taken away by backPatchLabels
5684 only those used in arthmetic operations remain */
5686 AOP_SET_LOCALS (ic);
5688 /* if both are bit variables */
5689 if (AOP_TYPE (left) == AOP_CRY &&
5690 AOP_TYPE (right) == AOP_CRY)
5692 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5693 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5694 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5695 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5697 aopOp (result,ic,FALSE, FALSE);
5703 tlbl = newiTempLabel (NULL);
5705 emitcode ("jnz", "!tlabel", tlbl->key + 100);
5707 emitcode ("", "!tlabeldef", tlbl->key + 100);
5708 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5709 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5711 aopOp (result,ic,FALSE, FALSE);
5716 freeAsmop (result, NULL, ic, TRUE);
5719 /*-----------------------------------------------------------------*/
5720 /* isLiteralBit - test if lit == 2^n */
5721 /*-----------------------------------------------------------------*/
5723 isLiteralBit (unsigned long lit)
5725 unsigned long pw[32] =
5726 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5727 0x100L, 0x200L, 0x400L, 0x800L,
5728 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5729 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5730 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5731 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5732 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5735 for (idx = 0; idx < 32; idx++)
5741 /*-----------------------------------------------------------------*/
5742 /* continueIfTrue - */
5743 /*-----------------------------------------------------------------*/
5745 continueIfTrue (iCode * ic)
5748 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5752 /*-----------------------------------------------------------------*/
5754 /*-----------------------------------------------------------------*/
5756 jumpIfTrue (iCode * ic)
5759 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5763 /*-----------------------------------------------------------------*/
5764 /* jmpTrueOrFalse - */
5765 /*-----------------------------------------------------------------*/
5767 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5769 // ugly but optimized by peephole
5772 symbol *nlbl = newiTempLabel (NULL);
5773 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
5774 emitcode ("", "!tlabeldef", tlbl->key + 100);
5775 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5776 emitcode ("", "!tlabeldef", nlbl->key + 100);
5780 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5781 emitcode ("", "!tlabeldef", tlbl->key + 100);
5786 // Generate code to perform a bit-wise logic operation
5787 // on two operands in far space (assumed to already have been
5788 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5789 // in far space. This requires pushing the result on the stack
5790 // then popping it into the result.
5792 genFarFarLogicOp(iCode *ic, char *logicOp)
5794 int size, resultSize, compSize;
5798 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5799 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5800 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5802 _startLazyDPSEvaluation();
5803 for (size = compSize; (size--); offset++)
5805 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5806 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5807 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5809 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5810 emitcode ("push", "acc");
5812 _endLazyDPSEvaluation();
5814 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5815 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5816 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5818 resultSize = AOP_SIZE(IC_RESULT(ic));
5820 ADJUST_PUSHED_RESULT(compSize, resultSize);
5822 _startLazyDPSEvaluation();
5825 emitcode ("pop", "acc");
5826 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5828 _endLazyDPSEvaluation();
5829 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5833 /*-----------------------------------------------------------------*/
5834 /* genAnd - code for and */
5835 /*-----------------------------------------------------------------*/
5837 genAnd (iCode * ic, iCode * ifx)
5839 operand *left, *right, *result;
5840 int size, offset = 0;
5841 unsigned long lit = 0L;
5846 D (emitcode (";", "genAnd "););
5848 AOP_OP_3_NOFATAL (ic, pushResult);
5849 AOP_SET_LOCALS (ic);
5853 genFarFarLogicOp(ic, "anl");
5858 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5860 AOP_TYPE (left), AOP_TYPE (right));
5861 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5863 AOP_SIZE (left), AOP_SIZE (right));
5866 /* if left is a literal & right is not then exchange them */
5867 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5868 #ifdef LOGIC_OPS_BROKEN
5869 || AOP_NEEDSACC (left)
5873 operand *tmp = right;
5878 /* if result = right then exchange them */
5879 if (sameRegs (AOP (result), AOP (right)))
5881 operand *tmp = right;
5886 /* if right is bit then exchange them */
5887 if (AOP_TYPE (right) == AOP_CRY &&
5888 AOP_TYPE (left) != AOP_CRY)
5890 operand *tmp = right;
5894 if (AOP_TYPE (right) == AOP_LIT)
5895 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5897 size = AOP_SIZE (result);
5900 // result = bit & yy;
5901 if (AOP_TYPE (left) == AOP_CRY)
5903 // c = bit & literal;
5904 if (AOP_TYPE (right) == AOP_LIT)
5908 if (size && sameRegs (AOP (result), AOP (left)))
5911 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5916 if (size && (AOP_TYPE (result) == AOP_CRY))
5918 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5921 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5926 emitcode ("clr", "c");
5931 if (AOP_TYPE (right) == AOP_CRY)
5934 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5935 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5940 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5942 emitcode ("rrc", "a");
5943 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5951 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5952 genIfxJump (ifx, "c");
5956 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5957 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5958 if ((AOP_TYPE (right) == AOP_LIT) &&
5959 (AOP_TYPE (result) == AOP_CRY) &&
5960 (AOP_TYPE (left) != AOP_CRY))
5962 int posbit = isLiteralBit (lit);
5967 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5970 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5976 sprintf (buffer, "acc.%d", posbit & 0x07);
5977 genIfxJump (ifx, buffer);
5984 symbol *tlbl = newiTempLabel (NULL);
5985 int sizel = AOP_SIZE (left);
5987 emitcode ("setb", "c");
5990 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5992 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5994 if ((posbit = isLiteralBit (bytelit)) != 0)
5995 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
5998 if (bytelit != 0x0FFL)
5999 emitcode ("anl", "a,%s",
6000 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
6001 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6006 // bit = left & literal
6009 emitcode ("clr", "c");
6010 emitcode ("", "!tlabeldef", tlbl->key + 100);
6012 // if(left & literal)
6016 jmpTrueOrFalse (ifx, tlbl);
6024 /* if left is same as result */
6025 if (sameRegs (AOP (result), AOP (left)))
6027 for (; size--; offset++)
6029 if (AOP_TYPE (right) == AOP_LIT)
6031 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6033 else if (bytelit == 0)
6034 aopPut (AOP (result), zero, offset);
6035 else if (IS_AOP_PREG (result))
6037 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6038 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6039 aopPut (AOP (result), "a", offset);
6042 emitcode ("anl", "%s,%s",
6043 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6044 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6048 if (AOP_TYPE (left) == AOP_ACC)
6049 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6052 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6053 if (IS_AOP_PREG (result))
6055 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6056 aopPut (AOP (result), "a", offset);
6060 emitcode ("anl", "%s,a",
6061 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6068 // left & result in different registers
6069 if (AOP_TYPE (result) == AOP_CRY)
6072 // if(size), result in bit
6073 // if(!size && ifx), conditional oper: if(left & right)
6074 symbol *tlbl = newiTempLabel (NULL);
6075 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6077 emitcode ("setb", "c");
6080 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6081 emitcode ("anl", "a,%s",
6082 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6084 if (AOP_TYPE(left)==AOP_ACC) {
6085 emitcode("mov", "b,a");
6086 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6087 emitcode("anl", "a,b");
6089 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6090 emitcode ("anl", "a,%s",
6091 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6094 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6100 emitcode ("", "!tlabeldef", tlbl->key + 100);
6104 jmpTrueOrFalse (ifx, tlbl);
6108 for (; (size--); offset++)
6111 // result = left & right
6112 if (AOP_TYPE (right) == AOP_LIT)
6114 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6116 aopPut (AOP (result),
6117 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6121 else if (bytelit == 0)
6123 aopPut (AOP (result), zero, offset);
6126 D (emitcode (";", "better literal AND."););
6127 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6128 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6129 FALSE, FALSE, FALSE));
6134 // faster than result <- left, anl result,right
6135 // and better if result is SFR
6136 if (AOP_TYPE (left) == AOP_ACC)
6138 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
6139 FALSE, FALSE, FALSE));
6143 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6144 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6146 emitcode("mov", "b,a");
6150 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6151 emitcode ("anl", "a,%s", rOp);
6154 aopPut (AOP (result), "a", offset);
6160 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6161 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6162 freeAsmop (result, NULL, ic, TRUE);
6166 /*-----------------------------------------------------------------*/
6167 /* genOr - code for or */
6168 /*-----------------------------------------------------------------*/
6170 genOr (iCode * ic, iCode * ifx)
6172 operand *left, *right, *result;
6173 int size, offset = 0;
6174 unsigned long lit = 0L;
6177 D (emitcode (";", "genOr "););
6179 AOP_OP_3_NOFATAL (ic, pushResult);
6180 AOP_SET_LOCALS (ic);
6184 genFarFarLogicOp(ic, "orl");
6190 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6192 AOP_TYPE (left), AOP_TYPE (right));
6193 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6195 AOP_SIZE (left), AOP_SIZE (right));
6198 /* if left is a literal & right is not then exchange them */
6199 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6200 #ifdef LOGIC_OPS_BROKEN
6201 || AOP_NEEDSACC (left) // I think this is a net loss now.
6205 operand *tmp = right;
6210 /* if result = right then exchange them */
6211 if (sameRegs (AOP (result), AOP (right)))
6213 operand *tmp = right;
6218 /* if right is bit then exchange them */
6219 if (AOP_TYPE (right) == AOP_CRY &&
6220 AOP_TYPE (left) != AOP_CRY)
6222 operand *tmp = right;
6226 if (AOP_TYPE (right) == AOP_LIT)
6227 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6229 size = AOP_SIZE (result);
6233 if (AOP_TYPE (left) == AOP_CRY)
6235 if (AOP_TYPE (right) == AOP_LIT)
6237 // c = bit & literal;
6240 // lit != 0 => result = 1
6241 if (AOP_TYPE (result) == AOP_CRY)
6244 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6246 continueIfTrue (ifx);
6249 emitcode ("setb", "c");
6253 // lit == 0 => result = left
6254 if (size && sameRegs (AOP (result), AOP (left)))
6256 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6261 if (AOP_TYPE (right) == AOP_CRY)
6264 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6265 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6270 symbol *tlbl = newiTempLabel (NULL);
6271 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6272 emitcode ("setb", "c");
6273 emitcode ("jb", "%s,!tlabel",
6274 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6276 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6277 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6279 jmpTrueOrFalse (ifx, tlbl);
6285 emitcode ("", "!tlabeldef", tlbl->key + 100);
6294 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6295 genIfxJump (ifx, "c");
6299 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6300 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6301 if ((AOP_TYPE (right) == AOP_LIT) &&
6302 (AOP_TYPE (result) == AOP_CRY) &&
6303 (AOP_TYPE (left) != AOP_CRY))
6309 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6311 continueIfTrue (ifx);
6316 // lit = 0, result = boolean(left)
6318 emitcode ("setb", "c");
6322 symbol *tlbl = newiTempLabel (NULL);
6323 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6325 emitcode ("", "!tlabeldef", tlbl->key + 100);
6329 genIfxJump (ifx, "a");
6337 /* if left is same as result */
6338 if (sameRegs (AOP (result), AOP (left)))
6340 for (; size--; offset++)
6342 if (AOP_TYPE (right) == AOP_LIT)
6344 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6350 if (IS_AOP_PREG (left))
6352 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6353 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6354 aopPut (AOP (result), "a", offset);
6358 emitcode ("orl", "%s,%s",
6359 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6360 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6366 if (AOP_TYPE (left) == AOP_ACC)
6368 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6372 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6373 if (IS_AOP_PREG (left))
6375 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6376 aopPut (AOP (result), "a", offset);
6380 emitcode ("orl", "%s,a",
6381 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6389 // left & result in different registers
6390 if (AOP_TYPE (result) == AOP_CRY)
6393 // if(size), result in bit
6394 // if(!size && ifx), conditional oper: if(left | right)
6395 symbol *tlbl = newiTempLabel (NULL);
6396 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6398 emitcode ("setb", "c");
6401 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6402 emitcode ("orl", "a,%s",
6403 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6405 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6406 emitcode ("orl", "a,%s",
6407 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6409 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6415 emitcode ("", "!tlabeldef", tlbl->key + 100);
6419 jmpTrueOrFalse (ifx, tlbl);
6423 _startLazyDPSEvaluation();
6424 for (; (size--); offset++)
6427 // result = left & right
6428 if (AOP_TYPE (right) == AOP_LIT)
6430 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6432 aopPut (AOP (result),
6433 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6437 D (emitcode (";", "better literal OR."););
6438 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6439 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6440 FALSE, FALSE, FALSE));
6445 // faster than result <- left, anl result,right
6446 // and better if result is SFR
6447 if (AOP_TYPE (left) == AOP_ACC)
6449 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6450 FALSE, FALSE, FALSE));
6454 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6456 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6458 emitcode("mov", "b,a");
6462 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6463 emitcode ("orl", "a,%s", rOp);
6466 aopPut (AOP (result), "a", offset);
6468 _endLazyDPSEvaluation();
6473 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6474 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6475 freeAsmop (result, NULL, ic, TRUE);
6478 /*-----------------------------------------------------------------*/
6479 /* genXor - code for xclusive or */
6480 /*-----------------------------------------------------------------*/
6482 genXor (iCode * ic, iCode * ifx)
6484 operand *left, *right, *result;
6485 int size, offset = 0;
6486 unsigned long lit = 0L;
6489 D (emitcode (";", "genXor "););
6491 AOP_OP_3_NOFATAL (ic, pushResult);
6492 AOP_SET_LOCALS (ic);
6496 genFarFarLogicOp(ic, "xrl");
6501 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6503 AOP_TYPE (left), AOP_TYPE (right));
6504 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6506 AOP_SIZE (left), AOP_SIZE (right));
6509 /* if left is a literal & right is not ||
6510 if left needs acc & right does not */
6511 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6512 #ifdef LOGIC_OPS_BROKEN
6513 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6517 operand *tmp = right;
6522 /* if result = right then exchange them */
6523 if (sameRegs (AOP (result), AOP (right)))
6525 operand *tmp = right;
6530 /* if right is bit then exchange them */
6531 if (AOP_TYPE (right) == AOP_CRY &&
6532 AOP_TYPE (left) != AOP_CRY)
6534 operand *tmp = right;
6538 if (AOP_TYPE (right) == AOP_LIT)
6539 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6541 size = AOP_SIZE (result);
6545 if (AOP_TYPE (left) == AOP_CRY)
6547 if (AOP_TYPE (right) == AOP_LIT)
6549 // c = bit & literal;
6552 // lit>>1 != 0 => result = 1
6553 if (AOP_TYPE (result) == AOP_CRY)
6556 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6558 continueIfTrue (ifx);
6561 emitcode ("setb", "c");
6568 // lit == 0, result = left
6569 if (size && sameRegs (AOP (result), AOP (left)))
6571 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6575 // lit == 1, result = not(left)
6576 if (size && sameRegs (AOP (result), AOP (left)))
6578 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6583 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6584 emitcode ("cpl", "c");
6593 symbol *tlbl = newiTempLabel (NULL);
6594 if (AOP_TYPE (right) == AOP_CRY)
6597 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6601 int sizer = AOP_SIZE (right);
6603 // if val>>1 != 0, result = 1
6604 emitcode ("setb", "c");
6607 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6609 // test the msb of the lsb
6610 emitcode ("anl", "a,#!constbyte",0xfe);
6611 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6615 emitcode ("rrc", "a");
6617 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6618 emitcode ("cpl", "c");
6619 emitcode ("", "!tlabeldef", (tlbl->key + 100));
6626 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6627 genIfxJump (ifx, "c");
6631 if (sameRegs (AOP (result), AOP (left)))
6633 /* if left is same as result */
6634 for (; size--; offset++)
6636 if (AOP_TYPE (right) == AOP_LIT)
6638 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6640 else if (IS_AOP_PREG (left))
6642 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6643 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6644 aopPut (AOP (result), "a", offset);
6647 emitcode ("xrl", "%s,%s",
6648 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6649 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6653 if (AOP_TYPE (left) == AOP_ACC)
6654 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6657 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6658 if (IS_AOP_PREG (left))
6660 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6661 aopPut (AOP (result), "a", offset);
6664 emitcode ("xrl", "%s,a",
6665 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6672 // left & result in different registers
6673 if (AOP_TYPE (result) == AOP_CRY)
6676 // if(size), result in bit
6677 // if(!size && ifx), conditional oper: if(left ^ right)
6678 symbol *tlbl = newiTempLabel (NULL);
6679 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6682 emitcode ("setb", "c");
6685 if ((AOP_TYPE (right) == AOP_LIT) &&
6686 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6688 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6692 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6693 emitcode ("xrl", "a,%s",
6694 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6696 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6697 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6699 emitcode("mov", "b,a");
6703 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6704 emitcode ("xrl", "a,%s", rOp);
6707 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6713 emitcode ("", "!tlabeldef", tlbl->key + 100);
6717 jmpTrueOrFalse (ifx, tlbl);
6721 for (; (size--); offset++)
6724 // result = left & right
6725 if (AOP_TYPE (right) == AOP_LIT)
6727 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6729 aopPut (AOP (result),
6730 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6734 D (emitcode (";", "better literal XOR."););
6735 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6736 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6737 FALSE, FALSE, FALSE));
6741 // faster than result <- left, anl result,right
6742 // and better if result is SFR
6743 if (AOP_TYPE (left) == AOP_ACC)
6745 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6746 FALSE, FALSE, FALSE));
6750 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6751 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6753 emitcode("mov", "b,a");
6757 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6758 emitcode ("xrl", "a,%s", rOp);
6761 aopPut (AOP (result), "a", offset);
6768 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6769 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6770 freeAsmop (result, NULL, ic, TRUE);
6773 /*-----------------------------------------------------------------*/
6774 /* genInline - write the inline code out */
6775 /*-----------------------------------------------------------------*/
6777 genInline (iCode * ic)
6779 char *buffer, *bp, *bp1;
6781 D (emitcode (";", "genInline ");
6784 _G.inLine += (!options.asmpeep);
6786 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6787 strcpy (buffer, IC_INLINE (ic));
6789 /* emit each line as a code */
6814 /* emitcode("",buffer); */
6815 _G.inLine -= (!options.asmpeep);
6818 /*-----------------------------------------------------------------*/
6819 /* genRRC - rotate right with carry */
6820 /*-----------------------------------------------------------------*/
6824 operand *left, *result;
6825 int size, offset = 0;
6828 D (emitcode (";", "genRRC ");
6831 /* rotate right with carry */
6832 left = IC_LEFT (ic);
6833 result = IC_RESULT (ic);
6834 aopOp (left, ic, FALSE, FALSE);
6835 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6837 /* move it to the result */
6838 size = AOP_SIZE (result);
6842 _startLazyDPSEvaluation ();
6845 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6847 emitcode ("rrc", "a");
6848 if (AOP_SIZE (result) > 1)
6849 aopPut (AOP (result), "a", offset--);
6851 _endLazyDPSEvaluation ();
6853 /* now we need to put the carry into the
6854 highest order byte of the result */
6855 if (AOP_SIZE (result) > 1)
6857 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6860 emitcode ("mov", "acc.7,c");
6861 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6862 freeAsmop (left, NULL, ic, TRUE);
6863 freeAsmop (result, NULL, ic, TRUE);
6866 /*-----------------------------------------------------------------*/
6867 /* genRLC - generate code for rotate left with carry */
6868 /*-----------------------------------------------------------------*/
6872 operand *left, *result;
6873 int size, offset = 0;
6876 D (emitcode (";", "genRLC ");
6879 /* rotate right with carry */
6880 left = IC_LEFT (ic);
6881 result = IC_RESULT (ic);
6882 aopOp (left, ic, FALSE, FALSE);
6883 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6885 /* move it to the result */
6886 size = AOP_SIZE (result);
6890 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6892 emitcode ("add", "a,acc");
6893 if (AOP_SIZE (result) > 1)
6895 aopPut (AOP (result), "a", offset++);
6898 _startLazyDPSEvaluation ();
6901 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6903 emitcode ("rlc", "a");
6904 if (AOP_SIZE (result) > 1)
6905 aopPut (AOP (result), "a", offset++);
6907 _endLazyDPSEvaluation ();
6909 /* now we need to put the carry into the
6910 highest order byte of the result */
6911 if (AOP_SIZE (result) > 1)
6913 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6916 emitcode ("mov", "acc.0,c");
6917 aopPut (AOP (result), "a", 0);
6918 freeAsmop (left, NULL, ic, TRUE);
6919 freeAsmop (result, NULL, ic, TRUE);
6922 /*-----------------------------------------------------------------*/
6923 /* genGetHbit - generates code get highest order bit */
6924 /*-----------------------------------------------------------------*/
6926 genGetHbit (iCode * ic)
6928 operand *left, *result;
6929 left = IC_LEFT (ic);
6930 result = IC_RESULT (ic);
6931 aopOp (left, ic, FALSE, FALSE);
6932 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6934 D (emitcode (";", "genGetHbit ");
6937 /* get the highest order byte into a */
6938 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6939 if (AOP_TYPE (result) == AOP_CRY)
6941 emitcode ("rlc", "a");
6946 emitcode ("rl", "a");
6947 emitcode ("anl", "a,#1");
6952 freeAsmop (left, NULL, ic, TRUE);
6953 freeAsmop (result, NULL, ic, TRUE);
6956 /*-----------------------------------------------------------------*/
6957 /* AccRol - rotate left accumulator by known count */
6958 /*-----------------------------------------------------------------*/
6960 AccRol (int shCount)
6962 shCount &= 0x0007; // shCount : 0..7
6969 emitcode ("rl", "a");
6972 emitcode ("rl", "a");
6973 emitcode ("rl", "a");
6976 emitcode ("swap", "a");
6977 emitcode ("rr", "a");
6980 emitcode ("swap", "a");
6983 emitcode ("swap", "a");
6984 emitcode ("rl", "a");
6987 emitcode ("rr", "a");
6988 emitcode ("rr", "a");
6991 emitcode ("rr", "a");
6996 /*-----------------------------------------------------------------*/
6997 /* AccLsh - left shift accumulator by known count */
6998 /*-----------------------------------------------------------------*/
7000 AccLsh (int shCount)
7005 emitcode ("add", "a,acc");
7006 else if (shCount == 2)
7008 emitcode ("add", "a,acc");
7009 emitcode ("add", "a,acc");
7013 /* rotate left accumulator */
7015 /* and kill the lower order bits */
7016 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7021 /*-----------------------------------------------------------------*/
7022 /* AccRsh - right shift accumulator by known count */
7023 /*-----------------------------------------------------------------*/
7025 AccRsh (int shCount)
7032 emitcode ("rrc", "a");
7036 /* rotate right accumulator */
7037 AccRol (8 - shCount);
7038 /* and kill the higher order bits */
7039 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7044 #ifdef BETTER_LITERAL_SHIFT
7045 /*-----------------------------------------------------------------*/
7046 /* AccSRsh - signed right shift accumulator by known count */
7047 /*-----------------------------------------------------------------*/
7049 AccSRsh (int shCount)
7056 emitcode ("mov", "c,acc.7");
7057 emitcode ("rrc", "a");
7059 else if (shCount == 2)
7061 emitcode ("mov", "c,acc.7");
7062 emitcode ("rrc", "a");
7063 emitcode ("mov", "c,acc.7");
7064 emitcode ("rrc", "a");
7068 tlbl = newiTempLabel (NULL);
7069 /* rotate right accumulator */
7070 AccRol (8 - shCount);
7071 /* and kill the higher order bits */
7072 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7073 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7074 emitcode ("orl", "a,#!constbyte",
7075 (unsigned char) ~SRMask[shCount]);
7076 emitcode ("", "!tlabeldef", tlbl->key + 100);
7082 #ifdef BETTER_LITERAL_SHIFT
7083 /*-----------------------------------------------------------------*/
7084 /* shiftR1Left2Result - shift right one byte from left to result */
7085 /*-----------------------------------------------------------------*/
7087 shiftR1Left2Result (operand * left, int offl,
7088 operand * result, int offr,
7089 int shCount, int sign)
7091 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7092 /* shift right accumulator */
7097 aopPut (AOP (result), "a", offr);
7101 #ifdef BETTER_LITERAL_SHIFT
7102 /*-----------------------------------------------------------------*/
7103 /* shiftL1Left2Result - shift left one byte from left to result */
7104 /*-----------------------------------------------------------------*/
7106 shiftL1Left2Result (operand * left, int offl,
7107 operand * result, int offr, int shCount)
7109 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7110 /* shift left accumulator */
7112 aopPut (AOP (result), "a", offr);
7116 #ifdef BETTER_LITERAL_SHIFT
7117 /*-----------------------------------------------------------------*/
7118 /* movLeft2Result - move byte from left to result */
7119 /*-----------------------------------------------------------------*/
7121 movLeft2Result (operand * left, int offl,
7122 operand * result, int offr, int sign)
7125 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7127 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
7129 if (*l == '@' && (IS_AOP_PREG (result)))
7131 emitcode ("mov", "a,%s", l);
7132 aopPut (AOP (result), "a", offr);
7138 aopPut (AOP (result), l, offr);
7142 /* MSB sign in acc.7 ! */
7143 if (getDataSize (left) == offl + 1)
7145 emitcode ("mov", "a,%s", l);
7146 aopPut (AOP (result), "a", offr);
7154 #ifdef BETTER_LITERAL_SHIFT
7155 /*-----------------------------------------------------------------*/
7156 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7157 /*-----------------------------------------------------------------*/
7161 emitcode ("rrc", "a");
7162 emitcode ("xch", "a,%s", x);
7163 emitcode ("rrc", "a");
7164 emitcode ("xch", "a,%s", x);
7168 #ifdef BETTER_LITERAL_SHIFT
7170 /*-----------------------------------------------------------------*/
7171 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7172 /*-----------------------------------------------------------------*/
7176 emitcode ("xch", "a,%s", x);
7177 emitcode ("rlc", "a");
7178 emitcode ("xch", "a,%s", x);
7179 emitcode ("rlc", "a");
7183 #ifdef BETTER_LITERAL_SHIFT
7184 /*-----------------------------------------------------------------*/
7185 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7186 /*-----------------------------------------------------------------*/
7190 emitcode ("xch", "a,%s", x);
7191 emitcode ("add", "a,acc");
7192 emitcode ("xch", "a,%s", x);
7193 emitcode ("rlc", "a");
7197 #ifdef BETTER_LITERAL_SHIFT
7198 /*-----------------------------------------------------------------*/
7199 /* AccAXLsh - left shift a:x by known count (0..7) */
7200 /*-----------------------------------------------------------------*/
7202 AccAXLsh (char *x, int shCount)
7217 case 5: // AAAAABBB:CCCCCDDD
7219 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7221 emitcode ("anl", "a,#!constbyte",
7222 SLMask[shCount]); // BBB00000:CCCCCDDD
7224 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7226 AccRol (shCount); // DDDCCCCC:BBB00000
7228 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7230 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7232 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7234 emitcode ("anl", "a,#!constbyte",
7235 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7237 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7239 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7242 case 6: // AAAAAABB:CCCCCCDD
7243 emitcode ("anl", "a,#!constbyte",
7244 SRMask[shCount]); // 000000BB:CCCCCCDD
7245 emitcode ("mov", "c,acc.0"); // c = B
7246 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7248 AccAXRrl1 (x); // BCCCCCCD:D000000B
7249 AccAXRrl1 (x); // BBCCCCCC:DD000000
7251 emitcode("rrc","a");
7252 emitcode("xch","a,%s", x);
7253 emitcode("rrc","a");
7254 emitcode("mov","c,acc.0"); //<< get correct bit
7255 emitcode("xch","a,%s", x);
7257 emitcode("rrc","a");
7258 emitcode("xch","a,%s", x);
7259 emitcode("rrc","a");
7260 emitcode("xch","a,%s", x);
7263 case 7: // a:x <<= 7
7265 emitcode ("anl", "a,#!constbyte",
7266 SRMask[shCount]); // 0000000B:CCCCCCCD
7268 emitcode ("mov", "c,acc.0"); // c = B
7270 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7272 AccAXRrl1 (x); // BCCCCCCC:D0000000
7281 #ifdef BETTER_LITERAL_SHIFT
7283 /*-----------------------------------------------------------------*/
7284 /* AccAXRsh - right shift a:x known count (0..7) */
7285 /*-----------------------------------------------------------------*/
7287 AccAXRsh (char *x, int shCount)
7295 AccAXRrl1 (x); // 0->a:x
7300 AccAXRrl1 (x); // 0->a:x
7303 AccAXRrl1 (x); // 0->a:x
7308 case 5: // AAAAABBB:CCCCCDDD = a:x
7310 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7312 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7314 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7316 emitcode ("anl", "a,#!constbyte",
7317 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7319 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7321 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7323 emitcode ("anl", "a,#!constbyte",
7324 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7326 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7328 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7330 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7333 case 6: // AABBBBBB:CCDDDDDD
7335 emitcode ("mov", "c,acc.7");
7336 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7338 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7340 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7342 emitcode ("anl", "a,#!constbyte",
7343 SRMask[shCount]); // 000000AA:BBBBBBCC
7346 case 7: // ABBBBBBB:CDDDDDDD
7348 emitcode ("mov", "c,acc.7"); // c = A
7350 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7352 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7354 emitcode ("anl", "a,#!constbyte",
7355 SRMask[shCount]); // 0000000A:BBBBBBBC
7364 #ifdef BETTER_LITERAL_SHIFT
7365 /*-----------------------------------------------------------------*/
7366 /* AccAXRshS - right shift signed a:x known count (0..7) */
7367 /*-----------------------------------------------------------------*/
7369 AccAXRshS (char *x, int shCount)
7377 emitcode ("mov", "c,acc.7");
7378 AccAXRrl1 (x); // s->a:x
7382 emitcode ("mov", "c,acc.7");
7383 AccAXRrl1 (x); // s->a:x
7385 emitcode ("mov", "c,acc.7");
7386 AccAXRrl1 (x); // s->a:x
7391 case 5: // AAAAABBB:CCCCCDDD = a:x
7393 tlbl = newiTempLabel (NULL);
7394 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7396 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7398 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7400 emitcode ("anl", "a,#!constbyte",
7401 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7403 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7405 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7407 emitcode ("anl", "a,#!constbyte",
7408 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7410 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7412 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7414 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7416 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7417 emitcode ("orl", "a,#!constbyte",
7418 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7420 emitcode ("", "!tlabeldef", tlbl->key + 100);
7421 break; // SSSSAAAA:BBBCCCCC
7423 case 6: // AABBBBBB:CCDDDDDD
7425 tlbl = newiTempLabel (NULL);
7426 emitcode ("mov", "c,acc.7");
7427 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7429 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7431 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7433 emitcode ("anl", "a,#!constbyte",
7434 SRMask[shCount]); // 000000AA:BBBBBBCC
7436 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7437 emitcode ("orl", "a,#!constbyte",
7438 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7440 emitcode ("", "!tlabeldef", tlbl->key + 100);
7442 case 7: // ABBBBBBB:CDDDDDDD
7444 tlbl = newiTempLabel (NULL);
7445 emitcode ("mov", "c,acc.7"); // c = A
7447 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7449 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7451 emitcode ("anl", "a,#!constbyte",
7452 SRMask[shCount]); // 0000000A:BBBBBBBC
7454 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7455 emitcode ("orl", "a,#!constbyte",
7456 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7458 emitcode ("", "!tlabeldef", tlbl->key + 100);
7466 #ifdef BETTER_LITERAL_SHIFT
7468 _loadLeftIntoAx(char **lsb,
7474 // Get the initial value from left into a pair of registers.
7475 // MSB must be in A, LSB can be any register.
7477 // If the result is held in registers, it is an optimization
7478 // if the LSB can be held in the register which will hold the,
7479 // result LSB since this saves us from having to copy it into
7480 // the result following AccAXLsh.
7482 // If the result is addressed indirectly, this is not a gain.
7483 if (AOP_NEEDSACC(result))
7487 _startLazyDPSEvaluation();
7488 if (AOP_TYPE(left) == AOP_DPTR2)
7491 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7492 // get LSB in DP2_RESULT_REG.
7493 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7494 assert(!strcmp(leftByte, DP2_RESULT_REG));
7498 // get LSB into DP2_RESULT_REG
7499 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7500 if (strcmp(leftByte, DP2_RESULT_REG))
7503 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7506 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7507 assert(strcmp(leftByte, DP2_RESULT_REG));
7510 _endLazyDPSEvaluation();
7511 *lsb = DP2_RESULT_REG;
7515 if (sameRegs (AOP (result), AOP (left)) &&
7516 ((offl + MSB16) == offr))
7518 /* don't crash result[offr] */
7519 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7520 emitcode ("xch", "a,%s",
7521 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7525 movLeft2Result (left, offl, result, offr, 0);
7526 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7528 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7529 assert(strcmp(*lsb,"a"));
7534 _storeAxResults(char *lsb,
7538 _startLazyDPSEvaluation();
7539 if (AOP_NEEDSACC(result))
7541 /* We have to explicitly update the result LSB.
7543 emitcode("xch","a,%s", lsb);
7544 aopPut(AOP(result), "a", offr);
7545 emitcode("mov","a,%s", lsb);
7547 if (getDataSize (result) > 1)
7549 aopPut (AOP (result), "a", offr + MSB16);
7551 _endLazyDPSEvaluation();
7554 /*-----------------------------------------------------------------*/
7555 /* shiftL2Left2Result - shift left two bytes from left to result */
7556 /*-----------------------------------------------------------------*/
7558 shiftL2Left2Result (operand * left, int offl,
7559 operand * result, int offr, int shCount)
7563 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7565 AccAXLsh (lsb, shCount);
7567 _storeAxResults(lsb, result, offr);
7571 #ifdef BETTER_LITERAL_SHIFT
7572 /*-----------------------------------------------------------------*/
7573 /* shiftR2Left2Result - shift right two bytes from left to result */
7574 /*-----------------------------------------------------------------*/
7576 shiftR2Left2Result (operand * left, int offl,
7577 operand * result, int offr,
7578 int shCount, int sign)
7582 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7584 /* a:x >> shCount (x = lsb(result)) */
7587 AccAXRshS(lsb, shCount);
7591 AccAXRsh(lsb, shCount);
7594 _storeAxResults(lsb, result, offr);
7600 /*-----------------------------------------------------------------*/
7601 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7602 /*-----------------------------------------------------------------*/
7604 shiftLLeftOrResult (operand * left, int offl,
7605 operand * result, int offr, int shCount)
7607 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7608 /* shift left accumulator */
7610 /* or with result */
7611 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7612 /* back to result */
7613 aopPut (AOP (result), "a", offr);
7619 /*-----------------------------------------------------------------*/
7620 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7621 /*-----------------------------------------------------------------*/
7623 shiftRLeftOrResult (operand * left, int offl,
7624 operand * result, int offr, int shCount)
7626 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7627 /* shift right accumulator */
7629 /* or with result */
7630 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7631 /* back to result */
7632 aopPut (AOP (result), "a", offr);
7636 #ifdef BETTER_LITERAL_SHIFT
7637 /*-----------------------------------------------------------------*/
7638 /* genlshOne - left shift a one byte quantity by known count */
7639 /*-----------------------------------------------------------------*/
7641 genlshOne (operand * result, operand * left, int shCount)
7643 D (emitcode (";", "genlshOne "););
7644 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7648 #ifdef BETTER_LITERAL_SHIFT
7649 /*-----------------------------------------------------------------*/
7650 /* genlshTwo - left shift two bytes by known amount != 0 */
7651 /*-----------------------------------------------------------------*/
7653 genlshTwo (operand * result, operand * left, int shCount)
7657 D (emitcode (";", "genlshTwo "););
7659 size = getDataSize (result);
7661 /* if shCount >= 8 */
7666 _startLazyDPSEvaluation();
7672 _endLazyDPSEvaluation();
7673 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7674 aopPut (AOP (result), zero, LSB);
7678 movLeft2Result (left, LSB, result, MSB16, 0);
7679 aopPut (AOP (result), zero, LSB);
7680 _endLazyDPSEvaluation();
7685 aopPut (AOP (result), zero, LSB);
7686 _endLazyDPSEvaluation();
7690 /* 1 <= shCount <= 7 */
7695 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7699 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7707 /*-----------------------------------------------------------------*/
7708 /* shiftLLong - shift left one long from left to result */
7709 /* offl = LSB or MSB16 */
7710 /*-----------------------------------------------------------------*/
7712 shiftLLong (operand * left, operand * result, int offr)
7715 int size = AOP_SIZE (result);
7717 if (size >= LSB + offr)
7719 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7721 emitcode ("add", "a,acc");
7722 if (sameRegs (AOP (left), AOP (result)) &&
7723 size >= MSB16 + offr && offr != LSB)
7724 emitcode ("xch", "a,%s",
7725 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7727 aopPut (AOP (result), "a", LSB + offr);
7730 if (size >= MSB16 + offr)
7732 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7734 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7737 emitcode ("rlc", "a");
7738 if (sameRegs (AOP (left), AOP (result)) &&
7739 size >= MSB24 + offr && offr != LSB)
7740 emitcode ("xch", "a,%s",
7741 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7743 aopPut (AOP (result), "a", MSB16 + offr);
7746 if (size >= MSB24 + offr)
7748 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7750 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7753 emitcode ("rlc", "a");
7754 if (sameRegs (AOP (left), AOP (result)) &&
7755 size >= MSB32 + offr && offr != LSB)
7756 emitcode ("xch", "a,%s",
7757 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7759 aopPut (AOP (result), "a", MSB24 + offr);
7762 if (size > MSB32 + offr)
7764 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7766 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7769 emitcode ("rlc", "a");
7770 aopPut (AOP (result), "a", MSB32 + offr);
7773 aopPut (AOP (result), zero, LSB);
7779 /*-----------------------------------------------------------------*/
7780 /* genlshFour - shift four byte by a known amount != 0 */
7781 /*-----------------------------------------------------------------*/
7783 genlshFour (operand * result, operand * left, int shCount)
7787 D (emitcode (";", "genlshFour ");
7790 size = AOP_SIZE (result);
7792 /* if shifting more that 3 bytes */
7797 /* lowest order of left goes to the highest
7798 order of the destination */
7799 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7801 movLeft2Result (left, LSB, result, MSB32, 0);
7802 aopPut (AOP (result), zero, LSB);
7803 aopPut (AOP (result), zero, MSB16);
7804 aopPut (AOP (result), zero, MSB24);
7808 /* more than two bytes */
7809 else if (shCount >= 16)
7811 /* lower order two bytes goes to higher order two bytes */
7813 /* if some more remaining */
7815 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7818 movLeft2Result (left, MSB16, result, MSB32, 0);
7819 movLeft2Result (left, LSB, result, MSB24, 0);
7821 aopPut (AOP (result), zero, MSB16);
7822 aopPut (AOP (result), zero, LSB);
7826 /* if more than 1 byte */
7827 else if (shCount >= 8)
7829 /* lower order three bytes goes to higher order three bytes */
7834 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7836 movLeft2Result (left, LSB, result, MSB16, 0);
7842 movLeft2Result (left, MSB24, result, MSB32, 0);
7843 movLeft2Result (left, MSB16, result, MSB24, 0);
7844 movLeft2Result (left, LSB, result, MSB16, 0);
7845 aopPut (AOP (result), zero, LSB);
7847 else if (shCount == 1)
7848 shiftLLong (left, result, MSB16);
7851 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7852 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7853 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7854 aopPut (AOP (result), zero, LSB);
7859 /* 1 <= shCount <= 7 */
7860 else if (shCount <= 2)
7862 shiftLLong (left, result, LSB);
7864 shiftLLong (result, result, LSB);
7866 /* 3 <= shCount <= 7, optimize */
7869 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7870 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7871 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7876 #ifdef BETTER_LITERAL_SHIFT
7877 /*-----------------------------------------------------------------*/
7878 /* genLeftShiftLiteral - left shifting by known count */
7879 /*-----------------------------------------------------------------*/
7881 genLeftShiftLiteral (operand * left,
7886 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7889 size = getSize (operandType (result));
7891 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7893 /* We only handle certain easy cases so far. */
7895 && (shCount < (size * 8))
7899 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7903 freeAsmop (right, NULL, ic, TRUE);
7905 aopOp(left, ic, FALSE, FALSE);
7906 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7909 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7911 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7912 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7914 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7917 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7919 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7920 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7922 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7928 emitcode ("; shift left ", "result %d, left %d", size,
7932 /* I suppose that the left size >= result size */
7935 _startLazyDPSEvaluation();
7938 movLeft2Result (left, size, result, size, 0);
7940 _endLazyDPSEvaluation();
7942 else if (shCount >= (size * 8))
7944 _startLazyDPSEvaluation();
7947 aopPut (AOP (result), zero, size);
7949 _endLazyDPSEvaluation();
7956 genlshOne (result, left, shCount);
7960 genlshTwo (result, left, shCount);
7964 genlshFour (result, left, shCount);
7968 fprintf(stderr, "*** ack! mystery literal shift!\n");
7972 freeAsmop (left, NULL, ic, TRUE);
7973 freeAsmop (result, NULL, ic, TRUE);
7978 /*-----------------------------------------------------------------*/
7979 /* genLeftShift - generates code for left shifting */
7980 /*-----------------------------------------------------------------*/
7982 genLeftShift (iCode * ic)
7984 operand *left, *right, *result;
7987 symbol *tlbl, *tlbl1;
7989 D (emitcode (";", "genLeftShift "););
7991 right = IC_RIGHT (ic);
7992 left = IC_LEFT (ic);
7993 result = IC_RESULT (ic);
7995 aopOp (right, ic, FALSE, FALSE);
7998 #ifdef BETTER_LITERAL_SHIFT
7999 /* if the shift count is known then do it
8000 as efficiently as possible */
8001 if (AOP_TYPE (right) == AOP_LIT)
8003 if (genLeftShiftLiteral (left, right, result, ic))
8010 /* shift count is unknown then we have to form
8011 a loop get the loop count in B : Note: we take
8012 only the lower order byte since shifting
8013 more that 32 bits make no sense anyway, ( the
8014 largest size of an object can be only 32 bits ) */
8016 if (AOP_TYPE (right) == AOP_LIT)
8018 /* Really should be handled by genLeftShiftLiteral,
8019 * but since I'm too lazy to fix that today, at least we can make
8020 * some small improvement.
8022 emitcode("mov", "b,#!constbyte",
8023 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8027 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8028 emitcode ("inc", "b");
8030 freeAsmop (right, NULL, ic, TRUE);
8031 aopOp (left, ic, FALSE, FALSE);
8032 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8034 /* now move the left to the result if they are not the
8036 if (!sameRegs (AOP (left), AOP (result)) &&
8037 AOP_SIZE (result) > 1)
8040 size = AOP_SIZE (result);
8042 _startLazyDPSEvaluation ();
8045 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8046 if (*l == '@' && (IS_AOP_PREG (result)))
8049 emitcode ("mov", "a,%s", l);
8050 aopPut (AOP (result), "a", offset);
8053 aopPut (AOP (result), l, offset);
8056 _endLazyDPSEvaluation ();
8059 tlbl = newiTempLabel (NULL);
8060 size = AOP_SIZE (result);
8062 tlbl1 = newiTempLabel (NULL);
8064 /* if it is only one byte then */
8067 symbol *tlbl1 = newiTempLabel (NULL);
8069 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8071 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8072 emitcode ("", "!tlabeldef", tlbl->key + 100);
8073 emitcode ("add", "a,acc");
8074 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8075 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8076 aopPut (AOP (result), "a", 0);
8080 reAdjustPreg (AOP (result));
8082 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8083 emitcode ("", "!tlabeldef", tlbl->key + 100);
8084 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8086 emitcode ("add", "a,acc");
8087 aopPut (AOP (result), "a", offset++);
8088 _startLazyDPSEvaluation ();
8091 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8093 emitcode ("rlc", "a");
8094 aopPut (AOP (result), "a", offset++);
8096 _endLazyDPSEvaluation ();
8097 reAdjustPreg (AOP (result));
8099 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8100 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8102 freeAsmop (left, NULL, ic, TRUE);
8103 freeAsmop (result, NULL, ic, TRUE);
8106 #ifdef BETTER_LITERAL_SHIFT
8107 /*-----------------------------------------------------------------*/
8108 /* genrshOne - right shift a one byte quantity by known count */
8109 /*-----------------------------------------------------------------*/
8111 genrshOne (operand * result, operand * left,
8112 int shCount, int sign)
8114 D (emitcode (";", "genrshOne"););
8115 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8119 #ifdef BETTER_LITERAL_SHIFT
8120 /*-----------------------------------------------------------------*/
8121 /* genrshTwo - right shift two bytes by known amount != 0 */
8122 /*-----------------------------------------------------------------*/
8124 genrshTwo (operand * result, operand * left,
8125 int shCount, int sign)
8127 D (emitcode (";", "genrshTwo"););
8129 /* if shCount >= 8 */
8133 _startLazyDPSEvaluation();
8136 shiftR1Left2Result (left, MSB16, result, LSB,
8141 movLeft2Result (left, MSB16, result, LSB, sign);
8143 addSign (result, MSB16, sign);
8144 _endLazyDPSEvaluation();
8147 /* 1 <= shCount <= 7 */
8150 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8157 /*-----------------------------------------------------------------*/
8158 /* shiftRLong - shift right one long from left to result */
8159 /* offl = LSB or MSB16 */
8160 /*-----------------------------------------------------------------*/
8162 shiftRLong (operand * left, int offl,
8163 operand * result, int sign)
8165 int isSameRegs=sameRegs(AOP(left),AOP(result));
8167 if (isSameRegs && offl>1) {
8168 // we are in big trouble, but this shouldn't happen
8169 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8172 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
8177 emitcode ("rlc", "a");
8178 emitcode ("subb", "a,acc");
8179 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
8181 aopPut (AOP(result), zero, MSB32);
8186 emitcode ("clr", "c");
8188 emitcode ("mov", "c,acc.7");
8191 emitcode ("rrc", "a");
8193 if (isSameRegs && offl==MSB16) {
8194 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
8196 aopPut (AOP (result), "a", MSB32);
8197 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
8200 emitcode ("rrc", "a");
8201 if (isSameRegs && offl==1) {
8202 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
8204 aopPut (AOP (result), "a", MSB24);
8205 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
8207 emitcode ("rrc", "a");
8208 aopPut (AOP (result), "a", MSB16 - offl);
8212 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
8213 emitcode ("rrc", "a");
8214 aopPut (AOP (result), "a", LSB);
8221 /*-----------------------------------------------------------------*/
8222 /* genrshFour - shift four byte by a known amount != 0 */
8223 /*-----------------------------------------------------------------*/
8225 genrshFour (operand * result, operand * left,
8226 int shCount, int sign)
8228 D (emitcode (";", "genrshFour");
8231 /* if shifting more that 3 bytes */
8236 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8238 movLeft2Result (left, MSB32, result, LSB, sign);
8239 addSign (result, MSB16, sign);
8241 else if (shCount >= 16)
8245 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8248 movLeft2Result (left, MSB24, result, LSB, 0);
8249 movLeft2Result (left, MSB32, result, MSB16, sign);
8251 addSign (result, MSB24, sign);
8253 else if (shCount >= 8)
8257 shiftRLong (left, MSB16, result, sign);
8258 else if (shCount == 0)
8260 movLeft2Result (left, MSB16, result, LSB, 0);
8261 movLeft2Result (left, MSB24, result, MSB16, 0);
8262 movLeft2Result (left, MSB32, result, MSB24, sign);
8263 addSign (result, MSB32, sign);
8267 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8268 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8269 /* the last shift is signed */
8270 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8271 addSign (result, MSB32, sign);
8275 { /* 1 <= shCount <= 7 */
8278 shiftRLong (left, LSB, result, sign);
8280 shiftRLong (result, LSB, result, sign);
8284 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8285 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8286 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8292 #ifdef BETTER_LITERAL_SHIFT
8293 /*-----------------------------------------------------------------*/
8294 /* genRightShiftLiteral - right shifting by known count */
8295 /*-----------------------------------------------------------------*/
8297 genRightShiftLiteral (operand * left,
8303 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8306 size = getSize (operandType (result));
8308 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8310 /* We only handle certain easy cases so far. */
8312 && (shCount < (size * 8))
8316 D(emitcode (";", "genRightShiftLiteral wimping out"););
8320 freeAsmop (right, NULL, ic, TRUE);
8322 aopOp (left, ic, FALSE, FALSE);
8323 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8326 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8330 /* test the LEFT size !!! */
8332 /* I suppose that the left size >= result size */
8335 size = getDataSize (result);
8336 _startLazyDPSEvaluation();
8339 movLeft2Result (left, size, result, size, 0);
8341 _endLazyDPSEvaluation();
8343 else if (shCount >= (size * 8))
8347 /* get sign in acc.7 */
8348 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8350 addSign (result, LSB, sign);
8357 genrshOne (result, left, shCount, sign);
8361 genrshTwo (result, left, shCount, sign);
8365 genrshFour (result, left, shCount, sign);
8372 freeAsmop (left, NULL, ic, TRUE);
8373 freeAsmop (result, NULL, ic, TRUE);
8379 /*-----------------------------------------------------------------*/
8380 /* genSignedRightShift - right shift of signed number */
8381 /*-----------------------------------------------------------------*/
8383 genSignedRightShift (iCode * ic)
8385 operand *right, *left, *result;
8388 symbol *tlbl, *tlbl1;
8390 D (emitcode (";", "genSignedRightShift "););
8392 /* we do it the hard way put the shift count in b
8393 and loop thru preserving the sign */
8395 right = IC_RIGHT (ic);
8396 left = IC_LEFT (ic);
8397 result = IC_RESULT (ic);
8399 aopOp (right, ic, FALSE, FALSE);
8401 #ifdef BETTER_LITERAL_SHIFT
8402 if (AOP_TYPE (right) == AOP_LIT)
8404 if (genRightShiftLiteral (left, right, result, ic, 1))
8410 /* shift count is unknown then we have to form
8411 a loop get the loop count in B : Note: we take
8412 only the lower order byte since shifting
8413 more that 32 bits make no sense anyway, ( the
8414 largest size of an object can be only 32 bits ) */
8416 if (AOP_TYPE (right) == AOP_LIT)
8418 /* Really should be handled by genRightShiftLiteral,
8419 * but since I'm too lazy to fix that today, at least we can make
8420 * some small improvement.
8422 emitcode("mov", "b,#!constbyte",
8423 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8427 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8428 emitcode ("inc", "b");
8430 freeAsmop (right, NULL, ic, TRUE);
8431 aopOp (left, ic, FALSE, FALSE);
8432 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8434 /* now move the left to the result if they are not the
8436 if (!sameRegs (AOP (left), AOP (result)) &&
8437 AOP_SIZE (result) > 1)
8440 size = AOP_SIZE (result);
8442 _startLazyDPSEvaluation ();
8445 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8446 if (*l == '@' && IS_AOP_PREG (result))
8449 emitcode ("mov", "a,%s", l);
8450 aopPut (AOP (result), "a", offset);
8453 aopPut (AOP (result), l, offset);
8456 _endLazyDPSEvaluation ();
8459 /* mov the highest order bit to OVR */
8460 tlbl = newiTempLabel (NULL);
8461 tlbl1 = newiTempLabel (NULL);
8463 size = AOP_SIZE (result);
8465 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8466 emitcode ("rlc", "a");
8467 emitcode ("mov", "ov,c");
8468 /* if it is only one byte then */
8471 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8473 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8474 emitcode ("", "!tlabeldef", tlbl->key + 100);
8475 emitcode ("mov", "c,ov");
8476 emitcode ("rrc", "a");
8477 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8478 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8479 aopPut (AOP (result), "a", 0);
8483 reAdjustPreg (AOP (result));
8484 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8485 emitcode ("", "!tlabeldef", tlbl->key + 100);
8486 emitcode ("mov", "c,ov");
8487 _startLazyDPSEvaluation ();
8490 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8492 emitcode ("rrc", "a");
8493 aopPut (AOP (result), "a", offset--);
8495 _endLazyDPSEvaluation ();
8496 reAdjustPreg (AOP (result));
8497 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8498 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8501 freeAsmop (left, NULL, ic, TRUE);
8502 freeAsmop (result, NULL, ic, TRUE);
8505 /*-----------------------------------------------------------------*/
8506 /* genRightShift - generate code for right shifting */
8507 /*-----------------------------------------------------------------*/
8509 genRightShift (iCode * ic)
8511 operand *right, *left, *result;
8515 symbol *tlbl, *tlbl1;
8517 D (emitcode (";", "genRightShift "););
8519 /* if signed then we do it the hard way preserve the
8520 sign bit moving it inwards */
8521 retype = getSpec (operandType (IC_RESULT (ic)));
8523 if (!SPEC_USIGN (retype))
8525 genSignedRightShift (ic);
8529 /* signed & unsigned types are treated the same : i.e. the
8530 signed is NOT propagated inwards : quoting from the
8531 ANSI - standard : "for E1 >> E2, is equivalent to division
8532 by 2**E2 if unsigned or if it has a non-negative value,
8533 otherwise the result is implementation defined ", MY definition
8534 is that the sign does not get propagated */
8536 right = IC_RIGHT (ic);
8537 left = IC_LEFT (ic);
8538 result = IC_RESULT (ic);
8540 aopOp (right, ic, FALSE, FALSE);
8542 #ifdef BETTER_LITERAL_SHIFT
8543 /* if the shift count is known then do it
8544 as efficiently as possible */
8545 if (AOP_TYPE (right) == AOP_LIT)
8547 if (genRightShiftLiteral (left, right, result, ic, 0))
8554 /* shift count is unknown then we have to form
8555 a loop get the loop count in B : Note: we take
8556 only the lower order byte since shifting
8557 more that 32 bits make no sense anyway, ( the
8558 largest size of an object can be only 32 bits ) */
8560 if (AOP_TYPE (right) == AOP_LIT)
8562 /* Really should be handled by genRightShiftLiteral,
8563 * but since I'm too lazy to fix that today, at least we can make
8564 * some small improvement.
8566 emitcode("mov", "b,#!constbyte",
8567 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8571 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8572 emitcode ("inc", "b");
8574 freeAsmop (right, NULL, ic, TRUE);
8575 aopOp (left, ic, FALSE, FALSE);
8576 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8578 /* now move the left to the result if they are not the
8580 if (!sameRegs (AOP (left), AOP (result)) &&
8581 AOP_SIZE (result) > 1)
8584 size = AOP_SIZE (result);
8586 _startLazyDPSEvaluation ();
8589 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8590 if (*l == '@' && IS_AOP_PREG (result))
8593 emitcode ("mov", "a,%s", l);
8594 aopPut (AOP (result), "a", offset);
8597 aopPut (AOP (result), l, offset);
8600 _endLazyDPSEvaluation ();
8603 tlbl = newiTempLabel (NULL);
8604 tlbl1 = newiTempLabel (NULL);
8605 size = AOP_SIZE (result);
8608 /* if it is only one byte then */
8611 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8613 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8614 emitcode ("", "!tlabeldef", tlbl->key + 100);
8616 emitcode ("rrc", "a");
8617 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8618 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8619 aopPut (AOP (result), "a", 0);
8623 reAdjustPreg (AOP (result));
8624 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8625 emitcode ("", "!tlabeldef", tlbl->key + 100);
8627 _startLazyDPSEvaluation ();
8630 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8632 emitcode ("rrc", "a");
8633 aopPut (AOP (result), "a", offset--);
8635 _endLazyDPSEvaluation ();
8636 reAdjustPreg (AOP (result));
8638 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8639 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8642 freeAsmop (left, NULL, ic, TRUE);
8643 freeAsmop (result, NULL, ic, TRUE);
8646 /*-----------------------------------------------------------------*/
8647 /* genUnpackBits - generates code for unpacking bits */
8648 /*-----------------------------------------------------------------*/
8650 genUnpackBits (operand * result, char *rname, int ptype)
8657 D (emitcode (";", "genUnpackBits ");
8660 etype = getSpec (operandType (result));
8662 /* read the first byte */
8668 emitcode ("mov", "a,@%s", rname);
8672 emitcode ("movx", "a,@%s", rname);
8676 emitcode ("movx", "a,@dptr");
8680 emitcode ("clr", "a");
8681 emitcode ("movc", "a,@a+dptr");
8685 emitcode ("lcall", "__gptrget");
8689 /* if we have bitdisplacement then it fits */
8690 /* into this byte completely or if length is */
8691 /* less than a byte */
8692 if ((shCnt = SPEC_BSTR (etype)) ||
8693 (SPEC_BLEN (etype) <= 8))
8696 /* shift right acc */
8699 emitcode ("anl", "a,#!constbyte",
8700 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8701 aopPut (AOP (result), "a", offset);
8705 /* bit field did not fit in a byte */
8706 rlen = SPEC_BLEN (etype) - 8;
8707 aopPut (AOP (result), "a", offset++);
8716 emitcode ("inc", "%s", rname);
8717 emitcode ("mov", "a,@%s", rname);
8721 emitcode ("inc", "%s", rname);
8722 emitcode ("movx", "a,@%s", rname);
8726 emitcode ("inc", "dptr");
8727 emitcode ("movx", "a,@dptr");
8731 emitcode ("clr", "a");
8732 emitcode ("inc", "dptr");
8733 emitcode ("movc", "a,@a+dptr");
8737 emitcode ("inc", "dptr");
8738 emitcode ("lcall", "__gptrget");
8743 /* if we are done */
8747 aopPut (AOP (result), "a", offset++);
8753 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
8754 aopPut (AOP (result), "a", offset);
8761 /*-----------------------------------------------------------------*/
8762 /* genDataPointerGet - generates code when ptr offset is known */
8763 /*-----------------------------------------------------------------*/
8765 genDataPointerGet (operand * left,
8771 int size, offset = 0;
8772 aopOp (result, ic, TRUE, FALSE);
8774 /* get the string representation of the name */
8775 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8776 size = AOP_SIZE (result);
8777 _startLazyDPSEvaluation ();
8781 sprintf (buffer, "(%s + %d)", l + 1, offset);
8783 sprintf (buffer, "%s", l + 1);
8784 aopPut (AOP (result), buffer, offset++);
8786 _endLazyDPSEvaluation ();
8788 freeAsmop (left, NULL, ic, TRUE);
8789 freeAsmop (result, NULL, ic, TRUE);
8792 /*-----------------------------------------------------------------*/
8793 /* genNearPointerGet - emitcode for near pointer fetch */
8794 /*-----------------------------------------------------------------*/
8796 genNearPointerGet (operand * left,
8804 sym_link *rtype, *retype, *letype;
8805 sym_link *ltype = operandType (left);
8808 rtype = operandType (result);
8809 retype = getSpec (rtype);
8810 letype = getSpec (ltype);
8812 aopOp (left, ic, FALSE, FALSE);
8814 /* if left is rematerialisable and
8815 result is not bit variable type and
8816 the left is pointer to data space i.e
8817 lower 128 bytes of space */
8818 if (AOP_TYPE (left) == AOP_IMMD &&
8819 !IS_BITVAR (retype) &&
8820 !IS_BITVAR (letype) &&
8821 DCL_TYPE (ltype) == POINTER)
8823 genDataPointerGet (left, result, ic);
8827 /* if the value is already in a pointer register
8828 then don't need anything more */
8829 if (!AOP_INPREG (AOP (left)))
8831 /* otherwise get a free pointer register */
8833 preg = getFreePtr (ic, &aop, FALSE);
8834 emitcode ("mov", "%s,%s",
8836 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8840 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8842 freeAsmop (left, NULL, ic, TRUE);
8843 aopOp (result, ic, FALSE, FALSE);
8845 /* if bitfield then unpack the bits */
8846 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8847 genUnpackBits (result, rname, POINTER);
8850 /* we have can just get the values */
8851 int size = AOP_SIZE (result);
8856 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8859 emitcode ("mov", "a,@%s", rname);
8860 aopPut (AOP (result), "a", offset);
8864 sprintf (buffer, "@%s", rname);
8865 aopPut (AOP (result), buffer, offset);
8869 emitcode ("inc", "%s", rname);
8873 /* now some housekeeping stuff */
8876 /* we had to allocate for this iCode */
8877 if (pi) { /* post increment present */
8878 aopPut(AOP ( left ),rname,0);
8880 freeAsmop (NULL, aop, ic, TRUE);
8884 /* we did not allocate which means left
8885 already in a pointer register, then
8886 if size > 0 && this could be used again
8887 we have to point it back to where it
8889 if (AOP_SIZE (result) > 1 &&
8890 !OP_SYMBOL (left)->remat &&
8891 (OP_SYMBOL (left)->liveTo > ic->seq ||
8895 int size = AOP_SIZE (result) - 1;
8897 emitcode ("dec", "%s", rname);
8902 freeAsmop (result, NULL, ic, TRUE);
8903 if (pi) pi->generated = 1;
8906 /*-----------------------------------------------------------------*/
8907 /* genPagedPointerGet - emitcode for paged pointer fetch */
8908 /*-----------------------------------------------------------------*/
8910 genPagedPointerGet (operand * left,
8918 sym_link *rtype, *retype, *letype;
8920 rtype = operandType (result);
8921 retype = getSpec (rtype);
8922 letype = getSpec (operandType (left));
8923 aopOp (left, ic, FALSE, FALSE);
8925 /* if the value is already in a pointer register
8926 then don't need anything more */
8927 if (!AOP_INPREG (AOP (left)))
8929 /* otherwise get a free pointer register */
8931 preg = getFreePtr (ic, &aop, FALSE);
8932 emitcode ("mov", "%s,%s",
8934 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8938 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8940 freeAsmop (left, NULL, ic, TRUE);
8941 aopOp (result, ic, FALSE, FALSE);
8943 /* if bitfield then unpack the bits */
8944 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8945 genUnpackBits (result, rname, PPOINTER);
8948 /* we have can just get the values */
8949 int size = AOP_SIZE (result);
8955 emitcode ("movx", "a,@%s", rname);
8956 aopPut (AOP (result), "a", offset);
8961 emitcode ("inc", "%s", rname);
8965 /* now some housekeeping stuff */
8968 /* we had to allocate for this iCode */
8969 if (pi) aopPut ( AOP (left), rname, 0);
8970 freeAsmop (NULL, aop, ic, TRUE);
8974 /* we did not allocate which means left
8975 already in a pointer register, then
8976 if size > 0 && this could be used again
8977 we have to point it back to where it
8979 if (AOP_SIZE (result) > 1 &&
8980 !OP_SYMBOL (left)->remat &&
8981 (OP_SYMBOL (left)->liveTo > ic->seq ||
8985 int size = AOP_SIZE (result) - 1;
8987 emitcode ("dec", "%s", rname);
8992 freeAsmop (result, NULL, ic, TRUE);
8993 if (pi) pi->generated = 1;
8996 /*-----------------------------------------------------------------*/
8997 /* genFarPointerGet - gget value from far space */
8998 /*-----------------------------------------------------------------*/
9000 genFarPointerGet (operand * left,
9001 operand * result, iCode * ic, iCode *pi)
9003 int size, offset, dopi=1;
9004 sym_link *retype = getSpec (operandType (result));
9005 sym_link *letype = getSpec (operandType (left));
9006 D (emitcode (";", "genFarPointerGet");
9009 aopOp (left, ic, FALSE, FALSE);
9011 /* if the operand is already in dptr
9012 then we do nothing else we move the value to dptr */
9013 if (AOP_TYPE (left) != AOP_STR)
9015 /* if this is remateriazable */
9016 if (AOP_TYPE (left) == AOP_IMMD)
9018 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9022 /* we need to get it byte by byte */
9023 _startLazyDPSEvaluation ();
9024 if (AOP_TYPE (left) != AOP_DPTR)
9026 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9027 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9028 if (options.model == MODEL_FLAT24)
9029 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9033 /* We need to generate a load to DPTR indirect through DPTR. */
9034 D (emitcode (";", "genFarPointerGet -- indirection special case.");
9036 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9037 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9038 if (options.model == MODEL_FLAT24)
9039 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9040 emitcode ("pop", "dph");
9041 emitcode ("pop", "dpl");
9044 _endLazyDPSEvaluation ();
9047 /* so dptr know contains the address */
9048 aopOp (result, ic, FALSE, TRUE);
9050 /* if bit then unpack */
9051 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9052 genUnpackBits (result, "dptr", FPOINTER);
9055 size = AOP_SIZE (result);
9058 _startLazyDPSEvaluation ();
9065 emitcode ("movx", "a,@dptr");
9066 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9067 emitcode ("inc", "dptr");
9069 aopPut (AOP (result), "a", offset++);
9071 _endLazyDPSEvaluation ();
9073 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9074 aopPut ( AOP (left), "dpl", 0);
9075 aopPut ( AOP (left), "dph", 1);
9076 if (options.model == MODEL_FLAT24)
9077 aopPut ( AOP (left), "dpx", 2);
9079 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9080 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9082 size = AOP_SIZE (result) - 1;
9083 while (size--) emitcode ("lcall","__decdptr");
9086 freeAsmop (left, NULL, ic, TRUE);
9087 freeAsmop (result, NULL, ic, TRUE);
9090 /*-----------------------------------------------------------------*/
9091 /* emitcodePointerGet - gget value from code space */
9092 /*-----------------------------------------------------------------*/
9094 emitcodePointerGet (operand * left,
9095 operand * result, iCode * ic, iCode *pi)
9097 int size, offset, dopi=1;
9098 sym_link *retype = getSpec (operandType (result));
9100 aopOp (left, ic, FALSE, FALSE);
9102 /* if the operand is already in dptr
9103 then we do nothing else we move the value to dptr */
9104 if (AOP_TYPE (left) != AOP_STR)
9106 /* if this is remateriazable */
9107 if (AOP_TYPE (left) == AOP_IMMD)
9109 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9112 { /* we need to get it byte by byte */
9113 _startLazyDPSEvaluation ();
9114 if (AOP_TYPE (left) != AOP_DPTR)
9116 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9117 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9118 if (options.model == MODEL_FLAT24)
9119 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9123 /* We need to generate a load to DPTR indirect through DPTR. */
9124 D (emitcode (";", "gencodePointerGet -- indirection special case.");
9126 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9127 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9128 if (options.model == MODEL_FLAT24)
9129 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9130 emitcode ("pop", "dph");
9131 emitcode ("pop", "dpl");
9134 _endLazyDPSEvaluation ();
9137 /* so dptr know contains the address */
9138 aopOp (result, ic, FALSE, TRUE);
9140 /* if bit then unpack */
9141 if (IS_BITVAR (retype))
9142 genUnpackBits (result, "dptr", CPOINTER);
9145 size = AOP_SIZE (result);
9148 _startLazyDPSEvaluation ();
9154 emitcode ("clr", "a");
9155 emitcode ("movc", "a,@a+dptr");
9156 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9157 emitcode ("inc", "dptr");
9158 aopPut (AOP (result), "a", offset++);
9160 _endLazyDPSEvaluation ();
9162 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9163 aopPut ( AOP (left), "dpl", 0);
9164 aopPut ( AOP (left), "dph", 1);
9165 if (options.model == MODEL_FLAT24)
9166 aopPut ( AOP (left), "dpx", 2);
9168 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9169 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9171 size = AOP_SIZE (result) - 1;
9172 while (size--) emitcode ("lcall","__decdptr");
9175 freeAsmop (left, NULL, ic, TRUE);
9176 freeAsmop (result, NULL, ic, TRUE);
9179 /*-----------------------------------------------------------------*/
9180 /* genGenPointerGet - gget value from generic pointer space */
9181 /*-----------------------------------------------------------------*/
9183 genGenPointerGet (operand * left,
9184 operand * result, iCode * ic, iCode * pi)
9187 sym_link *retype = getSpec (operandType (result));
9188 sym_link *letype = getSpec (operandType (left));
9190 D (emitcode (";", "genGenPointerGet "); );
9192 aopOp (left, ic, FALSE, (OP_SYMBOL(left)->ruonly ? FALSE : TRUE));
9194 /* if the operand is already in dptr
9195 then we do nothing else we move the value to dptr */
9196 if (AOP_TYPE (left) != AOP_STR)
9198 /* if this is remateriazable */
9199 if (AOP_TYPE (left) == AOP_IMMD)
9201 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9202 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9203 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
9205 emitcode ("mov", "b,#%d", pointerCode (retype));
9208 { /* we need to get it byte by byte */
9209 _startLazyDPSEvaluation ();
9210 if (AOP(left)->type==AOP_DPTR2) {
9212 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
9215 emitcode ("mov", "dpl,%s", l);
9216 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
9219 emitcode ("mov", "dph,%s", l);
9220 if (options.model == MODEL_FLAT24) {
9221 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
9224 emitcode ("mov", "dpx,%s", l);
9225 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9227 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9230 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
9231 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
9232 if (options.model == MODEL_FLAT24) {
9233 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9234 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9236 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9239 _endLazyDPSEvaluation ();
9242 /* so dptr know contains the address */
9243 aopOp (result, ic, FALSE, TRUE);
9245 /* if bit then unpack */
9246 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9247 genUnpackBits (result, "dptr", GPOINTER);
9250 size = AOP_SIZE (result);
9255 emitcode ("lcall", "__gptrget");
9256 aopPut (AOP (result), "a", offset++);
9257 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9258 emitcode ("inc", "dptr");
9262 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9263 aopPut ( AOP (left), "dpl", 0);
9264 aopPut ( AOP (left), "dph", 1);
9265 if (options.model == MODEL_FLAT24) {
9266 aopPut ( AOP (left), "dpx", 2);
9267 aopPut ( AOP (left), "b", 3);
9268 } else aopPut ( AOP (left), "b", 2);
9270 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9271 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9273 size = AOP_SIZE (result) - 1;
9274 while (size--) emitcode ("lcall","__decdptr");
9277 freeAsmop (left, NULL, ic, TRUE);
9278 freeAsmop (result, NULL, ic, TRUE);
9281 /*-----------------------------------------------------------------*/
9282 /* genPointerGet - generate code for pointer get */
9283 /*-----------------------------------------------------------------*/
9285 genPointerGet (iCode * ic, iCode *pi)
9287 operand *left, *result;
9288 sym_link *type, *etype;
9291 D (emitcode (";", "genPointerGet ");
9294 left = IC_LEFT (ic);
9295 result = IC_RESULT (ic);
9297 /* depending on the type of pointer we need to
9298 move it to the correct pointer register */
9299 type = operandType (left);
9300 etype = getSpec (type);
9301 /* if left is of type of pointer then it is simple */
9302 if (IS_PTR (type) && !IS_FUNC (type->next))
9303 p_type = DCL_TYPE (type);
9306 /* we have to go by the storage class */
9307 p_type = PTR_TYPE (SPEC_OCLS (etype));
9309 /* special case when cast remat */
9310 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9311 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9312 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9313 type = type = operandType (left);
9314 p_type = DCL_TYPE (type);
9316 /* now that we have the pointer type we assign
9317 the pointer values */
9323 genNearPointerGet (left, result, ic, pi);
9327 genPagedPointerGet (left, result, ic, pi);
9331 genFarPointerGet (left, result, ic, pi);
9335 emitcodePointerGet (left, result, ic, pi);
9339 genGenPointerGet (left, result, ic, pi);
9345 /*-----------------------------------------------------------------*/
9346 /* genPackBits - generates code for packed bit storage */
9347 /*-----------------------------------------------------------------*/
9349 genPackBits (sym_link * etype,
9351 char *rname, int p_type)
9359 blen = SPEC_BLEN (etype);
9360 bstr = SPEC_BSTR (etype);
9362 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9365 /* if the bit lenth is less than or */
9366 /* it exactly fits a byte then */
9367 if (SPEC_BLEN (etype) <= 8)
9369 shCount = SPEC_BSTR (etype);
9371 /* shift left acc */
9374 if (SPEC_BLEN (etype) < 8)
9375 { /* if smaller than a byte */
9381 emitcode ("mov", "b,a");
9382 emitcode ("mov", "a,@%s", rname);
9386 emitcode ("mov", "b,a");
9387 emitcode ("movx", "a,@dptr");
9391 emitcode ("push", "b");
9392 emitcode ("push", "acc");
9393 emitcode ("lcall", "__gptrget");
9394 emitcode ("pop", "b");
9398 emitcode ("anl", "a,#!constbyte", (unsigned char)
9399 ((unsigned char) (0xFF << (blen + bstr)) |
9400 (unsigned char) (0xFF >> (8 - bstr))));
9401 emitcode ("orl", "a,b");
9402 if (p_type == GPOINTER)
9403 emitcode ("pop", "b");
9410 emitcode ("mov", "@%s,a", rname);
9414 emitcode ("movx", "@dptr,a");
9418 emitcode ("lcall", "__gptrput");
9423 if (SPEC_BLEN (etype) <= 8)
9426 emitcode ("inc", "%s", rname);
9427 rLen = SPEC_BLEN (etype);
9429 /* now generate for lengths greater than one byte */
9433 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9445 emitcode ("mov", "@%s,a", rname);
9448 emitcode ("mov", "@%s,%s", rname, l);
9453 emitcode ("movx", "@dptr,a");
9458 emitcode ("lcall", "__gptrput");
9461 emitcode ("inc", "%s", rname);
9466 /* last last was not complete */
9469 /* save the byte & read byte */
9473 emitcode ("mov", "b,a");
9474 emitcode ("mov", "a,@%s", rname);
9478 emitcode ("mov", "b,a");
9479 emitcode ("movx", "a,@dptr");
9483 emitcode ("push", "b");
9484 emitcode ("push", "acc");
9485 emitcode ("lcall", "__gptrget");
9486 emitcode ("pop", "b");
9490 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9491 emitcode ("orl", "a,b");
9494 if (p_type == GPOINTER)
9495 emitcode ("pop", "b");
9501 emitcode ("mov", "@%s,a", rname);
9505 emitcode ("movx", "@dptr,a");
9509 emitcode ("lcall", "__gptrput");
9513 /*-----------------------------------------------------------------*/
9514 /* genDataPointerSet - remat pointer to data space */
9515 /*-----------------------------------------------------------------*/
9517 genDataPointerSet (operand * right,
9521 int size, offset = 0;
9522 char *l, buffer[256];
9524 aopOp (right, ic, FALSE, FALSE);
9526 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9527 size = AOP_SIZE (right);
9531 sprintf (buffer, "(%s + %d)", l + 1, offset);
9533 sprintf (buffer, "%s", l + 1);
9534 emitcode ("mov", "%s,%s", buffer,
9535 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9538 freeAsmop (right, NULL, ic, TRUE);
9539 freeAsmop (result, NULL, ic, TRUE);
9542 /*-----------------------------------------------------------------*/
9543 /* genNearPointerSet - emitcode for near pointer put */
9544 /*-----------------------------------------------------------------*/
9546 genNearPointerSet (operand * right,
9554 sym_link *retype, *letype;
9555 sym_link *ptype = operandType (result);
9557 retype = getSpec (operandType (right));
9558 letype = getSpec (ptype);
9560 aopOp (result, ic, FALSE, FALSE);
9562 /* if the result is rematerializable &
9563 in data space & not a bit variable */
9564 if (AOP_TYPE (result) == AOP_IMMD &&
9565 DCL_TYPE (ptype) == POINTER &&
9566 !IS_BITVAR (retype) &&
9567 !IS_BITVAR (letype))
9569 genDataPointerSet (right, result, ic);
9573 /* if the value is already in a pointer register
9574 then don't need anything more */
9575 if (!AOP_INPREG (AOP (result)))
9577 /* otherwise get a free pointer register */
9579 preg = getFreePtr (ic, &aop, FALSE);
9580 emitcode ("mov", "%s,%s",
9582 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9586 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9588 aopOp (right, ic, FALSE, FALSE);
9590 /* if bitfield then unpack the bits */
9591 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9592 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9595 /* we have can just get the values */
9596 int size = AOP_SIZE (right);
9601 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9605 emitcode ("mov", "@%s,a", rname);
9608 emitcode ("mov", "@%s,%s", rname, l);
9610 emitcode ("inc", "%s", rname);
9615 /* now some housekeeping stuff */
9618 /* we had to allocate for this iCode */
9619 if (pi) aopPut (AOP (result),rname,0);
9620 freeAsmop (NULL, aop, ic, TRUE);
9624 /* we did not allocate which means left
9625 already in a pointer register, then
9626 if size > 0 && this could be used again
9627 we have to point it back to where it
9629 if (AOP_SIZE (right) > 1 &&
9630 !OP_SYMBOL (result)->remat &&
9631 (OP_SYMBOL (result)->liveTo > ic->seq ||
9635 int size = AOP_SIZE (right) - 1;
9637 emitcode ("dec", "%s", rname);
9642 if (pi) pi->generated = 1;
9643 freeAsmop (result, NULL, ic, TRUE);
9644 freeAsmop (right, NULL, ic, TRUE);
9649 /*-----------------------------------------------------------------*/
9650 /* genPagedPointerSet - emitcode for Paged pointer put */
9651 /*-----------------------------------------------------------------*/
9653 genPagedPointerSet (operand * right,
9661 sym_link *retype, *letype;
9663 retype = getSpec (operandType (right));
9664 letype = getSpec (operandType (result));
9666 aopOp (result, ic, FALSE, FALSE);
9668 /* if the value is already in a pointer register
9669 then don't need anything more */
9670 if (!AOP_INPREG (AOP (result)))
9672 /* otherwise get a free pointer register */
9674 preg = getFreePtr (ic, &aop, FALSE);
9675 emitcode ("mov", "%s,%s",
9677 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9681 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9683 aopOp (right, ic, FALSE, FALSE);
9685 /* if bitfield then unpack the bits */
9686 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9687 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9690 /* we have can just get the values */
9691 int size = AOP_SIZE (right);
9696 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9699 emitcode ("movx", "@%s,a", rname);
9702 emitcode ("inc", "%s", rname);
9708 /* now some housekeeping stuff */
9711 if (pi) aopPut (AOP (result),rname,0);
9712 /* we had to allocate for this iCode */
9713 freeAsmop (NULL, aop, ic, TRUE);
9717 /* we did not allocate which means left
9718 already in a pointer register, then
9719 if size > 0 && this could be used again
9720 we have to point it back to where it
9722 if (AOP_SIZE (right) > 1 &&
9723 !OP_SYMBOL (result)->remat &&
9724 (OP_SYMBOL (result)->liveTo > ic->seq ||
9728 int size = AOP_SIZE (right) - 1;
9730 emitcode ("dec", "%s", rname);
9735 if (pi) pi->generated = 1;
9736 freeAsmop (result, NULL, ic, TRUE);
9737 freeAsmop (right, NULL, ic, TRUE);
9742 /*-----------------------------------------------------------------*/
9743 /* genFarPointerSet - set value from far space */
9744 /*-----------------------------------------------------------------*/
9746 genFarPointerSet (operand * right,
9747 operand * result, iCode * ic, iCode *pi)
9749 int size, offset, dopi=1;
9750 sym_link *retype = getSpec (operandType (right));
9751 sym_link *letype = getSpec (operandType (result));
9753 aopOp (result, ic, FALSE, FALSE);
9755 /* if the operand is already in dptr
9756 then we do nothing else we move the value to dptr */
9757 if (AOP_TYPE (result) != AOP_STR)
9759 /* if this is remateriazable */
9760 if (AOP_TYPE (result) == AOP_IMMD)
9761 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9764 /* we need to get it byte by byte */
9765 _startLazyDPSEvaluation ();
9766 if (AOP_TYPE (result) != AOP_DPTR)
9768 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9769 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9770 if (options.model == MODEL_FLAT24)
9771 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9775 /* We need to generate a load to DPTR indirect through DPTR. */
9776 D (emitcode (";", "genFarPointerSet -- indirection special case.");
9778 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9779 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9780 if (options.model == MODEL_FLAT24)
9781 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9782 emitcode ("pop", "dph");
9783 emitcode ("pop", "dpl");
9786 _endLazyDPSEvaluation ();
9789 /* so dptr know contains the address */
9790 aopOp (right, ic, FALSE, TRUE);
9792 /* if bit then unpack */
9793 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9794 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9797 size = AOP_SIZE (right);
9800 _startLazyDPSEvaluation ();
9803 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9809 emitcode ("movx", "@dptr,a");
9810 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
9811 emitcode ("inc", "dptr");
9813 _endLazyDPSEvaluation ();
9816 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
9817 aopPut (AOP(result),"dpl",0);
9818 aopPut (AOP(result),"dph",1);
9819 if (options.model == MODEL_FLAT24)
9820 aopPut (AOP(result),"dpx",2);
9822 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9823 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9825 size = AOP_SIZE (right) - 1;
9826 while (size--) emitcode ("lcall","__decdptr");
9828 freeAsmop (result, NULL, ic, TRUE);
9829 freeAsmop (right, NULL, ic, TRUE);
9832 /*-----------------------------------------------------------------*/
9833 /* genGenPointerSet - set value from generic pointer space */
9834 /*-----------------------------------------------------------------*/
9836 genGenPointerSet (operand * right,
9837 operand * result, iCode * ic, iCode *pi)
9840 sym_link *retype = getSpec (operandType (right));
9841 sym_link *letype = getSpec (operandType (result));
9843 aopOp (result, ic, FALSE, OP_SYMBOL(result)->ruonly ? FALSE : TRUE);
9845 /* if the operand is already in dptr
9846 then we do nothing else we move the value to dptr */
9847 if (AOP_TYPE (result) != AOP_STR)
9849 _startLazyDPSEvaluation ();
9850 /* if this is remateriazable */
9851 if (AOP_TYPE (result) == AOP_IMMD)
9853 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9854 if (AOP(result)->aopu.aop_immd.from_cast_remat)
9855 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
9857 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9860 { /* we need to get it byte by byte */
9861 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9862 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9863 if (options.model == MODEL_FLAT24) {
9864 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9865 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9867 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9870 _endLazyDPSEvaluation ();
9872 /* so dptr know contains the address */
9873 aopOp (right, ic, FALSE, TRUE);
9875 /* if bit then unpack */
9876 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9877 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9880 size = AOP_SIZE (right);
9883 _startLazyDPSEvaluation ();
9886 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9892 emitcode ("lcall", "__gptrput");
9893 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
9894 emitcode ("inc", "dptr");
9896 _endLazyDPSEvaluation ();
9899 if (pi && AOP_TYPE (result) != AOP_IMMD) {
9900 aopPut (AOP(result),"dpl",0);
9901 aopPut (AOP(result),"dph",1);
9902 if (options.model == MODEL_FLAT24) {
9903 aopPut (AOP(result),"dpx",2);
9904 aopPut (AOP(result),"b",3);
9906 aopPut (AOP(result),"b",2);
9909 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9910 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9912 size = AOP_SIZE (right) - 1;
9913 while (size--) emitcode ("lcall","__decdptr");
9915 freeAsmop (result, NULL, ic, TRUE);
9916 freeAsmop (right, NULL, ic, TRUE);
9919 /*-----------------------------------------------------------------*/
9920 /* genPointerSet - stores the value into a pointer location */
9921 /*-----------------------------------------------------------------*/
9923 genPointerSet (iCode * ic, iCode *pi)
9925 operand *right, *result;
9926 sym_link *type, *etype;
9929 D (emitcode (";", "genPointerSet ");
9932 right = IC_RIGHT (ic);
9933 result = IC_RESULT (ic);
9935 /* depending on the type of pointer we need to
9936 move it to the correct pointer register */
9937 type = operandType (result);
9938 etype = getSpec (type);
9939 /* if left is of type of pointer then it is simple */
9940 if (IS_PTR (type) && !IS_FUNC (type->next))
9942 p_type = DCL_TYPE (type);
9946 /* we have to go by the storage class */
9947 p_type = PTR_TYPE (SPEC_OCLS (etype));
9949 /* special case when cast remat */
9950 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9951 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9952 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9953 type = type = operandType (result);
9954 p_type = DCL_TYPE (type);
9957 /* now that we have the pointer type we assign
9958 the pointer values */
9964 genNearPointerSet (right, result, ic, pi);
9968 genPagedPointerSet (right, result, ic, pi);
9972 genFarPointerSet (right, result, ic, pi);
9976 genGenPointerSet (right, result, ic, pi);
9982 /*-----------------------------------------------------------------*/
9983 /* genIfx - generate code for Ifx statement */
9984 /*-----------------------------------------------------------------*/
9986 genIfx (iCode * ic, iCode * popIc)
9988 operand *cond = IC_COND (ic);
9991 D (emitcode (";", "genIfx "););
9993 aopOp (cond, ic, FALSE, FALSE);
9995 /* get the value into acc */
9996 if (AOP_TYPE (cond) != AOP_CRY)
10000 /* the result is now in the accumulator */
10001 freeAsmop (cond, NULL, ic, TRUE);
10003 /* if there was something to be popped then do it */
10007 /* if the condition is a bit variable */
10008 if (isbit && IS_ITEMP (cond) &&
10010 genIfxJump (ic, SPIL_LOC (cond)->rname);
10011 else if (isbit && !IS_ITEMP (cond))
10012 genIfxJump (ic, OP_SYMBOL (cond)->rname);
10014 genIfxJump (ic, "a");
10019 /*-----------------------------------------------------------------*/
10020 /* genAddrOf - generates code for address of */
10021 /*-----------------------------------------------------------------*/
10023 genAddrOf (iCode * ic)
10025 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10028 D (emitcode (";", "genAddrOf ");
10031 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10033 /* if the operand is on the stack then we
10034 need to get the stack offset of this
10036 if (sym->onStack) {
10038 /* if 10 bit stack */
10039 if (options.stack10bit) {
10041 tsprintf(buff,"#!constbyte",(options.stack_loc >> 16) & 0xff);
10042 /* if it has an offset then we need to compute it */
10043 emitcode ("subb", "a,#!constbyte",
10044 -((sym->stack < 0) ?
10045 ((short) (sym->stack - _G.nRegsSaved)) :
10046 ((short) sym->stack)) & 0xff);
10047 emitcode ("mov","b,a");
10048 emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ?
10049 ((short) (sym->stack - _G.nRegsSaved)) :
10050 ((short) sym->stack)) >> 8) & 0xff);
10052 emitcode ("mov", "a,_bpx");
10053 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
10054 ((char) (sym->stack - _G.nRegsSaved)) :
10055 ((char) sym->stack )) & 0xff);
10056 emitcode ("mov", "b,a");
10057 emitcode ("mov", "a,_bpx+1");
10058 emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ?
10059 ((short) (sym->stack - _G.nRegsSaved)) :
10060 ((short) sym->stack )) >> 8) & 0xff);
10061 aopPut (AOP (IC_RESULT (ic)), "b", 0);
10062 aopPut (AOP (IC_RESULT (ic)), "a", 1);
10063 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10065 /* we can just move _bp */
10066 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10067 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10068 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10071 /* if it has an offset then we need to compute it */
10073 emitcode ("mov", "a,_bp");
10074 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10075 aopPut (AOP (IC_RESULT (ic)), "a", 0);
10077 /* we can just move _bp */
10078 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10080 /* fill the result with zero */
10081 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10084 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10086 "*** warning: pointer to stack var truncated.\n");
10091 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10097 /* object not on stack then we need the name */
10098 size = AOP_SIZE (IC_RESULT (ic));
10103 char s[SDCC_NAME_MAX];
10107 tsprintf(s,"!his",sym->rname);
10110 tsprintf(s,"!hihis",sym->rname);
10113 tsprintf(s,"!hihihis",sym->rname);
10115 default: /* should not need this (just in case) */
10116 sprintf (s, "#(%s >> %d)",
10121 sprintf (s, "#%s", sym->rname);
10122 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10126 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10130 /*-----------------------------------------------------------------*/
10131 /* genArrayInit - generates code for address of */
10132 /*-----------------------------------------------------------------*/
10134 genArrayInit (iCode * ic)
10136 literalList *iLoop;
10138 int elementSize = 0, eIndex;
10139 unsigned val, lastVal;
10141 operand *left=IC_LEFT(ic);
10143 D (emitcode (";", "genArrayInit "););
10145 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10147 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10149 // Load immediate value into DPTR.
10150 emitcode("mov", "dptr, %s",
10151 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
10153 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10156 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10157 "Unexpected operand to genArrayInit.\n");
10160 // a regression because of SDCCcse.c:1.52
10161 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
10162 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
10163 if (options.model == MODEL_FLAT24)
10164 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
10168 type = operandType(IC_LEFT(ic));
10170 if (type && type->next)
10172 elementSize = getSize(type->next);
10176 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10177 "can't determine element size in genArrayInit.\n");
10181 iLoop = IC_ARRAYILIST(ic);
10186 bool firstpass = TRUE;
10188 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10189 iLoop->count, (int)iLoop->literalValue, elementSize);
10195 symbol *tlbl = NULL;
10197 count = ix > 256 ? 256 : ix;
10201 tlbl = newiTempLabel (NULL);
10202 if (firstpass || (count & 0xff))
10204 emitcode("mov", "b, #!constbyte", count & 0xff);
10207 emitcode ("", "!tlabeldef", tlbl->key + 100);
10212 for (eIndex = 0; eIndex < elementSize; eIndex++)
10214 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10215 if (val != lastVal)
10217 emitcode("mov", "a, #!constbyte", val);
10221 emitcode("movx", "@dptr, a");
10222 emitcode("inc", "dptr");
10227 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10233 iLoop = iLoop->next;
10236 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10239 /*-----------------------------------------------------------------*/
10240 /* genFarFarAssign - assignment when both are in far space */
10241 /*-----------------------------------------------------------------*/
10243 genFarFarAssign (operand * result, operand * right, iCode * ic)
10245 int size = AOP_SIZE (right);
10247 symbol *rSym = NULL;
10251 /* quick & easy case. */
10252 D(emitcode(";","genFarFarAssign (1 byte case)"););
10253 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
10254 freeAsmop (right, NULL, ic, FALSE);
10255 /* now assign DPTR to result */
10257 aopOp(result, ic, FALSE, FALSE);
10259 aopPut(AOP(result), "a", 0);
10260 freeAsmop(result, NULL, ic, FALSE);
10264 /* See if we've got an underlying symbol to abuse. */
10265 if (IS_SYMOP(result) && OP_SYMBOL(result))
10267 if (IS_TRUE_SYMOP(result))
10269 rSym = OP_SYMBOL(result);
10271 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10273 rSym = OP_SYMBOL(result)->usl.spillLoc;
10277 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10279 /* We can use the '390 auto-toggle feature to good effect here. */
10281 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10282 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10283 emitcode ("mov", "dptr,#%s", rSym->rname);
10284 /* DP2 = result, DP1 = right, DP1 is current. */
10287 emitcode("movx", "a,@dptr");
10288 emitcode("movx", "@dptr,a");
10291 emitcode("inc", "dptr");
10292 emitcode("inc", "dptr");
10295 emitcode("mov", "dps,#0");
10296 freeAsmop (right, NULL, ic, FALSE);
10298 some alternative code for processors without auto-toggle
10299 no time to test now, so later well put in...kpb
10300 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10301 emitcode("mov", "dps,#1"); /* Select DPTR2. */
10302 emitcode ("mov", "dptr,#%s", rSym->rname);
10303 /* DP2 = result, DP1 = right, DP1 is current. */
10307 emitcode("movx", "a,@dptr");
10309 emitcode("inc", "dptr");
10310 emitcode("inc", "dps");
10311 emitcode("movx", "@dptr,a");
10313 emitcode("inc", "dptr");
10314 emitcode("inc", "dps");
10316 emitcode("mov", "dps,#0");
10317 freeAsmop (right, NULL, ic, FALSE);
10322 D (emitcode (";", "genFarFarAssign"););
10323 aopOp (result, ic, TRUE, TRUE);
10325 _startLazyDPSEvaluation ();
10329 aopPut (AOP (result),
10330 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10333 _endLazyDPSEvaluation ();
10334 freeAsmop (result, NULL, ic, FALSE);
10335 freeAsmop (right, NULL, ic, FALSE);
10339 /*-----------------------------------------------------------------*/
10340 /* genAssign - generate code for assignment */
10341 /*-----------------------------------------------------------------*/
10343 genAssign (iCode * ic)
10345 operand *result, *right;
10347 unsigned long lit = 0L;
10349 D (emitcode (";", "genAssign ");
10352 result = IC_RESULT (ic);
10353 right = IC_RIGHT (ic);
10355 /* if they are the same */
10356 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10359 aopOp (right, ic, FALSE, FALSE);
10361 emitcode (";", "genAssign: resultIsFar = %s",
10362 isOperandInFarSpace (result) ?
10365 /* special case both in far space */
10366 if ((AOP_TYPE (right) == AOP_DPTR ||
10367 AOP_TYPE (right) == AOP_DPTR2) &&
10368 /* IS_TRUE_SYMOP(result) && */
10369 isOperandInFarSpace (result))
10371 genFarFarAssign (result, right, ic);
10375 aopOp (result, ic, TRUE, FALSE);
10377 /* if they are the same registers */
10378 if (sameRegs (AOP (right), AOP (result)))
10381 /* if the result is a bit */
10382 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10384 /* if the right size is a literal then
10385 we know what the value is */
10386 if (AOP_TYPE (right) == AOP_LIT)
10388 if (((int) operandLitValue (right)))
10389 aopPut (AOP (result), one, 0);
10391 aopPut (AOP (result), zero, 0);
10395 /* the right is also a bit variable */
10396 if (AOP_TYPE (right) == AOP_CRY)
10398 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10399 aopPut (AOP (result), "c", 0);
10403 /* we need to or */
10405 aopPut (AOP (result), "a", 0);
10409 /* bit variables done */
10411 size = AOP_SIZE (result);
10413 if (AOP_TYPE (right) == AOP_LIT)
10414 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10417 (AOP_TYPE (result) != AOP_REG) &&
10418 (AOP_TYPE (right) == AOP_LIT) &&
10419 !IS_FLOAT (operandType (right)))
10421 _startLazyDPSEvaluation ();
10422 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10424 aopPut (AOP (result),
10425 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10430 /* And now fill the rest with zeros. */
10433 emitcode ("clr", "a");
10437 aopPut (AOP (result), "a", offset++);
10439 _endLazyDPSEvaluation ();
10443 _startLazyDPSEvaluation ();
10446 aopPut (AOP (result),
10447 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10451 _endLazyDPSEvaluation ();
10455 freeAsmop (right, NULL, ic, FALSE);
10456 freeAsmop (result, NULL, ic, TRUE);
10459 /*-----------------------------------------------------------------*/
10460 /* genJumpTab - generates code for jump table */
10461 /*-----------------------------------------------------------------*/
10463 genJumpTab (iCode * ic)
10468 D (emitcode (";", "genJumpTab ");
10471 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10472 /* get the condition into accumulator */
10473 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10475 /* multiply by four! */
10476 emitcode ("add", "a,acc");
10477 emitcode ("add", "a,acc");
10478 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10480 jtab = newiTempLabel (NULL);
10481 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10482 emitcode ("jmp", "@a+dptr");
10483 emitcode ("", "!tlabeldef", jtab->key + 100);
10484 /* now generate the jump labels */
10485 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10486 jtab = setNextItem (IC_JTLABELS (ic)))
10487 emitcode ("ljmp", "!tlabel", jtab->key + 100);
10491 /*-----------------------------------------------------------------*/
10492 /* genCast - gen code for casting */
10493 /*-----------------------------------------------------------------*/
10495 genCast (iCode * ic)
10497 operand *result = IC_RESULT (ic);
10498 sym_link *ctype = operandType (IC_LEFT (ic));
10499 sym_link *rtype = operandType (IC_RIGHT (ic));
10500 operand *right = IC_RIGHT (ic);
10503 D (emitcode (";", "genCast ");
10506 /* if they are equivalent then do nothing */
10507 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10510 aopOp (right, ic, FALSE, FALSE);
10511 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10513 /* if the result is a bit */
10514 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10515 if (IS_BITVAR(OP_SYMBOL(result)->type))
10517 /* if the right size is a literal then
10518 we know what the value is */
10519 if (AOP_TYPE (right) == AOP_LIT)
10521 if (((int) operandLitValue (right)))
10522 aopPut (AOP (result), one, 0);
10524 aopPut (AOP (result), zero, 0);
10529 /* the right is also a bit variable */
10530 if (AOP_TYPE (right) == AOP_CRY)
10532 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10533 aopPut (AOP (result), "c", 0);
10537 /* we need to or */
10539 aopPut (AOP (result), "a", 0);
10543 /* if they are the same size : or less */
10544 if (AOP_SIZE (result) <= AOP_SIZE (right))
10547 /* if they are in the same place */
10548 if (sameRegs (AOP (right), AOP (result)))
10551 /* if they in different places then copy */
10552 size = AOP_SIZE (result);
10554 _startLazyDPSEvaluation ();
10557 aopPut (AOP (result),
10558 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10562 _endLazyDPSEvaluation ();
10567 /* if the result is of type pointer */
10568 if (IS_PTR (ctype))
10572 sym_link *type = operandType (right);
10574 /* pointer to generic pointer */
10575 if (IS_GENPTR (ctype))
10581 p_type = DCL_TYPE (type);
10585 #if OLD_CAST_BEHAVIOR
10586 /* KV: we are converting a non-pointer type to
10587 * a generic pointer. This (ifdef'd out) code
10588 * says that the resulting generic pointer
10589 * should have the same class as the storage
10590 * location of the non-pointer variable.
10592 * For example, converting an int (which happens
10593 * to be stored in DATA space) to a pointer results
10594 * in a DATA generic pointer; if the original int
10595 * in XDATA space, so will be the resulting pointer.
10597 * I don't like that behavior, and thus this change:
10598 * all such conversions will be forced to XDATA and
10599 * throw a warning. If you want some non-XDATA
10600 * type, or you want to suppress the warning, you
10601 * must go through an intermediate cast, like so:
10603 * char _generic *gp = (char _xdata *)(intVar);
10605 sym_link *etype = getSpec (type);
10607 /* we have to go by the storage class */
10608 if (SPEC_OCLS (etype) != generic)
10610 p_type = PTR_TYPE (SPEC_OCLS (etype));
10615 /* Converting unknown class (i.e. register variable)
10616 * to generic pointer. This is not good, but
10617 * we'll make a guess (and throw a warning).
10620 werror (W_INT_TO_GEN_PTR_CAST);
10624 /* the first two bytes are known */
10625 size = GPTRSIZE - 1;
10627 _startLazyDPSEvaluation ();
10630 aopPut (AOP (result),
10631 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10635 _endLazyDPSEvaluation ();
10637 /* the last byte depending on type */
10655 /* this should never happen */
10656 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10657 "got unknown pointer type");
10660 aopPut (AOP (result), l, GPTRSIZE - 1);
10664 /* just copy the pointers */
10665 size = AOP_SIZE (result);
10667 _startLazyDPSEvaluation ();
10670 aopPut (AOP (result),
10671 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10675 _endLazyDPSEvaluation ();
10679 /* so we now know that the size of destination is greater
10680 than the size of the source */
10681 /* we move to result for the size of source */
10682 size = AOP_SIZE (right);
10684 _startLazyDPSEvaluation ();
10687 aopPut (AOP (result),
10688 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10692 _endLazyDPSEvaluation ();
10694 /* now depending on the sign of the source && destination */
10695 size = AOP_SIZE (result) - AOP_SIZE (right);
10696 /* if unsigned or not an integral type */
10697 /* also, if the source is a bit, we don't need to sign extend, because
10698 * it can't possibly have set the sign bit.
10700 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10704 aopPut (AOP (result), zero, offset++);
10709 /* we need to extend the sign :{ */
10710 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10711 FALSE, FALSE, TRUE);
10713 emitcode ("rlc", "a");
10714 emitcode ("subb", "a,acc");
10716 aopPut (AOP (result), "a", offset++);
10719 /* we are done hurray !!!! */
10722 freeAsmop (right, NULL, ic, TRUE);
10723 freeAsmop (result, NULL, ic, TRUE);
10727 /*-----------------------------------------------------------------*/
10728 /* genDjnz - generate decrement & jump if not zero instrucion */
10729 /*-----------------------------------------------------------------*/
10731 genDjnz (iCode * ic, iCode * ifx)
10733 symbol *lbl, *lbl1;
10737 /* if the if condition has a false label
10738 then we cannot save */
10739 if (IC_FALSE (ifx))
10742 /* if the minus is not of the form
10744 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10745 !IS_OP_LITERAL (IC_RIGHT (ic)))
10748 if (operandLitValue (IC_RIGHT (ic)) != 1)
10751 /* if the size of this greater than one then no
10753 if (getSize (operandType (IC_RESULT (ic))) > 1)
10756 /* otherwise we can save BIG */
10757 D(emitcode(";", "genDjnz"););
10759 lbl = newiTempLabel (NULL);
10760 lbl1 = newiTempLabel (NULL);
10762 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10764 if (AOP_NEEDSACC(IC_RESULT(ic)))
10766 /* If the result is accessed indirectly via
10767 * the accumulator, we must explicitly write
10768 * it back after the decrement.
10770 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10772 if (strcmp(rByte, "a"))
10774 /* Something is hopelessly wrong */
10775 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10776 __FILE__, __LINE__);
10777 /* We can just give up; the generated code will be inefficient,
10778 * but what the hey.
10780 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10783 emitcode ("dec", "%s", rByte);
10784 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10785 emitcode ("jnz", "!tlabel", lbl->key + 100);
10787 else if (IS_AOP_PREG (IC_RESULT (ic)))
10789 emitcode ("dec", "%s",
10790 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10791 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10792 emitcode ("jnz", "!tlabel", lbl->key + 100);
10796 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10799 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
10800 emitcode ("", "!tlabeldef", lbl->key + 100);
10801 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
10802 emitcode ("", "!tlabeldef", lbl1->key + 100);
10804 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10805 ifx->generated = 1;
10809 /*-----------------------------------------------------------------*/
10810 /* genReceive - generate code for a receive iCode */
10811 /*-----------------------------------------------------------------*/
10813 genReceive (iCode * ic)
10816 D (emitcode (";", "genReceive ");
10819 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10820 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10821 IS_TRUE_SYMOP (IC_RESULT (ic))))
10823 int size = getSize (operandType (IC_RESULT (ic)));
10824 int offset = fReturnSizeDS390 - size;
10827 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10828 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10831 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10832 size = AOP_SIZE (IC_RESULT (ic));
10836 emitcode ("pop", "acc");
10837 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10844 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10846 assignResultValue (IC_RESULT (ic));
10849 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10852 /*-----------------------------------------------------------------*/
10853 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
10854 /*-----------------------------------------------------------------*/
10855 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
10857 operand *from , *to , *count;
10862 /* we know it has to be 3 parameters */
10863 assert (nparms == 3);
10865 rsave = newBitVect(16);
10866 /* save DPTR if it needs to be saved */
10867 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
10868 if (bitVectBitValue(ic->rMask,i))
10869 rsave = bitVectSetBit(rsave,i);
10871 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
10872 ds390_rUmaskForOp (IC_RESULT(ic))));
10879 aopOp (from, ic->next, FALSE, FALSE);
10881 /* get from into DPTR1 */
10882 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
10883 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
10884 if (options.model == MODEL_FLAT24) {
10885 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
10888 freeAsmop (from, NULL, ic, FALSE);
10889 aopOp (to, ic, FALSE, FALSE);
10890 /* get "to" into DPTR */
10891 /* if the operand is already in dptr
10892 then we do nothing else we move the value to dptr */
10893 if (AOP_TYPE (to) != AOP_STR) {
10894 /* if already in DPTR then we need to push */
10895 if (AOP_TYPE(to) == AOP_DPTR) {
10896 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
10897 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
10898 if (options.model == MODEL_FLAT24)
10899 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10900 emitcode ("pop", "dph");
10901 emitcode ("pop", "dpl");
10903 _startLazyDPSEvaluation ();
10904 /* if this is remateriazable */
10905 if (AOP_TYPE (to) == AOP_IMMD) {
10906 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
10907 } else { /* we need to get it byte by byte */
10908 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
10909 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
10910 if (options.model == MODEL_FLAT24) {
10911 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10914 _endLazyDPSEvaluation ();
10917 freeAsmop (to, NULL, ic, FALSE);
10919 aopOp (count, ic->next->next, FALSE,FALSE);
10920 lbl =newiTempLabel(NULL);
10922 /* now for the actual copy */
10923 if (AOP_TYPE(count) == AOP_LIT &&
10924 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
10925 emitcode (";","OH JOY auto increment with djnz (very fast)");
10926 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10927 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
10928 emitcode ("","!tlabeldef",lbl->key+100);
10930 emitcode ("clr","a");
10931 emitcode ("movc", "a,@a+dptr");
10933 emitcode ("movx", "a,@dptr");
10934 emitcode ("movx", "@dptr,a");
10935 emitcode ("inc", "dptr");
10936 emitcode ("inc", "dptr");
10937 emitcode ("djnz","b,!tlabel",lbl->key+100);
10939 symbol *lbl1 = newiTempLabel(NULL);
10941 emitcode (";"," Auto increment but no djnz");
10942 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
10943 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
10944 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10945 emitcode ("","!tlabeldef",lbl->key+100);
10947 emitcode ("clr","a");
10948 emitcode ("movc", "a,@a+dptr");
10950 emitcode ("movx", "a,@dptr");
10951 emitcode ("movx", "@dptr,a");
10952 emitcode ("inc", "dptr");
10953 emitcode ("inc", "dptr");
10954 emitcode ("mov","a,b");
10955 emitcode ("orl","a,_ap");
10956 emitcode ("jz","!tlabel",lbl1->key+100);
10957 emitcode ("mov","a,_ap");
10958 emitcode ("add","a,#!constbyte",0xFF);
10959 emitcode ("mov","_ap,a");
10960 emitcode ("mov","a,b");
10961 emitcode ("addc","a,#!constbyte",0xFF);
10962 emitcode ("mov","b,a");
10963 emitcode ("sjmp","!tlabel",lbl->key+100);
10964 emitcode ("","!tlabeldef",lbl1->key+100);
10966 emitcode ("mov", "dps,#0");
10967 freeAsmop (count, NULL, ic, FALSE);
10968 unsavermask(rsave);
10972 /*-----------------------------------------------------------------*/
10973 /* genMemsetX - gencode for memSetX data */
10974 /*-----------------------------------------------------------------*/
10975 static void genMemsetX(iCode *ic, int nparms, operand **parms)
10977 operand *to , *val , *count;
10981 bitVect *rsave = NULL;
10983 /* we know it has to be 3 parameters */
10984 assert (nparms == 3);
10990 /* save DPTR if it needs to be saved */
10991 rsave = newBitVect(16);
10992 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
10993 if (bitVectBitValue(ic->rMask,i))
10994 rsave = bitVectSetBit(rsave,i);
10996 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
10997 ds390_rUmaskForOp (IC_RESULT(ic))));
11000 aopOp (to, ic, FALSE, FALSE);
11001 /* get "to" into DPTR */
11002 /* if the operand is already in dptr
11003 then we do nothing else we move the value to dptr */
11004 if (AOP_TYPE (to) != AOP_STR) {
11005 /* if already in DPTR then we need to push */
11006 if (AOP_TYPE(to) == AOP_DPTR) {
11007 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11008 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11009 if (options.model == MODEL_FLAT24)
11010 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11011 emitcode ("pop", "dph");
11012 emitcode ("pop", "dpl");
11014 _startLazyDPSEvaluation ();
11015 /* if this is remateriazable */
11016 if (AOP_TYPE (to) == AOP_IMMD) {
11017 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11018 } else { /* we need to get it byte by byte */
11019 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11020 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11021 if (options.model == MODEL_FLAT24) {
11022 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11025 _endLazyDPSEvaluation ();
11028 freeAsmop (to, NULL, ic, FALSE);
11030 aopOp (val, ic->next->next, FALSE,FALSE);
11031 aopOp (count, ic->next->next, FALSE,FALSE);
11032 lbl =newiTempLabel(NULL);
11033 /* now for the actual copy */
11034 if (AOP_TYPE(count) == AOP_LIT &&
11035 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11036 l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11037 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11039 emitcode ("","!tlabeldef",lbl->key+100);
11040 emitcode ("movx", "@dptr,a");
11041 emitcode ("inc", "dptr");
11042 emitcode ("djnz","b,!tlabel",lbl->key+100);
11044 symbol *lbl1 = newiTempLabel(NULL);
11046 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11047 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11048 emitcode ("","!tlabeldef",lbl->key+100);
11049 l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11051 emitcode ("movx", "a,@dptr");
11052 emitcode ("inc", "dptr");
11053 emitcode ("mov","a,b");
11054 emitcode ("orl","a,_ap");
11055 emitcode ("jz","!tlabel",lbl1->key+100);
11056 emitcode ("mov","a,_ap");
11057 emitcode ("add","a,#!constbyte",0xFF);
11058 emitcode ("mov","_ap,a");
11059 emitcode ("mov","a,b");
11060 emitcode ("addc","a,#!constbyte",0xFF);
11061 emitcode ("mov","b,a");
11062 emitcode ("sjmp","!tlabel",lbl->key+100);
11063 emitcode ("","!tlabeldef",lbl1->key+100);
11065 freeAsmop (count, NULL, ic, FALSE);
11066 unsavermask(rsave);
11069 /*-----------------------------------------------------------------*/
11070 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11071 /*-----------------------------------------------------------------*/
11072 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11075 operand *pnum, *result;
11078 assert (nparms==1);
11079 /* save registers that need to be saved */
11080 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11081 ds390_rUmaskForOp (IC_RESULT(ic))));
11084 aopOp (pnum, ic, FALSE, FALSE);
11085 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11086 freeAsmop (pnum, NULL, ic, FALSE);
11087 emitcode ("lcall","NatLib_LoadPrimitive");
11088 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11089 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
11090 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11091 for (i = (size-1) ; i >= 0 ; i-- ) {
11092 emitcode ("push","a%s",javaRet[i]);
11094 for (i=0; i < size ; i++ ) {
11095 emitcode ("pop","a%s",aopGet(AOP(result),i,FALSE,FALSE,FALSE));
11098 for (i = 0 ; i < size ; i++ ) {
11099 aopPut(AOP(result),javaRet[i],i);
11102 freeAsmop (result, NULL, ic, FALSE);
11103 unsavermask(rsave);
11106 /*-----------------------------------------------------------------*/
11107 /* genNatLibLoadPointer - calls TINI api function to load pointer */
11108 /*-----------------------------------------------------------------*/
11109 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11112 operand *pnum, *result;
11116 assert (nparms==1);
11117 /* save registers that need to be saved */
11118 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11119 ds390_rUmaskForOp (IC_RESULT(ic))));
11122 aopOp (pnum, ic, FALSE, FALSE);
11123 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11124 freeAsmop (pnum, NULL, ic, FALSE);
11125 emitcode ("lcall","NatLib_LoadPointer");
11126 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11127 if (AOP_TYPE(result)!=AOP_STR) {
11128 for (i = 0 ; i < size ; i++ ) {
11129 aopPut(AOP(result),fReturn[i],i);
11132 freeAsmop (result, NULL, ic, FALSE);
11133 unsavermask(rsave);
11136 /*-----------------------------------------------------------------*/
11137 /* genNatLibInstallStateBlock - */
11138 /*-----------------------------------------------------------------*/
11139 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
11140 operand **parms, const char *name)
11143 operand *psb, *handle;
11144 assert (nparms==2);
11146 /* save registers that need to be saved */
11147 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11148 ds390_rUmaskForOp (IC_RESULT(ic))));
11152 /* put pointer to state block into DPTR1 */
11153 aopOp (psb, ic, FALSE, FALSE);
11154 if (AOP_TYPE (psb) == AOP_IMMD) {
11155 emitcode ("mov","dps,#1");
11156 emitcode ("mov", "dptr,%s", aopGet (AOP (psb), 0, TRUE, FALSE, FALSE));
11157 emitcode ("mov","dps,#0");
11159 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,FALSE));
11160 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,FALSE));
11161 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,FALSE));
11163 freeAsmop (psb, NULL, ic, FALSE);
11165 /* put libraryID into DPTR */
11166 emitcode ("mov","dptr,#LibraryID");
11168 /* put handle into r3:r2 */
11169 aopOp (handle, ic, FALSE, FALSE);
11170 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11171 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11172 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11173 emitcode ("pop","ar3");
11174 emitcode ("pop","ar2");
11176 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11177 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11179 freeAsmop (psb, NULL, ic, FALSE);
11181 /* make the call */
11182 emitcode ("lcall","NatLib_Install%sStateBlock",name);
11184 /* put return value into place*/
11186 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
11188 aopPut(AOP(IC_RESULT(ic)),"a",0);
11189 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11190 unsavermask(rsave);
11193 /*-----------------------------------------------------------------*/
11194 /* genNatLibRemoveStateBlock - */
11195 /*-----------------------------------------------------------------*/
11196 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
11202 /* save registers that need to be saved */
11203 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11204 ds390_rUmaskForOp (IC_RESULT(ic))));
11206 /* put libraryID into DPTR */
11207 emitcode ("mov","dptr,#LibraryID");
11208 /* make the call */
11209 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11210 unsavermask(rsave);
11213 /*-----------------------------------------------------------------*/
11214 /* genNatLibGetStateBlock - */
11215 /*-----------------------------------------------------------------*/
11216 static void genNatLibGetStateBlock(iCode *ic,int nparms,
11217 operand **parms,const char *name)
11220 symbol *lbl = newiTempLabel(NULL);
11223 /* save registers that need to be saved */
11224 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11225 ds390_rUmaskForOp (IC_RESULT(ic))));
11227 /* put libraryID into DPTR */
11228 emitcode ("mov","dptr,#LibraryID");
11229 /* make the call */
11230 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11231 emitcode ("jnz","!tlabel",lbl->key+100);
11233 /* put return value into place */
11234 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11235 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11236 emitcode ("push","ar3");
11237 emitcode ("push","ar2");
11238 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11239 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11241 aopPut(AOP(IC_RESULT(ic)),"r2",0);
11242 aopPut(AOP(IC_RESULT(ic)),"r3",1);
11244 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11245 emitcode ("","!tlabeldef",lbl->key+100);
11246 unsavermask(rsave);
11249 /*-----------------------------------------------------------------*/
11250 /* genMMMalloc - */
11251 /*-----------------------------------------------------------------*/
11252 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
11253 int size, const char *name)
11258 symbol *lbl = newiTempLabel(NULL);
11260 assert (nparms == 1);
11261 /* save registers that need to be saved */
11262 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11263 ds390_rUmaskForOp (IC_RESULT(ic))));
11266 aopOp (bsize,ic,FALSE,FALSE);
11268 /* put the size in R4-R2 */
11269 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
11270 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
11271 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
11273 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
11274 emitcode("pop","ar4");
11276 emitcode("pop","ar3");
11277 emitcode("pop","ar2");
11279 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
11280 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
11282 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
11285 freeAsmop (bsize, NULL, ic, FALSE);
11287 /* make the call */
11288 emitcode ("lcall","MM_%s",name);
11289 emitcode ("jz","!tlabel",lbl->key+100);
11290 emitcode ("mov","r2,#!constbyte",0xff);
11291 emitcode ("mov","r3,#!constbyte",0xff);
11292 emitcode ("","!tlabeldef",lbl->key+100);
11293 /* we don't care about the pointer : we just save the handle */
11294 rsym = OP_SYMBOL(IC_RESULT(ic));
11295 if (rsym->liveFrom != rsym->liveTo) {
11296 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11297 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11298 emitcode ("push","ar3");
11299 emitcode ("push","ar2");
11300 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11301 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11303 aopPut(AOP(IC_RESULT(ic)),"r2",0);
11304 aopPut(AOP(IC_RESULT(ic)),"r3",1);
11306 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11308 unsavermask(rsave);
11311 /*-----------------------------------------------------------------*/
11313 /*-----------------------------------------------------------------*/
11314 static void genMMDeref (iCode *ic,int nparms, operand **parms)
11319 assert (nparms == 1);
11320 /* save registers that need to be saved */
11321 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11322 ds390_rUmaskForOp (IC_RESULT(ic))));
11325 aopOp (handle,ic,FALSE,FALSE);
11327 /* put the size in R4-R2 */
11328 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11329 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11330 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11331 emitcode("pop","ar3");
11332 emitcode("pop","ar2");
11334 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11335 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11337 freeAsmop (handle, NULL, ic, FALSE);
11339 /* make the call */
11340 emitcode ("lcall","MM_Deref");
11343 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11344 if (rsym->liveFrom != rsym->liveTo) {
11345 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11346 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
11347 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
11348 aopPut(AOP(IC_RESULT(ic)),"dph",1);
11349 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
11353 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11354 unsavermask(rsave);
11357 /*-----------------------------------------------------------------*/
11358 /* genMMUnrestrictedPersist - */
11359 /*-----------------------------------------------------------------*/
11360 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
11365 assert (nparms == 1);
11366 /* save registers that need to be saved */
11367 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11368 ds390_rUmaskForOp (IC_RESULT(ic))));
11371 aopOp (handle,ic,FALSE,FALSE);
11373 /* put the size in R3-R2 */
11374 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11375 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11376 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11377 emitcode("pop","ar3");
11378 emitcode("pop","ar2");
11380 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11381 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11383 freeAsmop (handle, NULL, ic, FALSE);
11385 /* make the call */
11386 emitcode ("lcall","MM_UnrestrictedPersist");
11389 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11390 if (rsym->liveFrom != rsym->liveTo) {
11391 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11392 aopPut(AOP(IC_RESULT(ic)),"a",0);
11393 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11396 unsavermask(rsave);
11399 /*-----------------------------------------------------------------*/
11400 /* genSystemExecJavaProcess - */
11401 /*-----------------------------------------------------------------*/
11402 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
11405 operand *handle, *pp;
11407 assert (nparms==2);
11408 /* save registers that need to be saved */
11409 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11410 ds390_rUmaskForOp (IC_RESULT(ic))));
11415 /* put the handle in R3-R2 */
11416 aopOp (handle,ic,FALSE,FALSE);
11417 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11418 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11419 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11420 emitcode("pop","ar3");
11421 emitcode("pop","ar2");
11423 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11424 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11426 freeAsmop (handle, NULL, ic, FALSE);
11428 /* put pointer in DPTR */
11429 aopOp (pp,ic,FALSE,FALSE);
11430 if (AOP_TYPE(pp) == AOP_IMMD) {
11431 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));
11432 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
11433 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
11434 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
11435 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
11437 freeAsmop (handle, NULL, ic, FALSE);
11439 /* make the call */
11440 emitcode ("lcall","System_ExecJavaProcess");
11442 /* put result in place */
11444 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11445 if (rsym->liveFrom != rsym->liveTo) {
11446 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11447 aopPut(AOP(IC_RESULT(ic)),"a",0);
11448 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11452 unsavermask(rsave);
11455 /*-----------------------------------------------------------------*/
11456 /* genSystemRTCRegisters - */
11457 /*-----------------------------------------------------------------*/
11458 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
11464 assert (nparms==1);
11465 /* save registers that need to be saved */
11466 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11467 ds390_rUmaskForOp (IC_RESULT(ic))));
11470 /* put pointer in DPTR */
11471 aopOp (pp,ic,FALSE,FALSE);
11472 if (AOP_TYPE (pp) == AOP_IMMD) {
11473 emitcode ("mov","dps,#1");
11474 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));
11475 emitcode ("mov","dps,#0");
11477 emitcode ("mov","dpl1,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
11478 emitcode ("mov","dph1,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
11479 emitcode ("mov","dpx1,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
11481 freeAsmop (pp, NULL, ic, FALSE);
11483 /* make the call */
11484 emitcode ("lcall","System_%sRTCRegisters",name);
11486 unsavermask(rsave);
11489 /*-----------------------------------------------------------------*/
11490 /* genSystemThreadSleep - */
11491 /*-----------------------------------------------------------------*/
11492 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
11497 assert (nparms==1);
11498 /* save registers that need to be saved */
11499 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11500 ds390_rUmaskForOp (IC_RESULT(ic))));
11503 aopOp(to,ic,FALSE,FALSE);
11504 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
11505 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
11506 emitcode ("push","%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
11507 emitcode ("push","%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
11508 emitcode ("push","%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
11509 emitcode ("push","%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
11510 emitcode ("pop","ar3");
11511 emitcode ("pop","ar2");
11512 emitcode ("pop","ar1");
11513 emitcode ("pop","ar0");
11515 emitcode ("mov","r0,%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
11516 emitcode ("mov","r1,%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
11517 emitcode ("mov","r2,%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
11518 emitcode ("mov","r3,%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
11520 freeAsmop (to, NULL, ic, FALSE);
11522 /* suspend in acc */
11524 aopOp(s,ic,FALSE,FALSE);
11525 emitcode ("mov","a,%s",aopGet(AOP(s),0,FALSE,TRUE,FALSE));
11526 freeAsmop (s, NULL, ic, FALSE);
11528 /* make the call */
11529 emitcode ("lcall","System_%s",name);
11531 unsavermask(rsave);
11534 /*-----------------------------------------------------------------*/
11535 /* genSystemThreadResume - */
11536 /*-----------------------------------------------------------------*/
11537 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
11542 assert (nparms==2);
11543 /* save registers that need to be saved */
11544 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11545 ds390_rUmaskForOp (IC_RESULT(ic))));
11551 aopOp(pid,ic,FALSE,FALSE);
11552 emitcode ("mov","r0,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
11553 freeAsmop (pid, NULL, ic, FALSE);
11556 aopOp(tid,ic,FALSE,FALSE);
11557 emitcode ("mov","a,%s",aopGet(AOP(tid),0,FALSE,TRUE,FALSE));
11558 freeAsmop (tid, NULL, ic, FALSE);
11560 emitcode ("lcall","System_ThreadResume");
11562 /* put result into place */
11564 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11565 if (rsym->liveFrom != rsym->liveTo) {
11566 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11567 aopPut(AOP(IC_RESULT(ic)),"a",0);
11568 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11571 unsavermask(rsave);
11574 /*-----------------------------------------------------------------*/
11575 /* genSystemProcessResume - */
11576 /*-----------------------------------------------------------------*/
11577 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
11582 assert (nparms==1);
11583 /* save registers that need to be saved */
11584 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11585 ds390_rUmaskForOp (IC_RESULT(ic))));
11590 aopOp(pid,ic,FALSE,FALSE);
11591 emitcode ("mov","a,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
11592 freeAsmop (pid, NULL, ic, FALSE);
11594 emitcode ("lcall","System_ProcessResume");
11596 unsavermask(rsave);
11599 /*-----------------------------------------------------------------*/
11601 /*-----------------------------------------------------------------*/
11602 static void genSystem (iCode *ic,int nparms,char *name)
11604 assert(nparms == 0);
11606 emitcode ("lcall","System_%s",name);
11609 /*-----------------------------------------------------------------*/
11610 /* genSystemPoll - */
11611 /*-----------------------------------------------------------------*/
11612 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
11617 assert (nparms==1);
11618 /* save registers that need to be saved */
11619 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11620 ds390_rUmaskForOp (IC_RESULT(ic))));
11623 aopOp (fp,ic,FALSE,FALSE);
11624 if (AOP_TYPE (fp) == AOP_IMMD) {
11625 emitcode ("mov", "dptr,%s", aopGet (AOP (fp), 0, TRUE, FALSE, FALSE));
11626 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
11627 emitcode ("mov","dpl,%s",aopGet(AOP(fp),0,FALSE,FALSE,FALSE));
11628 emitcode ("mov","dph,%s",aopGet(AOP(fp),1,FALSE,FALSE,FALSE));
11629 emitcode ("mov","dpx,%s",aopGet(AOP(fp),2,FALSE,FALSE,FALSE));
11631 freeAsmop (fp, NULL, ic, FALSE);
11633 emitcode ("lcall","System_%sPoll",name);
11635 /* put result into place */
11637 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11638 if (rsym->liveFrom != rsym->liveTo) {
11639 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11640 aopPut(AOP(IC_RESULT(ic)),"a",0);
11641 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11644 unsavermask(rsave);
11647 /*-----------------------------------------------------------------*/
11648 /* genSystemGetCurrentID - */
11649 /*-----------------------------------------------------------------*/
11650 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
11652 assert (nparms==0);
11654 emitcode ("lcall","System_GetCurrent%sId",name);
11655 /* put result into place */
11657 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11658 if (rsym->liveFrom != rsym->liveTo) {
11659 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11660 aopPut(AOP(IC_RESULT(ic)),"a",0);
11661 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11666 /*-----------------------------------------------------------------*/
11667 /* genBuiltIn - calls the appropriate function to generating code */
11668 /* for a built in function */
11669 /*-----------------------------------------------------------------*/
11670 static void genBuiltIn (iCode *ic)
11672 operand *bi_parms[MAX_BUILTIN_ARGS];
11677 /* get all the arguments for a built in function */
11678 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
11680 /* which function is it */
11681 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
11682 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
11683 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
11684 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
11685 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
11686 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
11687 genMemsetX(bi_iCode,nbi_parms,bi_parms);
11688 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
11689 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
11690 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
11691 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
11692 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
11693 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
11694 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
11695 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
11696 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
11697 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
11698 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
11699 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
11700 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
11701 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
11702 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
11703 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
11704 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
11705 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
11706 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
11707 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
11708 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
11709 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
11710 } else if (strcmp(bif->name,"MM_Malloc")==0) {
11711 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
11712 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
11713 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
11714 } else if (strcmp(bif->name,"MM_Free")==0) {
11715 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
11716 } else if (strcmp(bif->name,"MM_Deref")==0) {
11717 genMMDeref(bi_iCode,nbi_parms,bi_parms);
11718 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
11719 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
11720 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
11721 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
11722 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
11723 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
11724 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
11725 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
11726 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
11727 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
11728 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
11729 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
11730 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
11731 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
11732 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
11733 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
11734 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
11735 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
11736 } else if (strcmp(bif->name,"System_SaveThread")==0) {
11737 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
11738 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
11739 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
11740 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
11741 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
11742 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
11743 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
11744 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
11745 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
11746 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
11747 genSystem(bi_iCode,nbi_parms,"ProcessYield");
11748 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
11749 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
11750 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
11751 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
11752 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
11753 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
11754 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
11755 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
11756 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
11757 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
11759 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
11765 /*-----------------------------------------------------------------*/
11766 /* gen390Code - generate code for Dallas 390 based controllers */
11767 /*-----------------------------------------------------------------*/
11769 gen390Code (iCode * lic)
11774 lineHead = lineCurr = NULL;
11776 if (options.model == MODEL_FLAT24) {
11777 fReturnSizeDS390 = 5;
11778 fReturn = fReturn24;
11780 fReturnSizeDS390 = 4;
11781 fReturn = fReturn16;
11782 options.stack10bit=0;
11785 /* print the allocation information */
11787 printAllocInfo (currFunc, codeOutFile);
11789 /* if debug information required */
11790 if (options.debug && currFunc)
11792 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
11794 if (IS_STATIC (currFunc->etype))
11795 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
11797 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
11800 /* stack pointer name */
11801 if (options.useXstack)
11807 for (ic = lic; ic; ic = ic->next)
11810 if (cln != ic->lineno)
11815 emitcode ("", "C$%s$%d$%d$%d ==.",
11816 FileBaseName (ic->filename), ic->lineno,
11817 ic->level, ic->block);
11820 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
11821 printCLine(ic->filename, ic->lineno));
11824 /* if the result is marked as
11825 spilt and rematerializable or code for
11826 this has already been generated then
11828 if (resultRemat (ic) || ic->generated)
11831 /* depending on the operation */
11851 /* IPOP happens only when trying to restore a
11852 spilt live range, if there is an ifx statement
11853 following this pop then the if statement might
11854 be using some of the registers being popped which
11855 would destory the contents of the register so
11856 we need to check for this condition and handle it */
11858 ic->next->op == IFX &&
11859 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11860 genIfx (ic->next, ic);
11878 genEndFunction (ic);
11898 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11915 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11919 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11926 /* note these two are xlated by algebraic equivalence
11927 during parsing SDCC.y */
11928 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11929 "got '>=' or '<=' shouldn't have come here");
11933 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11945 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11949 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11953 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11977 genRightShift (ic);
11980 case GET_VALUE_AT_ADDRESS:
11981 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_LEFT(ic)))));
11985 if (POINTER_SET (ic))
11986 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
12012 if (ic->builtinSEND) genBuiltIn(ic);
12013 else addSet (&_G.sendSet, ic);
12026 /* now we are ready to call the
12027 peep hole optimizer */
12028 if (!options.nopeep)
12029 peepHole (&lineHead);
12031 /* now do the actual printing */
12032 printLine (lineHead, codeOutFile);