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 *dptrn[2][3];
84 static char *javaRet[] = { "r0","r1","r2","r3"};
85 static short rbank = -1;
102 static char *rb1regs[] = {
103 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
106 static void saveRBank (int, iCode *, bool);
108 #define RESULTONSTACK(x) \
109 (IC_RESULT(x) && IC_RESULT(x)->aop && \
110 IC_RESULT(x)->aop->type == AOP_STK )
112 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
113 #define MOVA(x) { char *_mova_tmp = strdup(x); \
114 if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
116 emitcode("mov","a,%s",_mova_tmp); \
120 #define MOVB(x) { char *_movb_tmp = strdup(x); \
121 if (strcmp(_movb_tmp,"b")) \
123 emitcode("mov","b,%s",_movb_tmp); \
127 #define CLRC emitcode("clr","c")
128 #define SETC emitcode("setb","c")
130 // A scratch register which will be used to hold
131 // result bytes from operands in far space via DPTR2.
132 #define DP2_RESULT_REG "_ap"
134 static lineNode *lineHead = NULL;
135 static lineNode *lineCurr = NULL;
137 static unsigned char SLMask[] =
138 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
139 0xE0, 0xC0, 0x80, 0x00};
140 static unsigned char SRMask[] =
141 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
142 0x07, 0x03, 0x01, 0x00};
148 #define PROTECT_SP {if (options.protect_sp_update) { \
149 symbol *lbl = newiTempLabel(NULL); \
150 emitcode ("setb","F1"); \
151 emitcode ("jbc","EA,!tlabel",lbl->key+100); \
152 emitcode ("clr","F1"); \
153 emitcode ("","!tlabeldef",lbl->key+100); \
155 #define UNPROTECT_SP { if (options.protect_sp_update) { \
156 symbol *lbl = newiTempLabel(NULL); \
157 emitcode ("jnb","F1,!tlabel",lbl->key+100); \
158 emitcode ("setb","EA"); \
159 emitcode ("","!tlabeldef",lbl->key+100); \
163 /*-----------------------------------------------------------------*/
164 /* emitcode - writes the code into a file : for now it is simple */
165 /*-----------------------------------------------------------------*/
167 emitcode (char *inst, char *fmt,...)
170 char lb[INITIAL_INLINEASM];
179 SNPRINTF (lb, sizeof(lb), "%s\t", inst);
183 SNPRINTF (lb, sizeof(lb), "%s", inst);
186 tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb),
191 tvsprintf (lb, sizeof(lb), fmt, ap);
195 while (isspace (*lbp))
202 lineCurr = (lineCurr ?
203 connectLine (lineCurr, newLineNode (lb)) :
204 (lineHead = newLineNode (lb)));
207 lineCurr->isInline = _G.inLine;
208 lineCurr->isDebug = _G.debugLine;
212 /*-----------------------------------------------------------------*/
213 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
214 /*-----------------------------------------------------------------*/
216 getFreePtr (iCode * ic, asmop ** aopp, bool result)
221 /* the logic: if r0 & r1 used in the instruction
222 then we are in trouble otherwise */
224 /* first check if r0 & r1 are used by this
225 instruction, in which case we are in trouble */
226 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
227 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
232 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
233 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
235 /* if no usage of r0 then return it */
238 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
239 (*aopp)->type = AOP_R0;
241 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
244 /* if no usage of r1 then return it */
247 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
248 (*aopp)->type = AOP_R1;
250 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
253 /* now we know they both have usage */
254 /* if r0 not used in this instruction */
257 /* push it if not already pushed */
260 emitcode ("push", "%s",
261 ds390_regWithIdx (R0_IDX)->dname);
265 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
266 (*aopp)->type = AOP_R0;
268 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
271 /* if r1 not used then */
275 /* push it if not already pushed */
278 emitcode ("push", "%s",
279 ds390_regWithIdx (R1_IDX)->dname);
283 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
284 (*aopp)->type = AOP_R1;
285 return ds390_regWithIdx (R1_IDX);
289 /* I said end of world but not quite end of world yet */
290 /* if this is a result then we can push it on the stack */
293 (*aopp)->type = AOP_STK;
297 /* other wise this is true end of the world */
298 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
299 "getFreePtr should never reach here");
302 return NULL; // notreached, but makes compiler happy.
305 /*-----------------------------------------------------------------*/
306 /* newAsmop - creates a new asmOp */
307 /*-----------------------------------------------------------------*/
309 newAsmop (short type)
313 aop = Safe_calloc (1, sizeof (asmop));
318 static int _currentDPS; /* Current processor DPS. */
319 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
320 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
322 /*-----------------------------------------------------------------*/
323 /* genSetDPTR: generate code to select which DPTR is in use (zero */
324 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
325 /* alternate DPTR (DPL1/DPH1/DPX1). */
326 /*-----------------------------------------------------------------*/
331 /* If we are doing lazy evaluation, simply note the desired
332 * change, but don't emit any code yet.
342 emitcode ("mov", "dps,#0");
347 emitcode ("mov", "dps,#1");
351 /*-----------------------------------------------------------------*/
352 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
354 /* Any code that operates on DPTR (NB: not on the individual */
355 /* components, like DPH) *must* call _flushLazyDPS() before using */
356 /* DPTR within a lazy DPS evaluation block. */
358 /* Note that aopPut and aopGet already contain the proper calls to */
359 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
360 /* DPS evaluation block. */
362 /* Also, _flushLazyDPS must be called before any flow control */
363 /* operations that could potentially branch out of the block. */
365 /* Lazy DPS evaluation is simply an optimization (though an */
366 /* important one), so if in doubt, leave it out. */
367 /*-----------------------------------------------------------------*/
369 _startLazyDPSEvaluation (void)
373 #ifdef BETTER_LITERAL_SHIFT
380 /*-----------------------------------------------------------------*/
381 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
382 /* desired one. Call before using DPTR within a lazy DPS evaluation */
384 /*-----------------------------------------------------------------*/
394 if (_desiredDPS != _currentDPS)
398 emitcode ("inc", "dps");
402 emitcode ("dec", "dps");
404 _currentDPS = _desiredDPS;
408 /*-----------------------------------------------------------------*/
409 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
411 /* Forces us back to the safe state (standard DPTR selected). */
412 /*-----------------------------------------------------------------*/
414 _endLazyDPSEvaluation (void)
416 #ifdef BETTER_LITERAL_SHIFT
435 /*-----------------------------------------------------------------*/
436 /* pointerCode - returns the code for a pointer type */
437 /*-----------------------------------------------------------------*/
439 pointerCode (sym_link * etype)
442 return PTR_TYPE (SPEC_OCLS (etype));
446 /*-----------------------------------------------------------------*/
447 /* aopForSym - for a true symbol */
448 /*-----------------------------------------------------------------*/
450 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
453 memmap *space = SPEC_OCLS (sym->etype);
455 /* if already has one */
459 /* assign depending on the storage class */
460 /* if it is on the stack or indirectly addressable */
461 /* space we need to assign either r0 or r1 to it */
462 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
464 sym->aop = aop = newAsmop (0);
465 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
466 aop->size = getSize (sym->type);
468 /* now assign the address of the variable to
469 the pointer register */
470 if (aop->type != AOP_STK)
476 emitcode ("push", "acc");
479 emitcode ("push", "b");
481 emitcode ("mov", "a,_bp");
482 emitcode ("add", "a,#!constbyte",
484 ((char) (sym->stack - _G.nRegsSaved)) :
485 ((char) sym->stack)) & 0xff);
486 emitcode ("mov", "%s,a",
487 aop->aopu.aop_ptr->name);
490 emitcode ("pop", "b");
493 emitcode ("pop", "acc");
496 emitcode ("mov", "%s,#%s",
497 aop->aopu.aop_ptr->name,
499 aop->paged = space->paged;
502 aop->aopu.aop_stk = sym->stack;
506 if (sym->onStack && options.stack10bit)
508 short stack_val = -((sym->stack < 0) ?
509 ((short) (sym->stack - _G.nRegsSaved)) :
510 ((short) sym->stack)) ;
511 if (useDP2 && _G.dptr1InUse) {
512 emitcode ("push","dpl1");
513 emitcode ("push","dph1");
514 emitcode ("push","dpx1");
515 } else if (_G.dptrInUse ) {
516 emitcode ("push","dpl");
517 emitcode ("push","dph");
518 emitcode ("push","dpx");
520 /* It's on the 10 bit stack, which is located in
523 if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
525 if (options.model == MODEL_FLAT24)
526 emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
528 emitcode ("mov", "dph1,_bpx+1");
529 emitcode ("mov", "dpl1,_bpx");
530 emitcode ("mov","dps,#1");
532 if (options.model == MODEL_FLAT24)
533 emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
534 emitcode ("mov", "dph,_bpx+1");
535 emitcode ("mov", "dpl,_bpx");
537 stack_val = -stack_val;
538 while (stack_val--) {
539 emitcode ("inc","dptr");
542 emitcode("mov","dps,#0");
546 emitcode ("push", "acc");
549 emitcode ("push", "b");
551 emitcode ("mov", "a,_bpx");
552 emitcode ("clr","c");
553 emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
554 emitcode ("mov","b,a");
555 emitcode ("mov","a,_bpx+1");
556 emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
558 if (options.model == MODEL_FLAT24)
559 emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
561 emitcode ("mov", "dph1,a");
562 emitcode ("mov", "dpl1,b");
564 if (options.model == MODEL_FLAT24)
565 emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
566 emitcode ("mov", "dph,a");
567 emitcode ("mov", "dpl,b");
571 emitcode ("pop", "b");
574 emitcode ("pop", "acc");
576 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
577 aop->size = getSize (sym->type);
581 /* if in bit space */
582 if (IN_BITSPACE (space))
584 sym->aop = aop = newAsmop (AOP_CRY);
585 aop->aopu.aop_dir = sym->rname;
586 aop->size = getSize (sym->type);
589 /* if it is in direct space */
590 if (IN_DIRSPACE (space))
592 sym->aop = aop = newAsmop (AOP_DIR);
593 aop->aopu.aop_dir = sym->rname;
594 aop->size = getSize (sym->type);
598 /* special case for a function */
599 if (IS_FUNC (sym->type))
601 sym->aop = aop = newAsmop (AOP_IMMD);
602 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
603 aop->size = FPTRSIZE;
607 /* only remaining is far space */
608 /* in which case DPTR gets the address */
609 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
614 emitcode ("mov", "dptr,#%s", sym->rname);
619 emitcode ("mov", "dptr,#%s", sym->rname);
621 aop->size = getSize (sym->type);
623 /* if it is in code space */
624 if (IN_CODESPACE (space))
630 /*-----------------------------------------------------------------*/
631 /* aopForRemat - rematerialzes an object */
632 /*-----------------------------------------------------------------*/
634 aopForRemat (symbol * sym)
636 iCode *ic = sym->rematiCode;
637 asmop *aop = newAsmop (AOP_IMMD);
644 val += (int) operandLitValue (IC_RIGHT (ic));
645 else if (ic->op == '-')
646 val -= (int) operandLitValue (IC_RIGHT (ic));
647 else if (IS_CAST_ICODE(ic)) {
648 sym_link *from_type = operandType(IC_RIGHT(ic));
649 aop->aopu.aop_immd.from_cast_remat = 1;
650 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
651 ptr_type = DCL_TYPE(from_type);
652 if (ptr_type == IPOINTER) {
659 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
664 SNPRINTF (buffer, sizeof(buffer),
666 OP_SYMBOL (IC_LEFT (ic))->rname,
667 val >= 0 ? '+' : '-',
672 if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
674 SNPRINTF(buffer, sizeof(buffer),
675 "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
679 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
683 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
684 /* set immd2 field if required */
685 if (aop->aopu.aop_immd.from_cast_remat)
687 tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
688 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
694 /*-----------------------------------------------------------------*/
695 /* aopHasRegs - returns true if aop has regs between from-to */
696 /*-----------------------------------------------------------------*/
697 static int aopHasRegs(asmop *aop, int from, int to)
701 if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
703 for (; size < aop->size ; size++) {
705 for (reg = from ; reg <= to ; reg++)
706 if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
711 /*-----------------------------------------------------------------*/
712 /* regsInCommon - two operands have some registers in common */
713 /*-----------------------------------------------------------------*/
715 regsInCommon (operand * op1, operand * op2)
720 /* if they have registers in common */
721 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
724 sym1 = OP_SYMBOL (op1);
725 sym2 = OP_SYMBOL (op2);
727 if (sym1->nRegs == 0 || sym2->nRegs == 0)
730 for (i = 0; i < sym1->nRegs; i++)
736 for (j = 0; j < sym2->nRegs; j++)
741 if (sym2->regs[j] == sym1->regs[i])
749 /*-----------------------------------------------------------------*/
750 /* operandsEqu - equivalent */
751 /*-----------------------------------------------------------------*/
753 operandsEqu (operand * op1, operand * op2)
757 /* if they not symbols */
758 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
761 sym1 = OP_SYMBOL (op1);
762 sym2 = OP_SYMBOL (op2);
764 /* if both are itemps & one is spilt
765 and the other is not then false */
766 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
767 sym1->isspilt != sym2->isspilt)
770 /* if they are the same */
774 if (strcmp (sym1->rname, sym2->rname) == 0)
778 /* if left is a tmp & right is not */
779 if (IS_ITEMP (op1) &&
782 (sym1->usl.spillLoc == sym2))
785 if (IS_ITEMP (op2) &&
789 (sym2->usl.spillLoc == sym1))
795 /*-----------------------------------------------------------------*/
796 /* sameRegs - two asmops have the same registers */
797 /*-----------------------------------------------------------------*/
799 sameRegs (asmop * aop1, asmop * aop2)
805 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
812 if (aop1->type != AOP_REG ||
813 aop2->type != AOP_REG)
816 if (aop1->size != aop2->size)
819 for (i = 0; i < aop1->size; i++)
820 if (aop1->aopu.aop_reg[i] !=
821 aop2->aopu.aop_reg[i])
827 /*-----------------------------------------------------------------*/
828 /* aopOp - allocates an asmop for an operand : */
829 /*-----------------------------------------------------------------*/
831 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
840 /* if this a literal */
841 if (IS_OP_LITERAL (op))
843 op->aop = aop = newAsmop (AOP_LIT);
844 aop->aopu.aop_lit = op->operand.valOperand;
845 aop->size = getSize (operandType (op));
849 /* if already has a asmop then continue */
853 /* if the underlying symbol has a aop */
854 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
856 op->aop = OP_SYMBOL (op)->aop;
860 /* if this is a true symbol */
861 if (IS_TRUE_SYMOP (op))
863 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
867 /* this is a temporary : this has
873 e) can be a return use only */
875 sym = OP_SYMBOL (op);
878 /* if the type is a conditional */
879 if (sym->regType == REG_CND)
881 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
886 /* if it is spilt then two situations
888 b) has a spill location */
889 if (sym->isspilt || sym->nRegs == 0)
892 /* rematerialize it NOW */
895 sym->aop = op->aop = aop =
897 aop->size = getSize (sym->type);
904 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
905 aop->size = getSize (sym->type);
906 for (i = 0; i < 2; i++)
907 aop->aopu.aop_str[i] = accUse[i];
917 /* a AOP_STR uses DPTR, but DPTR is already in use;
920 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
923 aop = op->aop = sym->aop = newAsmop (AOP_STR);
924 aop->size = getSize (sym->type);
925 for (i = 0; i < (int) fReturnSizeDS390; i++)
926 aop->aopu.aop_str[i] = fReturn[i];
930 if (sym->dptr) { /* has been allocated to a DPTRn */
931 aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
932 aop->size = getSize (sym->type);
933 aop->aopu.dptr = sym->dptr;
936 /* else spill location */
937 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
938 /* force a new aop if sizes differ */
939 sym->usl.spillLoc->aop = NULL;
941 sym->aop = op->aop = aop =
942 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
943 aop->size = getSize (sym->type);
947 /* must be in a register */
948 sym->aop = op->aop = aop = newAsmop (AOP_REG);
949 aop->size = sym->nRegs;
950 for (i = 0; i < sym->nRegs; i++)
951 aop->aopu.aop_reg[i] = sym->regs[i];
954 /*-----------------------------------------------------------------*/
955 /* freeAsmop - free up the asmop given to an operand */
956 /*----------------------------------------------------------------*/
958 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
975 /* depending on the asmop type only three cases need work AOP_RO
976 , AOP_R1 && AOP_STK */
984 emitcode ("pop", "ar0");
988 bitVectUnSetBit (ic->rUsed, R0_IDX);
996 emitcode ("pop", "ar1");
1000 bitVectUnSetBit (ic->rUsed, R1_IDX);
1006 int stk = aop->aopu.aop_stk + aop->size;
1007 bitVectUnSetBit (ic->rUsed, R0_IDX);
1008 bitVectUnSetBit (ic->rUsed, R1_IDX);
1010 getFreePtr (ic, &aop, FALSE);
1012 if (options.stack10bit)
1014 /* I'm not sure what to do here yet... */
1017 "*** Warning: probably generating bad code for "
1018 "10 bit stack mode.\n");
1023 emitcode ("mov", "a,_bp");
1024 emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1025 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1029 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1034 emitcode ("pop", "acc");
1035 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1038 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1041 freeAsmop (op, NULL, ic, TRUE);
1044 emitcode ("pop", "ar0");
1050 emitcode ("pop", "ar1");
1055 if (_G.dptr1InUse) {
1056 emitcode ("pop","dpx1");
1057 emitcode ("pop","dph1");
1058 emitcode ("pop","dpl1");
1063 emitcode ("pop","dpx");
1064 emitcode ("pop","dph");
1065 emitcode ("pop","dpl");
1070 /* all other cases just dealloc */
1076 OP_SYMBOL (op)->aop = NULL;
1077 /* if the symbol has a spill */
1079 SPIL_LOC (op)->aop = NULL;
1084 /*-------------------------------------------------------------------*/
1085 /* aopGet - for fetching value of the aop */
1087 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1088 /* in the accumulator. Set it to the name of a free register */
1089 /* if acc must be preserved; the register will be used to preserve */
1090 /* acc temporarily and to return the result byte. */
1091 /*-------------------------------------------------------------------*/
1100 /* offset is greater than
1102 if (offset > (aop->size - 1) &&
1103 aop->type != AOP_LIT)
1106 /* depending on type */
1112 /* if we need to increment it */
1113 while (offset > aop->coff)
1115 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1119 while (offset < aop->coff)
1121 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1128 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1129 return (dname ? "acc" : "a");
1131 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1132 return Safe_strdup(buffer);
1135 assert(offset <= 3);
1136 return dptrn[aop->aopu.dptr][offset];
1141 if (aop->type == AOP_DPTR2)
1147 emitcode ("xch", "a, %s", saveAcc);
1153 while (offset > aop->coff)
1155 emitcode ("inc", "dptr");
1159 while (offset < aop->coff)
1161 emitcode ("lcall", "__decdptr");
1168 emitcode ("clr", "a");
1169 emitcode ("movc", "a,@a+dptr");
1173 emitcode ("movx", "a,@dptr");
1176 if (aop->type == AOP_DPTR2)
1182 emitcode ("xch", "a, %s", saveAcc);
1186 return (dname ? "acc" : "a");
1189 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1191 SNPRINTF(buffer, sizeof(buffer),
1192 "%s",aop->aopu.aop_immd.aop_immd2);
1196 SNPRINTF(buffer, sizeof(buffer),
1197 "#%s", aop->aopu.aop_immd.aop_immd1);
1203 tsprintf(buffer, sizeof(buffer),
1204 "#!his",aop->aopu.aop_immd.aop_immd1);
1207 tsprintf(buffer, sizeof(buffer),
1208 "#!hihis",aop->aopu.aop_immd.aop_immd1);
1211 tsprintf(buffer, sizeof(buffer),
1212 "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1214 default: /* should not need this (just in case) */
1215 SNPRINTF (buffer, sizeof(buffer),
1217 aop->aopu.aop_immd.aop_immd1,
1223 SNPRINTF (buffer, sizeof(buffer),
1224 "#%s", aop->aopu.aop_immd.aop_immd1);
1226 return Safe_strdup(buffer);
1231 SNPRINTF (buffer, sizeof(buffer),
1238 SNPRINTF(buffer, sizeof(buffer),
1239 "%s", aop->aopu.aop_dir);
1242 return Safe_strdup(buffer);
1246 return aop->aopu.aop_reg[offset]->dname;
1248 return aop->aopu.aop_reg[offset]->name;
1251 emitcode ("clr", "a");
1252 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1253 emitcode ("rlc", "a");
1254 return (dname ? "acc" : "a");
1257 if (!offset && dname)
1259 return aop->aopu.aop_str[offset];
1262 return aopLiteral (aop->aopu.aop_lit, offset);
1266 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1270 return aop->aopu.aop_str[offset];
1274 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1275 "aopget got unsupported aop->type");
1278 return NULL; // not reached, but makes compiler happy.
1280 /*-----------------------------------------------------------------*/
1281 /* aopPut - puts a string for a aop */
1282 /*-----------------------------------------------------------------*/
1284 aopPut (asmop * aop, char *s, int offset)
1286 if (aop->size && offset > (aop->size - 1))
1288 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1289 "aopPut got offset > aop->size");
1293 /* will assign value to value */
1294 /* depending on where it is ofcourse */
1300 SNPRINTF (buffer, sizeof(buffer),
1302 aop->aopu.aop_dir, offset);
1306 SNPRINTF (buffer, sizeof(buffer),
1307 "%s", aop->aopu.aop_dir);
1311 if (strcmp (buffer, s))
1313 emitcode ("mov", "%s,%s", buffer, s);
1318 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1319 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1322 strcmp (s, "r0") == 0 ||
1323 strcmp (s, "r1") == 0 ||
1324 strcmp (s, "r2") == 0 ||
1325 strcmp (s, "r3") == 0 ||
1326 strcmp (s, "r4") == 0 ||
1327 strcmp (s, "r5") == 0 ||
1328 strcmp (s, "r6") == 0 ||
1329 strcmp (s, "r7") == 0)
1331 emitcode ("mov", "%s,%s",
1332 aop->aopu.aop_reg[offset]->dname, s);
1336 emitcode ("mov", "%s,%s",
1337 aop->aopu.aop_reg[offset]->name, s);
1343 emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1349 if (aop->type == AOP_DPTR2)
1357 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1358 "aopPut writting to code space");
1362 while (offset > aop->coff)
1365 emitcode ("inc", "dptr");
1368 while (offset < aop->coff)
1371 emitcode ("lcall", "__decdptr");
1376 /* if not in accumulater */
1379 emitcode ("movx", "@dptr,a");
1381 if (aop->type == AOP_DPTR2)
1389 while (offset > aop->coff)
1392 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1394 while (offset < aop->coff)
1397 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1404 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1410 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1412 else if (strcmp (s, "r0") == 0 ||
1413 strcmp (s, "r1") == 0 ||
1414 strcmp (s, "r2") == 0 ||
1415 strcmp (s, "r3") == 0 ||
1416 strcmp (s, "r4") == 0 ||
1417 strcmp (s, "r5") == 0 ||
1418 strcmp (s, "r6") == 0 ||
1419 strcmp (s, "r7") == 0)
1422 SNPRINTF(buff, sizeof(buff),
1424 emitcode ("mov", "@%s,%s",
1425 aop->aopu.aop_ptr->name, buff);
1429 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1434 if (strcmp (s, "a") == 0)
1435 emitcode ("push", "acc");
1439 emitcode ("push", "acc");
1441 emitcode ("push", s);
1447 /* if bit variable */
1448 if (!aop->aopu.aop_dir)
1450 emitcode ("clr", "a");
1451 emitcode ("rlc", "a");
1456 emitcode ("clr", "%s", aop->aopu.aop_dir);
1458 emitcode ("setb", "%s", aop->aopu.aop_dir);
1459 else if (!strcmp (s, "c"))
1460 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1463 if (strcmp (s, "a"))
1468 /* set C, if a >= 1 */
1469 emitcode ("add", "a,#!constbyte",0xff);
1470 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1478 if (strcmp (aop->aopu.aop_str[offset], s))
1479 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1484 if (!offset && (strcmp (s, "acc") == 0))
1487 if (strcmp (aop->aopu.aop_str[offset], s))
1488 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1492 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1493 "aopPut got unsupported aop->type");
1500 /*--------------------------------------------------------------------*/
1501 /* reAdjustPreg - points a register back to where it should (coff==0) */
1502 /*--------------------------------------------------------------------*/
1504 reAdjustPreg (asmop * aop)
1506 if ((aop->coff==0) || (aop->size <= 1)) {
1515 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1519 if (aop->type == AOP_DPTR2)
1526 emitcode ("lcall", "__decdptr");
1529 if (aop->type == AOP_DPTR2)
1539 #define AOP(op) op->aop
1540 #define AOP_TYPE(op) AOP(op)->type
1541 #define AOP_SIZE(op) AOP(op)->size
1542 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1543 AOP_TYPE(x) == AOP_R0))
1545 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1546 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1549 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1550 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1551 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1552 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1553 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1554 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1556 // The following two macros can be used even if the aop has not yet been aopOp'd.
1557 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1558 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1560 /* Workaround for DS80C390 bug: div ab may return bogus results
1561 * if A is accessed in instruction immediately before the div.
1563 * Will be fixed in B4 rev of processor, Dallas claims.
1566 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1567 if (!AOP_NEEDSACC(RIGHT)) \
1569 /* We can load A first, then B, since \
1570 * B (the RIGHT operand) won't clobber A, \
1571 * thus avoiding touching A right before the div. \
1573 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1574 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1576 L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1581 /* Just stuff in a nop after loading A. */ \
1582 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1583 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1585 emitcode("nop", "; workaround for DS80C390 div bug."); \
1588 /*-----------------------------------------------------------------*/
1589 /* genNotFloat - generates not for float operations */
1590 /*-----------------------------------------------------------------*/
1592 genNotFloat (operand * op, operand * res)
1598 D (emitcode (";", "genNotFloat "););
1600 /* we will put 127 in the first byte of
1602 aopPut (AOP (res), "#127", 0);
1603 size = AOP_SIZE (op) - 1;
1606 _startLazyDPSEvaluation ();
1607 l = aopGet (op->aop, offset++, FALSE, FALSE, NULL);
1612 emitcode ("orl", "a,%s",
1614 offset++, FALSE, FALSE,
1617 _endLazyDPSEvaluation ();
1619 tlbl = newiTempLabel (NULL);
1620 aopPut (res->aop, one, 1);
1621 emitcode ("jz", "!tlabel", (tlbl->key + 100));
1622 aopPut (res->aop, zero, 1);
1623 emitcode ("", "!tlabeldef", (tlbl->key + 100));
1625 size = res->aop->size - 2;
1627 /* put zeros in the rest */
1629 aopPut (res->aop, zero, offset++);
1632 /*-----------------------------------------------------------------*/
1633 /* opIsGptr: returns non-zero if the passed operand is */
1634 /* a generic pointer type. */
1635 /*-----------------------------------------------------------------*/
1637 opIsGptr (operand * op)
1639 sym_link *type = operandType (op);
1641 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1648 /*-----------------------------------------------------------------*/
1649 /* getDataSize - get the operand data size */
1650 /*-----------------------------------------------------------------*/
1652 getDataSize (operand * op)
1655 size = AOP_SIZE (op);
1656 if (size == GPTRSIZE)
1658 sym_link *type = operandType (op);
1659 if (IS_GENPTR (type))
1661 /* generic pointer; arithmetic operations
1662 * should ignore the high byte (pointer type).
1670 /*-----------------------------------------------------------------*/
1671 /* outAcc - output Acc */
1672 /*-----------------------------------------------------------------*/
1674 outAcc (operand * result)
1677 size = getDataSize (result);
1680 aopPut (AOP (result), "a", 0);
1683 /* unsigned or positive */
1686 aopPut (AOP (result), zero, offset++);
1691 /*-----------------------------------------------------------------*/
1692 /* outBitC - output a bit C */
1693 /*-----------------------------------------------------------------*/
1695 outBitC (operand * result)
1697 /* if the result is bit */
1698 if (AOP_TYPE (result) == AOP_CRY)
1700 aopPut (AOP (result), "c", 0);
1704 emitcode ("clr", "a");
1705 emitcode ("rlc", "a");
1710 /*-----------------------------------------------------------------*/
1711 /* toBoolean - emit code for orl a,operator(sizeop) */
1712 /*-----------------------------------------------------------------*/
1714 toBoolean (operand * oper)
1716 int size = AOP_SIZE (oper) - 1;
1720 /* The generic part of a generic pointer should
1721 * not participate in it's truth value.
1723 * i.e. 0x10000000 is zero.
1725 if (opIsGptr (oper))
1727 D (emitcode (";", "toBoolean: generic ptr special case."););
1731 _startLazyDPSEvaluation ();
1732 if (AOP_NEEDSACC (oper) && size)
1735 emitcode ("push", "b");
1736 MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, "b"));
1740 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1747 emitcode ("orl", "b,%s",
1748 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1752 emitcode ("orl", "a,%s",
1753 aopGet (AOP (oper), offset++, FALSE, FALSE, DP2_RESULT_REG));
1756 _endLazyDPSEvaluation ();
1760 emitcode ("mov", "a,b");
1761 emitcode ("pop", "b");
1766 /*-----------------------------------------------------------------*/
1767 /* genNot - generate code for ! operation */
1768 /*-----------------------------------------------------------------*/
1773 sym_link *optype = operandType (IC_LEFT (ic));
1775 D (emitcode (";", "genNot "););
1777 /* assign asmOps to operand & result */
1778 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1779 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1781 /* if in bit space then a special case */
1782 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1784 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1785 emitcode ("cpl", "c");
1786 outBitC (IC_RESULT (ic));
1790 /* if type float then do float */
1791 if (IS_FLOAT (optype))
1793 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1797 toBoolean (IC_LEFT (ic));
1799 tlbl = newiTempLabel (NULL);
1800 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1801 emitcode ("", "!tlabeldef", tlbl->key + 100);
1802 outBitC (IC_RESULT (ic));
1805 /* release the aops */
1806 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1807 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1811 /*-----------------------------------------------------------------*/
1812 /* genCpl - generate code for complement */
1813 /*-----------------------------------------------------------------*/
1821 D (emitcode (";", "genCpl "););
1824 /* assign asmOps to operand & result */
1825 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1826 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1828 /* special case if in bit space */
1829 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1830 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1831 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1832 emitcode ("cpl", "c");
1833 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1836 tlbl=newiTempLabel(NULL);
1837 emitcode ("cjne", "%s,#0x01,%05d$",
1838 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1839 emitcode ("", "%05d$:", tlbl->key+100);
1840 outBitC (IC_RESULT(ic));
1844 size = AOP_SIZE (IC_RESULT (ic));
1845 _startLazyDPSEvaluation ();
1848 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1849 emitcode ("cpl", "a");
1850 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1852 _endLazyDPSEvaluation ();
1856 /* release the aops */
1857 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1858 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1861 /*-----------------------------------------------------------------*/
1862 /* genUminusFloat - unary minus for floating points */
1863 /*-----------------------------------------------------------------*/
1865 genUminusFloat (operand * op, operand * result)
1867 int size, offset = 0;
1869 D(emitcode (";", "genUminusFloat"););
1871 /* for this we just copy and then flip the bit */
1873 _startLazyDPSEvaluation ();
1874 size = AOP_SIZE (op) - 1;
1878 aopPut (AOP (result),
1879 aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1884 MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1886 emitcode ("cpl", "acc.7");
1887 aopPut (AOP (result), "a", offset);
1888 _endLazyDPSEvaluation ();
1891 /*-----------------------------------------------------------------*/
1892 /* genUminus - unary minus code generation */
1893 /*-----------------------------------------------------------------*/
1895 genUminus (iCode * ic)
1900 D (emitcode (";", "genUminus "););
1903 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1904 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1906 /* if both in bit space then special
1908 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1909 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1912 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1913 emitcode ("cpl", "c");
1914 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1918 optype = operandType (IC_LEFT (ic));
1920 /* if float then do float stuff */
1921 if (IS_FLOAT (optype))
1923 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1927 /* otherwise subtract from zero */
1928 size = AOP_SIZE (IC_LEFT (ic));
1930 _startLazyDPSEvaluation ();
1933 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
1934 if (!strcmp (l, "a"))
1938 emitcode ("cpl", "a");
1939 emitcode ("addc", "a,#0");
1945 emitcode ("clr", "a");
1946 emitcode ("subb", "a,%s", l);
1948 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1950 _endLazyDPSEvaluation ();
1952 /* if any remaining bytes in the result */
1953 /* we just need to propagate the sign */
1954 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
1956 emitcode ("rlc", "a");
1957 emitcode ("subb", "a,acc");
1959 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1963 /* release the aops */
1964 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1965 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1968 /*-----------------------------------------------------------------*/
1969 /* savermask - saves registers in the mask */
1970 /*-----------------------------------------------------------------*/
1971 static void savermask(bitVect *rs_mask)
1974 if (options.useXstack) {
1975 if (bitVectBitValue (rs_mask, R0_IDX))
1976 emitcode ("mov", "b,r0");
1977 emitcode ("mov", "r0,%s", spname);
1978 for (i = 0; i < ds390_nRegs; i++) {
1979 if (bitVectBitValue (rs_mask, i)) {
1981 emitcode ("mov", "a,b");
1983 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1984 emitcode ("movx", "@r0,a");
1985 emitcode ("inc", "r0");
1988 emitcode ("mov", "%s,r0", spname);
1989 if (bitVectBitValue (rs_mask, R0_IDX))
1990 emitcode ("mov", "r0,b");
1992 for (i = 0; i < ds390_nRegs; i++) {
1993 if (bitVectBitValue (rs_mask, i))
1994 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1999 /*-----------------------------------------------------------------*/
2000 /* saveRegisters - will look for a call and save the registers */
2001 /*-----------------------------------------------------------------*/
2003 saveRegisters (iCode * lic)
2009 for (ic = lic; ic; ic = ic->next)
2010 if (ic->op == CALL || ic->op == PCALL)
2015 fprintf (stderr, "found parameter push with no function call\n");
2019 /* if the registers have been saved already then
2021 if (ic->regsSaved || IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))) return ;
2023 /* special case if DPTR alive across a function call then must save it
2024 even though callee saves */
2025 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2027 rsave = newBitVect(ic->rMask->size);
2028 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2029 if (bitVectBitValue(ic->rMask,i))
2030 rsave = bitVectSetBit(rsave,i);
2032 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2034 /* safe the registers in use at this time but skip the
2035 ones for the result */
2036 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2037 ds390_rUmaskForOp (IC_RESULT(ic)));
2043 /*-----------------------------------------------------------------*/
2044 /* usavermask - restore registers with mask */
2045 /*-----------------------------------------------------------------*/
2046 static void unsavermask(bitVect *rs_mask)
2049 if (options.useXstack) {
2050 emitcode ("mov", "r0,%s", spname);
2051 for (i = ds390_nRegs; i >= 0; i--) {
2052 if (bitVectBitValue (rs_mask, i)) {
2053 emitcode ("dec", "r0");
2054 emitcode ("movx", "a,@r0");
2056 emitcode ("mov", "b,a");
2058 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2061 emitcode ("mov", "%s,r0", spname);
2062 if (bitVectBitValue (rs_mask, R0_IDX))
2063 emitcode ("mov", "r0,b");
2065 for (i = ds390_nRegs; i >= 0; i--) {
2066 if (bitVectBitValue (rs_mask, i))
2067 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2072 /*-----------------------------------------------------------------*/
2073 /* unsaveRegisters - pop the pushed registers */
2074 /*-----------------------------------------------------------------*/
2076 unsaveRegisters (iCode * ic)
2080 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2082 rsave = newBitVect(ic->rMask->size);
2083 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2084 if (bitVectBitValue(ic->rMask,i))
2085 rsave = bitVectSetBit(rsave,i);
2087 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2089 /* restore the registers in use at this time but skip the
2090 ones for the result */
2091 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2092 ds390_rUmaskForOp (IC_RESULT(ic)));
2098 /*-----------------------------------------------------------------*/
2100 /*-----------------------------------------------------------------*/
2102 pushSide (operand * oper, int size)
2105 _startLazyDPSEvaluation ();
2108 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2109 if (AOP_TYPE (oper) != AOP_REG &&
2110 AOP_TYPE (oper) != AOP_DIR &&
2113 emitcode ("mov", "a,%s", l);
2114 emitcode ("push", "acc");
2117 emitcode ("push", "%s", l);
2119 _endLazyDPSEvaluation ();
2122 /*-----------------------------------------------------------------*/
2123 /* assignResultValue - */
2124 /*-----------------------------------------------------------------*/
2126 assignResultValue (operand * oper)
2129 int size = AOP_SIZE (oper);
2131 _startLazyDPSEvaluation ();
2134 aopPut (AOP (oper), fReturn[offset], offset);
2137 _endLazyDPSEvaluation ();
2141 /*-----------------------------------------------------------------*/
2142 /* genXpush - pushes onto the external stack */
2143 /*-----------------------------------------------------------------*/
2145 genXpush (iCode * ic)
2147 asmop *aop = newAsmop (0);
2149 int size, offset = 0;
2151 D (emitcode (";", "genXpush ");
2154 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2155 r = getFreePtr (ic, &aop, FALSE);
2158 emitcode ("mov", "%s,_spx", r->name);
2160 size = AOP_SIZE (IC_LEFT (ic));
2161 _startLazyDPSEvaluation ();
2165 MOVA (aopGet (AOP (IC_LEFT (ic)),
2166 offset++, FALSE, FALSE, NULL));
2167 emitcode ("movx", "@%s,a", r->name);
2168 emitcode ("inc", "%s", r->name);
2171 _endLazyDPSEvaluation ();
2174 emitcode ("mov", "_spx,%s", r->name);
2176 freeAsmop (NULL, aop, ic, TRUE);
2177 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2180 /*-----------------------------------------------------------------*/
2181 /* genIpush - generate code for pushing this gets a little complex */
2182 /*-----------------------------------------------------------------*/
2184 genIpush (iCode * ic)
2186 int size, offset = 0;
2189 D (emitcode (";", "genIpush ");
2192 /* if this is not a parm push : ie. it is spill push
2193 and spill push is always done on the local stack */
2197 /* and the item is spilt then do nothing */
2198 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2201 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2202 size = AOP_SIZE (IC_LEFT (ic));
2203 /* push it on the stack */
2204 _startLazyDPSEvaluation ();
2207 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2213 emitcode ("push", "%s", l);
2215 _endLazyDPSEvaluation ();
2219 /* this is a paramter push: in this case we call
2220 the routine to find the call and save those
2221 registers that need to be saved */
2224 /* if use external stack then call the external
2225 stack pushing routine */
2226 if (options.useXstack)
2232 /* then do the push */
2233 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2235 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2236 size = AOP_SIZE (IC_LEFT (ic));
2238 _startLazyDPSEvaluation ();
2241 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2242 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2243 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2246 emitcode ("mov", "a,%s", l);
2247 emitcode ("push", "acc");
2251 emitcode ("push", "%s", l);
2254 _endLazyDPSEvaluation ();
2256 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2259 /*-----------------------------------------------------------------*/
2260 /* genIpop - recover the registers: can happen only for spilling */
2261 /*-----------------------------------------------------------------*/
2263 genIpop (iCode * ic)
2267 D (emitcode (";", "genIpop ");
2271 /* if the temp was not pushed then */
2272 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2275 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2276 size = AOP_SIZE (IC_LEFT (ic));
2277 offset = (size - 1);
2278 _startLazyDPSEvaluation ();
2281 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2282 FALSE, TRUE, NULL));
2284 _endLazyDPSEvaluation ();
2286 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2289 /*-----------------------------------------------------------------*/
2290 /* unsaveRBank - restores the resgister bank from stack */
2291 /*-----------------------------------------------------------------*/
2293 unsaveRBank (int bank, iCode * ic, bool popPsw)
2299 if (options.useXstack)
2303 /* Assume r0 is available for use. */
2304 r = ds390_regWithIdx (R0_IDX);;
2309 r = getFreePtr (ic, &aop, FALSE);
2311 emitcode ("mov", "%s,_spx", r->name);
2316 if (options.useXstack)
2318 emitcode ("movx", "a,@%s", r->name);
2319 emitcode ("mov", "psw,a");
2320 emitcode ("dec", "%s", r->name);
2324 emitcode ("pop", "psw");
2328 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2330 if (options.useXstack)
2332 emitcode ("movx", "a,@%s", r->name);
2333 emitcode ("mov", "(%s+%d),a",
2334 regs390[i].base, 8 * bank + regs390[i].offset);
2335 emitcode ("dec", "%s", r->name);
2339 emitcode ("pop", "(%s+%d)",
2340 regs390[i].base, 8 * bank + regs390[i].offset);
2343 if (options.useXstack)
2345 emitcode ("mov", "_spx,%s", r->name);
2350 freeAsmop (NULL, aop, ic, TRUE);
2354 /*-----------------------------------------------------------------*/
2355 /* saveRBank - saves an entire register bank on the stack */
2356 /*-----------------------------------------------------------------*/
2358 saveRBank (int bank, iCode * ic, bool pushPsw)
2364 if (options.useXstack)
2368 /* Assume r0 is available for use. */
2369 r = ds390_regWithIdx (R0_IDX);;
2374 r = getFreePtr (ic, &aop, FALSE);
2376 emitcode ("mov", "%s,_spx", r->name);
2379 for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2381 if (options.useXstack)
2383 emitcode ("inc", "%s", r->name);
2384 emitcode ("mov", "a,(%s+%d)",
2385 regs390[i].base, 8 * bank + regs390[i].offset);
2386 emitcode ("movx", "@%s,a", r->name);
2389 emitcode ("push", "(%s+%d)",
2390 regs390[i].base, 8 * bank + regs390[i].offset);
2395 if (options.useXstack)
2397 emitcode ("mov", "a,psw");
2398 emitcode ("movx", "@%s,a", r->name);
2399 emitcode ("inc", "%s", r->name);
2400 emitcode ("mov", "_spx,%s", r->name);
2404 emitcode ("push", "psw");
2407 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2412 freeAsmop (NULL, aop, ic, TRUE);
2421 /*-----------------------------------------------------------------*/
2422 /* genSend - gen code for SEND */
2423 /*-----------------------------------------------------------------*/
2424 static void genSend(set *sendSet)
2428 static int rb1_count = 0;
2430 for (sic = setFirstItem (sendSet); sic;
2431 sic = setNextItem (sendSet)) {
2432 int size, offset = 0;
2434 size=getSize(operandType(IC_LEFT(sic)));
2435 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2436 if (sendCount == 0) { /* first parameter */
2437 // we know that dpl(hxb) is the result, so
2439 _startLazyDPSEvaluation ();
2441 aopOp (IC_LEFT (sic), sic, FALSE,
2442 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2444 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2447 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2448 FALSE, FALSE, NULL);
2449 if (strcmp (l, fReturn[offset])) {
2450 emitcode ("mov", "%s,%s",
2456 _endLazyDPSEvaluation ();
2457 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2459 } else { /* if more parameter in registers */
2460 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2462 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2463 FALSE, FALSE, NULL));
2465 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2471 /*-----------------------------------------------------------------*/
2472 /* genCall - generates a call statement */
2473 /*-----------------------------------------------------------------*/
2475 genCall (iCode * ic)
2478 bool restoreBank = FALSE;
2479 bool swapBanks = FALSE;
2481 D (emitcode (";", "genCall "););
2483 /* if we are calling a not _naked function that is not using
2484 the same register bank then we need to save the
2485 destination registers on the stack */
2486 dtype = operandType (IC_LEFT (ic));
2487 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2488 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2489 IFFUNC_ISISR (currFunc->type))
2493 /* This is unexpected; the bank should have been saved in
2496 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2502 /* if caller saves & we have not saved then */
2506 /* if send set is not empty the assign */
2507 /* We've saved all the registers we care about;
2508 * therefore, we may clobber any register not used
2509 * in the calling convention (i.e. anything not in
2514 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2515 genSend(reverseSet(_G.sendSet));
2517 genSend(_G.sendSet);
2524 emitcode ("mov", "psw,#!constbyte",
2525 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2529 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2530 OP_SYMBOL (IC_LEFT (ic))->rname :
2531 OP_SYMBOL (IC_LEFT (ic))->name));
2535 emitcode ("mov", "psw,#!constbyte",
2536 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2539 /* if we need assign a result value */
2540 if ((IS_ITEMP (IC_RESULT (ic)) &&
2541 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2542 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2543 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2544 IS_TRUE_SYMOP (IC_RESULT (ic)))
2546 if (isOperandInFarSpace (IC_RESULT (ic))
2547 && getSize (operandType (IC_RESULT (ic))) <= 2)
2549 int size = getSize (operandType (IC_RESULT (ic)));
2551 /* Special case for 1 or 2 byte return in far space. */
2555 emitcode ("mov", "b,%s", fReturn[1]);
2558 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2559 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2563 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2565 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2570 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2573 assignResultValue (IC_RESULT (ic));
2575 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2579 /* adjust the stack for parameters if
2581 if (ic->parmBytes) {
2583 if (options.stack10bit) {
2584 if (ic->parmBytes <= 10) {
2585 emitcode(";","stack adjustment for parms");
2586 for (i=0; i < ic->parmBytes ; i++) {
2587 emitcode("pop","acc");
2591 emitcode ("clr","c");
2592 emitcode ("mov","a,sp");
2593 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2594 emitcode ("mov","sp,a");
2595 emitcode ("mov","a,esp");
2596 emitcode ("anl","a,#3");
2597 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2598 emitcode ("mov","esp,a");
2602 if (ic->parmBytes > 3) {
2603 emitcode ("mov", "a,%s", spname);
2604 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2605 emitcode ("mov", "%s,a", spname);
2607 for (i = 0; i < ic->parmBytes; i++)
2608 emitcode ("dec", "%s", spname);
2612 /* if we hade saved some registers then unsave them */
2614 unsaveRegisters (ic);
2616 /* if register bank was saved then pop them */
2618 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2621 /*-----------------------------------------------------------------*/
2622 /* genPcall - generates a call by pointer statement */
2623 /*-----------------------------------------------------------------*/
2625 genPcall (iCode * ic)
2628 symbol *rlbl = newiTempLabel (NULL);
2629 bool restoreBank=FALSE;
2631 D (emitcode (";", "genPcall ");
2635 /* if caller saves & we have not saved then */
2639 /* if we are calling a function that is not using
2640 the same register bank then we need to save the
2641 destination registers on the stack */
2642 dtype = operandType (IC_LEFT (ic));
2643 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2644 IFFUNC_ISISR (currFunc->type) &&
2645 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2646 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2650 /* push the return address on to the stack */
2651 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2652 emitcode ("push", "acc");
2653 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2654 emitcode ("push", "acc");
2656 if (options.model == MODEL_FLAT24)
2658 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2659 emitcode ("push", "acc");
2662 /* now push the calling address */
2663 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2665 pushSide (IC_LEFT (ic), FPTRSIZE);
2667 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2669 /* if send set is not empty the assign */
2672 genSend(reverseSet(_G.sendSet));
2676 emitcode ("ret", "");
2677 emitcode ("", "!tlabeldef", (rlbl->key + 100));
2680 /* if we need assign a result value */
2681 if ((IS_ITEMP (IC_RESULT (ic)) &&
2682 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2683 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2684 IS_TRUE_SYMOP (IC_RESULT (ic)))
2688 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2691 assignResultValue (IC_RESULT (ic));
2693 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2696 /* adjust the stack for parameters if
2701 if (options.stack10bit) {
2702 if (ic->parmBytes <= 10) {
2703 emitcode(";","stack adjustment for parms");
2704 for (i=0; i < ic->parmBytes ; i++) {
2705 emitcode("pop","acc");
2709 emitcode ("clr","c");
2710 emitcode ("mov","a,sp");
2711 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2712 emitcode ("mov","sp,a");
2713 emitcode ("mov","a,esp");
2714 emitcode ("anl","a,#3");
2715 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2716 emitcode ("mov","esp,a");
2720 if (ic->parmBytes > 3) {
2721 emitcode ("mov", "a,%s", spname);
2722 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2723 emitcode ("mov", "%s,a", spname);
2726 for (i = 0; i < ic->parmBytes; i++)
2727 emitcode ("dec", "%s", spname);
2731 /* if register bank was saved then unsave them */
2733 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2735 /* if we hade saved some registers then
2738 unsaveRegisters (ic);
2742 /*-----------------------------------------------------------------*/
2743 /* resultRemat - result is rematerializable */
2744 /*-----------------------------------------------------------------*/
2746 resultRemat (iCode * ic)
2748 if (SKIP_IC (ic) || ic->op == IFX)
2751 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2753 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2754 if (sym->remat && !POINTER_SET (ic))
2761 #if defined(__BORLANDC__) || defined(_MSC_VER)
2762 #define STRCASECMP stricmp
2764 #define STRCASECMP strcasecmp
2767 /*-----------------------------------------------------------------*/
2768 /* inExcludeList - return 1 if the string is in exclude Reg list */
2769 /*-----------------------------------------------------------------*/
2771 inExcludeList (char *s)
2775 if (options.excludeRegs[i] &&
2776 STRCASECMP (options.excludeRegs[i], "none") == 0)
2779 for (i = 0; options.excludeRegs[i]; i++)
2781 if (options.excludeRegs[i] &&
2782 STRCASECMP (s, options.excludeRegs[i]) == 0)
2788 /*-----------------------------------------------------------------*/
2789 /* genFunction - generated code for function entry */
2790 /*-----------------------------------------------------------------*/
2792 genFunction (iCode * ic)
2796 bool switchedPSW = FALSE;
2798 D (emitcode (";", "genFunction "););
2801 /* create the function header */
2802 emitcode (";", "-----------------------------------------");
2803 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2804 emitcode (";", "-----------------------------------------");
2806 emitcode ("", "%s:", sym->rname);
2807 ftype = operandType (IC_LEFT (ic));
2809 if (IFFUNC_ISNAKED(ftype))
2811 emitcode(";", "naked function: no prologue.");
2815 if (options.stack_probe)
2816 emitcode ("lcall","__stack_probe");
2817 /* if critical function then turn interrupts off */
2818 if (IFFUNC_ISCRITICAL (ftype))
2819 emitcode ("clr", "ea");
2821 /* here we need to generate the equates for the
2822 register bank if required */
2823 if (FUNC_REGBANK (ftype) != rbank)
2827 rbank = FUNC_REGBANK (ftype);
2828 for (i = 0; i < ds390_nRegs; i++)
2830 if (regs390[i].print) {
2831 if (strcmp (regs390[i].base, "0") == 0)
2832 emitcode ("", "%s !equ !constbyte",
2834 8 * rbank + regs390[i].offset);
2836 emitcode ("", "%s !equ %s + !constbyte",
2839 8 * rbank + regs390[i].offset);
2844 /* if this is an interrupt service routine then
2845 save acc, b, dpl, dph */
2846 if (IFFUNC_ISISR (sym->type))
2848 if (!inExcludeList ("acc"))
2849 emitcode ("push", "acc");
2850 if (!inExcludeList ("b"))
2851 emitcode ("push", "b");
2852 if (!inExcludeList ("dpl"))
2853 emitcode ("push", "dpl");
2854 if (!inExcludeList ("dph"))
2855 emitcode ("push", "dph");
2856 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2858 emitcode ("push", "dpx");
2859 /* Make sure we're using standard DPTR */
2860 emitcode ("push", "dps");
2861 emitcode ("mov", "dps,#0");
2862 if (options.stack10bit)
2864 /* This ISR could conceivably use DPTR2. Better save it. */
2865 emitcode ("push", "dpl1");
2866 emitcode ("push", "dph1");
2867 emitcode ("push", "dpx1");
2868 emitcode ("push", DP2_RESULT_REG);
2871 /* if this isr has no bank i.e. is going to
2872 run with bank 0 , then we need to save more
2874 if (!FUNC_REGBANK (sym->type))
2878 /* if this function does not call any other
2879 function then we can be economical and
2880 save only those registers that are used */
2881 if (!IFFUNC_HASFCALL(sym->type))
2884 /* if any registers used */
2887 /* save the registers used */
2888 for (i = 0; i < sym->regsUsed->size; i++)
2890 if (bitVectBitValue (sym->regsUsed, i) ||
2891 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2892 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2899 /* this function has a function call cannot
2900 determines register usage so we will have to push the
2902 saveRBank (0, ic, FALSE);
2903 if (options.parms_in_bank1) {
2904 for (i=0; i < 8 ; i++ ) {
2905 emitcode ("push","%s",rb1regs[i]);
2912 /* This ISR uses a non-zero bank.
2914 * We assume that the bank is available for our
2917 * However, if this ISR calls a function which uses some
2918 * other bank, we must save that bank entirely.
2920 unsigned long banksToSave = 0;
2922 if (IFFUNC_HASFCALL(sym->type))
2925 #define MAX_REGISTER_BANKS 4
2930 for (i = ic; i; i = i->next)
2932 if (i->op == ENDFUNCTION)
2934 /* we got to the end OK. */
2942 dtype = operandType (IC_LEFT(i));
2944 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2946 /* Mark this bank for saving. */
2947 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2949 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2953 banksToSave |= (1 << FUNC_REGBANK(dtype));
2956 /* And note that we don't need to do it in
2964 /* This is a mess; we have no idea what
2965 * register bank the called function might
2968 * The only thing I can think of to do is
2969 * throw a warning and hope.
2971 werror(W_FUNCPTR_IN_USING_ISR);
2975 if (banksToSave && options.useXstack)
2977 /* Since we aren't passing it an ic,
2978 * saveRBank will assume r0 is available to abuse.
2980 * So switch to our (trashable) bank now, so
2981 * the caller's R0 isn't trashed.
2983 emitcode ("push", "psw");
2984 emitcode ("mov", "psw,#!constbyte",
2985 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2989 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2991 if (banksToSave & (1 << ix))
2993 saveRBank(ix, NULL, FALSE);
2997 // jwk: this needs a closer look
2998 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3003 /* if callee-save to be used for this function
3004 then save the registers being used in this function */
3005 if (IFFUNC_CALLEESAVES(sym->type))
3009 /* if any registers used */
3012 /* save the registers used */
3013 for (i = 0; i < sym->regsUsed->size; i++)
3015 if (bitVectBitValue (sym->regsUsed, i) ||
3016 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3018 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3026 /* set the register bank to the desired value */
3027 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3030 emitcode ("push", "psw");
3031 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3034 if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3035 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3036 if (options.stack10bit) {
3037 emitcode ("push","_bpx");
3038 emitcode ("push","_bpx+1");
3039 emitcode ("mov","_bpx,%s",spname);
3040 emitcode ("mov","_bpx+1,esp");
3041 emitcode ("anl","_bpx+1,#3");
3043 if (options.useXstack) {
3044 emitcode ("mov", "r0,%s", spname);
3045 emitcode ("mov", "a,_bp");
3046 emitcode ("movx", "@r0,a");
3047 emitcode ("inc", "%s", spname);
3049 /* set up the stack */
3050 emitcode ("push", "_bp"); /* save the callers stack */
3052 emitcode ("mov", "_bp,%s", spname);
3056 /* adjust the stack for the function */
3059 if (options.stack10bit) {
3060 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3061 assert (sym->recvSize <= 4);
3062 if (sym->stack <= 8) {
3063 while (i--) emitcode ("push","acc");
3066 emitcode ("mov","a,sp");
3067 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3068 emitcode ("mov","sp,a");
3069 emitcode ("mov","a,esp");
3070 emitcode ("anl","a,#3");
3071 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3072 emitcode ("mov","esp,a");
3077 werror (W_STACK_OVERFLOW, sym->name);
3079 if (i > 3 && sym->recvSize < 4) {
3081 emitcode ("mov", "a,sp");
3082 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3083 emitcode ("mov", "sp,a");
3087 emitcode ("inc", "sp");
3094 emitcode ("mov", "a,_spx");
3095 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3096 emitcode ("mov", "_spx,a");
3101 /*-----------------------------------------------------------------*/
3102 /* genEndFunction - generates epilogue for functions */
3103 /*-----------------------------------------------------------------*/
3105 genEndFunction (iCode * ic)
3107 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3109 D (emitcode (";", "genEndFunction "););
3111 if (IFFUNC_ISNAKED(sym->type))
3113 emitcode(";", "naked function: no epilogue.");
3117 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3118 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3120 if (options.stack10bit) {
3122 emitcode ("mov", "sp,_bpx", spname);
3123 emitcode ("mov", "esp,_bpx+1", spname);
3126 emitcode ("mov", "%s,_bp", spname);
3130 /* if use external stack but some variables were
3131 added to the local stack then decrement the
3133 if (options.useXstack && sym->stack) {
3134 emitcode ("mov", "a,sp");
3135 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3136 emitcode ("mov", "sp,a");
3140 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3141 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3143 if (options.useXstack) {
3144 emitcode ("mov", "r0,%s", spname);
3145 emitcode ("movx", "a,@r0");
3146 emitcode ("mov", "_bp,a");
3147 emitcode ("dec", "%s", spname);
3149 if (options.stack10bit) {
3150 emitcode ("pop", "_bpx+1");
3151 emitcode ("pop", "_bpx");
3153 emitcode ("pop", "_bp");
3158 /* restore the register bank */
3159 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3161 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3162 || !options.useXstack)
3164 /* Special case of ISR using non-zero bank with useXstack
3167 emitcode ("pop", "psw");
3171 if (IFFUNC_ISISR (sym->type))
3174 /* now we need to restore the registers */
3175 /* if this isr has no bank i.e. is going to
3176 run with bank 0 , then we need to save more
3178 if (!FUNC_REGBANK (sym->type))
3181 /* if this function does not call any other
3182 function then we can be economical and
3183 save only those registers that are used */
3184 if (!IFFUNC_HASFCALL(sym->type))
3187 /* if any registers used */
3190 /* save the registers used */
3191 for (i = sym->regsUsed->size; i >= 0; i--)
3193 if (bitVectBitValue (sym->regsUsed, i) ||
3194 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3195 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3202 /* this function has a function call cannot
3203 determines register usage so we will have to pop the
3205 if (options.parms_in_bank1) {
3206 for (i = 7 ; i >= 0 ; i-- ) {
3207 emitcode ("pop","%s",rb1regs[i]);
3210 unsaveRBank (0, ic, FALSE);
3215 /* This ISR uses a non-zero bank.
3217 * Restore any register banks saved by genFunction
3220 // jwk: this needs a closer look
3221 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3224 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3226 if (savedBanks & (1 << ix))
3228 unsaveRBank(ix, NULL, FALSE);
3232 if (options.useXstack)
3234 /* Restore bank AFTER calling unsaveRBank,
3235 * since it can trash r0.
3237 emitcode ("pop", "psw");
3241 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3243 if (options.stack10bit)
3245 emitcode ("pop", DP2_RESULT_REG);
3246 emitcode ("pop", "dpx1");
3247 emitcode ("pop", "dph1");
3248 emitcode ("pop", "dpl1");
3250 emitcode ("pop", "dps");
3251 emitcode ("pop", "dpx");
3253 if (!inExcludeList ("dph"))
3254 emitcode ("pop", "dph");
3255 if (!inExcludeList ("dpl"))
3256 emitcode ("pop", "dpl");
3257 if (!inExcludeList ("b"))
3258 emitcode ("pop", "b");
3259 if (!inExcludeList ("acc"))
3260 emitcode ("pop", "acc");
3262 if (IFFUNC_ISCRITICAL (sym->type))
3263 emitcode ("setb", "ea");
3265 /* if debug then send end of function */
3266 if (options.debug && currFunc) {
3268 emitcode ("", "C$%s$%d$%d$%d ==.",
3269 FileBaseName (ic->filename), currFunc->lastLine,
3270 ic->level, ic->block);
3271 if (IS_STATIC (currFunc->etype))
3272 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3274 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3278 emitcode ("reti", "");
3282 if (IFFUNC_ISCRITICAL (sym->type))
3283 emitcode ("setb", "ea");
3285 if (IFFUNC_CALLEESAVES(sym->type))
3289 /* if any registers used */
3292 /* save the registers used */
3293 for (i = sym->regsUsed->size; i >= 0; i--)
3295 if (bitVectBitValue (sym->regsUsed, i) ||
3296 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3297 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3303 /* if debug then send end of function */
3304 if (options.debug && currFunc)
3307 emitcode ("", "C$%s$%d$%d$%d ==.",
3308 FileBaseName (ic->filename), currFunc->lastLine,
3309 ic->level, ic->block);
3310 if (IS_STATIC (currFunc->etype))
3311 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3313 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3317 emitcode ("ret", "");
3322 /*-----------------------------------------------------------------*/
3323 /* genJavaNativeRet - generate code for return JavaNative */
3324 /*-----------------------------------------------------------------*/
3325 static void genJavaNativeRet(iCode *ic)
3329 aopOp (IC_LEFT (ic), ic, FALSE,
3330 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3331 size = AOP_SIZE (IC_LEFT (ic));
3335 /* it is assigned to GPR0-R3 then push them */
3336 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3337 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3338 for (i = 0 ; i < size ; i++ ) {
3339 emitcode ("push","%s",
3340 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3342 for (i = (size-1) ; i >= 0 ; i--) {
3343 emitcode ("pop","a%s",javaRet[i]);
3346 for (i = 0 ; i < size ; i++)
3347 emitcode ("mov","%s,%s",javaRet[i],
3348 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3350 for (i = size ; i < 4 ; i++ )
3351 emitcode ("mov","%s,#0",javaRet[i]);
3355 /*-----------------------------------------------------------------*/
3356 /* genRet - generate code for return statement */
3357 /*-----------------------------------------------------------------*/
3361 int size, offset = 0, pushed = 0;
3363 D (emitcode (";", "genRet "););
3365 /* if we have no return value then
3366 just generate the "ret" */
3370 /* if this is a JavaNative function then return
3371 value in different register */
3372 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3373 genJavaNativeRet(ic);
3376 /* we have something to return then
3377 move the return value into place */
3378 aopOp (IC_LEFT (ic), ic, FALSE,
3379 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3380 size = AOP_SIZE (IC_LEFT (ic));
3382 _startLazyDPSEvaluation ();
3386 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3388 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3390 emitcode ("push", "%s", l);
3395 /* Since A is the last element of fReturn,
3396 * is is OK to clobber it in the aopGet.
3398 l = aopGet (AOP (IC_LEFT (ic)), offset,
3399 FALSE, FALSE, NULL);
3400 if (strcmp (fReturn[offset], l))
3401 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3404 _endLazyDPSEvaluation ();
3411 if (strcmp (fReturn[pushed], "a"))
3412 emitcode ("pop", fReturn[pushed]);
3414 emitcode ("pop", "acc");
3417 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3420 /* generate a jump to the return label
3421 if the next is not the return statement */
3422 if (!(ic->next && ic->next->op == LABEL &&
3423 IC_LABEL (ic->next) == returnLabel))
3425 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3429 /*-----------------------------------------------------------------*/
3430 /* genLabel - generates a label */
3431 /*-----------------------------------------------------------------*/
3433 genLabel (iCode * ic)
3435 /* special case never generate */
3436 if (IC_LABEL (ic) == entryLabel)
3439 D (emitcode (";", "genLabel ");
3442 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3445 /*-----------------------------------------------------------------*/
3446 /* genGoto - generates a ljmp */
3447 /*-----------------------------------------------------------------*/
3449 genGoto (iCode * ic)
3451 D (emitcode (";", "genGoto ");
3453 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3456 /*-----------------------------------------------------------------*/
3457 /* findLabelBackwards: walks back through the iCode chain looking */
3458 /* for the given label. Returns number of iCode instructions */
3459 /* between that label and given ic. */
3460 /* Returns zero if label not found. */
3461 /*-----------------------------------------------------------------*/
3463 findLabelBackwards (iCode * ic, int key)
3472 /* If we have any pushes or pops, we cannot predict the distance.
3473 I don't like this at all, this should be dealt with in the
3475 if (ic->op == IPUSH || ic->op == IPOP) {
3479 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3481 /* printf("findLabelBackwards = %d\n", count); */
3489 /*-----------------------------------------------------------------*/
3490 /* genPlusIncr :- does addition with increment if possible */
3491 /*-----------------------------------------------------------------*/
3493 genPlusIncr (iCode * ic)
3495 unsigned int icount;
3496 unsigned int size = getDataSize (IC_RESULT (ic));
3498 /* will try to generate an increment */
3499 /* if the right side is not a literal
3501 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3504 /* if the literal value of the right hand side
3505 is greater than 4 then it is not worth it */
3506 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3509 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3510 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3512 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3516 /* if increment 16 bits in register */
3518 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3519 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3520 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3529 /* If the next instruction is a goto and the goto target
3530 * is <= 5 instructions previous to this, we can generate
3531 * jumps straight to that target.
3533 if (ic->next && ic->next->op == GOTO
3534 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3537 D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3538 tlbl = IC_LABEL (ic->next);
3543 tlbl = newiTempLabel (NULL);
3547 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3548 emitcode ("inc", "%s", l);
3550 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3551 IS_AOP_PREG (IC_RESULT (ic)))
3553 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3557 emitcode ("clr", "a");
3558 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3561 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
3562 emitcode ("inc", "%s", l);
3565 if (!strcmp(l, "acc"))
3567 emitcode("jnz", "!tlabel", tlbl->key + 100);
3569 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3570 IS_AOP_PREG (IC_RESULT (ic)))
3572 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3576 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3579 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3580 emitcode ("inc", "%s", l);
3584 if (!strcmp(l, "acc"))
3586 emitcode("jnz", "!tlabel", tlbl->key + 100);
3588 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3589 IS_AOP_PREG (IC_RESULT (ic)))
3591 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3595 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3598 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3599 emitcode ("inc", "%s", l); }
3603 emitcode ("", "!tlabeldef", tlbl->key + 100);
3608 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3609 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
3610 options.model == MODEL_FLAT24 ) {
3614 emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3616 emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3618 emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3621 while (icount--) emitcode ("inc","dptr");
3625 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3626 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3628 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3629 while (icount--) emitcode ("inc","dptr");
3630 emitcode ("mov","dps,#0");
3634 /* if the sizes are greater than 1 then we cannot */
3635 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3636 AOP_SIZE (IC_LEFT (ic)) > 1)
3639 /* we can if the aops of the left & result match or
3640 if they are in registers and the registers are the
3643 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3644 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3645 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3650 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3651 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3652 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3657 _startLazyDPSEvaluation ();
3660 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3662 _endLazyDPSEvaluation ();
3671 /*-----------------------------------------------------------------*/
3672 /* outBitAcc - output a bit in acc */
3673 /*-----------------------------------------------------------------*/
3675 outBitAcc (operand * result)
3677 symbol *tlbl = newiTempLabel (NULL);
3678 /* if the result is a bit */
3679 if (AOP_TYPE (result) == AOP_CRY)
3681 aopPut (AOP (result), "a", 0);
3685 emitcode ("jz", "!tlabel", tlbl->key + 100);
3686 emitcode ("mov", "a,%s", one);
3687 emitcode ("", "!tlabeldef", tlbl->key + 100);
3692 /*-----------------------------------------------------------------*/
3693 /* genPlusBits - generates code for addition of two bits */
3694 /*-----------------------------------------------------------------*/
3696 genPlusBits (iCode * ic)
3698 D (emitcode (";", "genPlusBits "););
3700 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3702 symbol *lbl = newiTempLabel (NULL);
3703 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3704 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3705 emitcode ("cpl", "c");
3706 emitcode ("", "!tlabeldef", (lbl->key + 100));
3707 outBitC (IC_RESULT (ic));
3711 emitcode ("clr", "a");
3712 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3713 emitcode ("rlc", "a");
3714 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3715 emitcode ("addc", "a,#0");
3716 outAcc (IC_RESULT (ic));
3721 adjustArithmeticResult (iCode * ic)
3723 if (opIsGptr (IC_RESULT (ic)) &&
3724 opIsGptr (IC_LEFT (ic)) &&
3725 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3727 aopPut (AOP (IC_RESULT (ic)),
3728 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3732 if (opIsGptr (IC_RESULT (ic)) &&
3733 opIsGptr (IC_RIGHT (ic)) &&
3734 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3736 aopPut (AOP (IC_RESULT (ic)),
3737 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3741 if (opIsGptr (IC_RESULT (ic)) &&
3742 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3743 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3744 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3745 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3748 SNPRINTF (buff, sizeof(buff),
3749 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3750 aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3754 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3755 // generates the result if possible. If result is generated, returns TRUE; otherwise
3756 // returns false and caller must deal with fact that result isn't aopOp'd.
3757 bool aopOp3(iCode * ic)
3759 bool dp1InUse, dp2InUse;
3762 // First, generate the right opcode. DPTR may be used if neither left nor result are
3765 // D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3766 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3767 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3768 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3770 // D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3771 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3772 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3773 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3777 // Right uses DPTR unless left or result is an AOP_STR.
3778 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)));
3780 // if the right used DPTR, left MUST use DPTR2.
3781 // if the right used DPTR2, left MUST use DPTR.
3782 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3783 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3784 // enabling us to assign DPTR to result.
3786 if (AOP_USESDPTR(IC_RIGHT(ic)))
3790 else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3796 if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3806 aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3808 // We've op'd the left & right. So, if left or right are the same operand as result,
3809 // we know aopOp will succeed, and we can just do it & bail.
3810 if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3811 isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3813 // D(emitcode(";", "aopOp3: (left | right) & result equal"););
3814 aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3818 // Note which dptrs are currently in use.
3819 dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3820 dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3822 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
3824 if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3829 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3830 if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3835 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
3836 if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3841 aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3843 // Some sanity checking...
3844 if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
3847 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
3848 __FILE__, __LINE__, ic->filename, ic->lineno);
3849 emitcode(";", ">>> unexpected DPTR here.");
3852 if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
3855 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
3856 __FILE__, __LINE__, ic->filename, ic->lineno);
3857 emitcode(";", ">>> unexpected DPTR2 here.");
3863 // Macro to aopOp all three operands of an ic. If this cannot be done,
3864 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3865 // will be set TRUE. The caller must then handle the case specially, noting
3866 // that the IC_RESULT operand is not aopOp'd.
3868 #define AOP_OP_3_NOFATAL(ic, rc) \
3869 do { rc = !aopOp3(ic); } while (0)
3871 // aopOp the left & right operands of an ic.
3872 #define AOP_OP_2(ic) \
3873 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3874 aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3876 // convienience macro.
3877 #define AOP_SET_LOCALS(ic) \
3878 left = IC_LEFT(ic); \
3879 right = IC_RIGHT(ic); \
3880 result = IC_RESULT(ic);
3883 // Given an integer value of pushedSize bytes on the stack,
3884 // adjust it to be resultSize bytes, either by discarding
3885 // the most significant bytes or by zero-padding.
3887 // On exit from this macro, pushedSize will have been adjusted to
3888 // equal resultSize, and ACC may be trashed.
3889 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3890 /* If the pushed data is bigger than the result, \
3891 * simply discard unused bytes. Icky, but works. \
3893 while (pushedSize > resultSize) \
3895 D (emitcode (";", "discarding unused result byte."););\
3896 emitcode ("pop", "acc"); \
3899 if (pushedSize < resultSize) \
3901 emitcode ("clr", "a"); \
3902 /* Conversly, we haven't pushed enough here. \
3903 * just zero-pad, and all is well. \
3905 while (pushedSize < resultSize) \
3907 emitcode("push", "acc"); \
3911 assert(pushedSize == resultSize);
3913 /*-----------------------------------------------------------------*/
3914 /* genPlus - generates code for addition */
3915 /*-----------------------------------------------------------------*/
3917 genPlus (iCode * ic)
3919 int size, offset = 0;
3923 D (emitcode (";", "genPlus "););
3925 /* special cases :- */
3926 if ( AOP_IS_STR(IC_LEFT(ic)) &&
3927 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3928 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3929 size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3931 while (size--) emitcode ("inc","dptr");
3933 emitcode ("mov","a,dpl");
3934 emitcode ("add","a,#!constbyte",size & 0xff);
3935 emitcode ("mov","dpl,a");
3936 emitcode ("mov","a,dph");
3937 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3938 emitcode ("mov","dph,a");
3939 emitcode ("mov","a,dpx");
3940 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3941 emitcode ("mov","dpx,a");
3943 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3946 if ( IS_SYMOP(IC_LEFT(ic)) &&
3947 OP_SYMBOL(IC_LEFT(ic))->remat &&
3948 isOperandInFarSpace(IC_RIGHT(ic))) {
3949 operand *op = IC_RIGHT(ic);
3950 IC_RIGHT(ic) = IC_LEFT(ic);
3954 AOP_OP_3_NOFATAL (ic, pushResult);
3958 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3963 /* if literal, literal on the right or
3964 if left requires ACC or right is already
3966 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3967 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3968 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3970 operand *t = IC_RIGHT (ic);
3971 IC_RIGHT (ic) = IC_LEFT (ic);
3973 emitcode (";", "Swapped plus args.");
3976 /* if both left & right are in bit
3978 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3979 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3985 /* if left in bit space & right literal */
3986 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3987 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3989 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3990 /* if result in bit space */
3991 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3993 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3994 emitcode ("cpl", "c");
3995 outBitC (IC_RESULT (ic));
3999 size = getDataSize (IC_RESULT (ic));
4000 _startLazyDPSEvaluation ();
4003 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4004 emitcode ("addc", "a,#0");
4005 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4007 _endLazyDPSEvaluation ();
4012 /* if I can do an increment instead
4013 of add then GOOD for ME */
4014 if (genPlusIncr (ic) == TRUE)
4016 emitcode (";", "did genPlusIncr");
4021 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4023 _startLazyDPSEvaluation ();
4026 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4028 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4030 emitcode ("add", "a,%s",
4031 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, DP2_RESULT_REG));
4033 emitcode ("addc", "a,%s",
4034 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, DP2_RESULT_REG));
4038 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4040 /* right is going to use ACC or we would have taken the
4043 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4045 D(emitcode(";", "+ AOP_ACC special case."););
4046 emitcode("xch", "a, %s", DP2_RESULT_REG);
4048 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4051 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4054 emitcode("add", "a, %s", DP2_RESULT_REG);
4058 emitcode ("add", "a,%s",
4059 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4065 emitcode ("addc", "a,%s",
4066 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4072 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4076 emitcode ("push", "acc");
4080 _endLazyDPSEvaluation ();
4084 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4086 size = getDataSize (IC_LEFT (ic));
4087 rSize = getDataSize (IC_RESULT (ic));
4089 ADJUST_PUSHED_RESULT(size, rSize);
4091 _startLazyDPSEvaluation ();
4094 emitcode ("pop", "acc");
4095 aopPut (AOP (IC_RESULT (ic)), "a", size);
4097 _endLazyDPSEvaluation ();
4100 adjustArithmeticResult (ic);
4103 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4104 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4105 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4108 /*-----------------------------------------------------------------*/
4109 /* genMinusDec :- does subtraction with deccrement if possible */
4110 /*-----------------------------------------------------------------*/
4112 genMinusDec (iCode * ic)
4114 unsigned int icount;
4115 unsigned int size = getDataSize (IC_RESULT (ic));
4117 /* will try to generate an increment */
4118 /* if the right side is not a literal
4120 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4123 /* if the literal value of the right hand side
4124 is greater than 4 then it is not worth it */
4125 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4128 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4129 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4131 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4135 /* if decrement 16 bits in register */
4136 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4137 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4138 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4147 /* If the next instruction is a goto and the goto target
4148 * is <= 5 instructions previous to this, we can generate
4149 * jumps straight to that target.
4151 if (ic->next && ic->next->op == GOTO
4152 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4155 emitcode (";", "tail decrement optimized (range %d)", labelRange);
4156 tlbl = IC_LABEL (ic->next);
4161 tlbl = newiTempLabel (NULL);
4165 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4166 emitcode ("dec", "%s", l);
4168 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4169 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4170 IS_AOP_PREG (IC_RESULT (ic)))
4172 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4176 emitcode ("mov", "a,#!constbyte",0xff);
4177 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4179 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, NULL, NULL);
4180 emitcode ("dec", "%s", l);
4183 if (!strcmp(l, "acc"))
4185 emitcode("jnz", "!tlabel", tlbl->key + 100);
4187 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4188 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4189 IS_AOP_PREG (IC_RESULT (ic)))
4191 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4195 emitcode ("mov", "a,#!constbyte",0xff);
4196 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4198 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, NULL, NULL);
4199 emitcode ("dec", "%s", l);
4203 if (!strcmp(l, "acc"))
4205 emitcode("jnz", "!tlabel", tlbl->key + 100);
4207 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4208 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4209 IS_AOP_PREG (IC_RESULT (ic)))
4211 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4215 emitcode ("mov", "a,#!constbyte",0xff);
4216 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4218 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, NULL, NULL);
4219 emitcode ("dec", "%s", l);
4223 emitcode ("", "!tlabeldef", tlbl->key + 100);
4228 /* if the sizes are greater than 1 then we cannot */
4229 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4230 AOP_SIZE (IC_LEFT (ic)) > 1)
4233 /* we can if the aops of the left & result match or
4234 if they are in registers and the registers are the
4237 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4238 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4239 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4242 _startLazyDPSEvaluation ();
4245 emitcode ("dec", "%s",
4246 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4248 _endLazyDPSEvaluation ();
4256 /*-----------------------------------------------------------------*/
4257 /* addSign - complete with sign */
4258 /*-----------------------------------------------------------------*/
4260 addSign (operand * result, int offset, int sign)
4262 int size = (getDataSize (result) - offset);
4265 _startLazyDPSEvaluation();
4268 emitcode ("rlc", "a");
4269 emitcode ("subb", "a,acc");
4272 aopPut (AOP (result), "a", offset++);
4279 aopPut (AOP (result), zero, offset++);
4282 _endLazyDPSEvaluation();
4286 /*-----------------------------------------------------------------*/
4287 /* genMinusBits - generates code for subtraction of two bits */
4288 /*-----------------------------------------------------------------*/
4290 genMinusBits (iCode * ic)
4292 symbol *lbl = newiTempLabel (NULL);
4294 D (emitcode (";", "genMinusBits "););
4296 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4298 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4299 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4300 emitcode ("cpl", "c");
4301 emitcode ("", "!tlabeldef", (lbl->key + 100));
4302 outBitC (IC_RESULT (ic));
4306 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4307 emitcode ("subb", "a,acc");
4308 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4309 emitcode ("inc", "a");
4310 emitcode ("", "!tlabeldef", (lbl->key + 100));
4311 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4312 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4316 /*-----------------------------------------------------------------*/
4317 /* genMinus - generates code for subtraction */
4318 /*-----------------------------------------------------------------*/
4320 genMinus (iCode * ic)
4322 int size, offset = 0;
4327 D (emitcode (";", "genMinus "););
4329 AOP_OP_3_NOFATAL(ic, pushResult);
4333 /* special cases :- */
4334 /* if both left & right are in bit space */
4335 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4336 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4342 /* if I can do an decrement instead
4343 of subtract then GOOD for ME */
4344 if (genMinusDec (ic) == TRUE)
4349 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4351 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4357 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4362 /* if literal, add a,#-lit, else normal subb */
4363 _startLazyDPSEvaluation ();
4365 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4366 if (AOP_USESDPTR(IC_RIGHT(ic))) {
4367 emitcode ("mov","b,%s",
4368 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4369 MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4370 emitcode ("subb","a,b");
4372 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4373 emitcode ("subb", "a,%s",
4374 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE,
4378 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4379 /* first add without previous c */
4381 if (!size && lit==-1) {
4382 emitcode ("dec", "a");
4384 emitcode ("add", "a,#!constbyte",
4385 (unsigned int) (lit & 0x0FFL));
4388 emitcode ("addc", "a,#!constbyte",
4389 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4394 emitcode ("push", "acc");
4396 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4400 _endLazyDPSEvaluation ();
4404 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4406 size = getDataSize (IC_LEFT (ic));
4407 rSize = getDataSize (IC_RESULT (ic));
4409 ADJUST_PUSHED_RESULT(size, rSize);
4411 _startLazyDPSEvaluation ();
4414 emitcode ("pop", "acc");
4415 aopPut (AOP (IC_RESULT (ic)), "a", size);
4417 _endLazyDPSEvaluation ();
4420 adjustArithmeticResult (ic);
4423 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4424 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4425 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4429 /*-----------------------------------------------------------------*/
4430 /* genMultbits :- multiplication of bits */
4431 /*-----------------------------------------------------------------*/
4433 genMultbits (operand * left,
4438 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4439 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4440 aopOp(result, ic, TRUE, FALSE);
4445 /*-----------------------------------------------------------------*/
4446 /* genMultOneByte : 8*8=8/16 bit multiplication */
4447 /*-----------------------------------------------------------------*/
4449 genMultOneByte (operand * left,
4454 sym_link *opetype = operandType (result);
4458 /* (if two literals: the value is computed before) */
4459 /* if one literal, literal on the right */
4460 if (AOP_TYPE (left) == AOP_LIT)
4465 emitcode (";", "swapped left and right");
4468 if (SPEC_USIGN(opetype)
4469 // ignore the sign of left and right, what else can we do?
4470 || (SPEC_USIGN(operandType(left)) &&
4471 SPEC_USIGN(operandType(right)))) {
4472 // just an unsigned 8*8=8/16 multiply
4473 //emitcode (";","unsigned");
4474 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4475 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4476 emitcode ("mul", "ab");
4478 _G.accInUse++; _G.bInUse++;
4479 aopOp(result, ic, TRUE, FALSE);
4481 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4483 // this should never happen
4484 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4485 AOP_SIZE(result), __FILE__, lineno);
4489 aopPut (AOP (result), "a", 0);
4490 _G.accInUse--; _G.bInUse--;
4491 if (AOP_SIZE(result)==2)
4493 aopPut (AOP (result), "b", 1);
4498 // we have to do a signed multiply
4500 emitcode (";", "signed");
4501 emitcode ("clr", "F0"); // reset sign flag
4502 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4504 lbl=newiTempLabel(NULL);
4505 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4506 // left side is negative, 8-bit two's complement, this fails for -128
4507 emitcode ("setb", "F0"); // set sign flag
4508 emitcode ("cpl", "a");
4509 emitcode ("inc", "a");
4511 emitcode ("", "!tlabeldef", lbl->key+100);
4514 if (AOP_TYPE(right)==AOP_LIT) {
4515 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4516 /* AND literal negative */
4517 if ((int) val < 0) {
4518 emitcode ("cpl", "F0"); // complement sign flag
4519 emitcode ("mov", "b,#!constbyte", -val);
4521 emitcode ("mov", "b,#!constbyte", val);
4524 lbl=newiTempLabel(NULL);
4525 emitcode ("mov", "b,a");
4526 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4527 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4528 // right side is negative, 8-bit two's complement
4529 emitcode ("cpl", "F0"); // complement sign flag
4530 emitcode ("cpl", "a");
4531 emitcode ("inc", "a");
4532 emitcode ("", "!tlabeldef", lbl->key+100);
4534 emitcode ("mul", "ab");
4536 _G.accInUse++;_G.bInUse++;
4537 aopOp(result, ic, TRUE, FALSE);
4539 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4541 // this should never happen
4542 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4543 AOP_SIZE(result), __FILE__, lineno);
4547 lbl=newiTempLabel(NULL);
4548 emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4549 // only ONE op was negative, we have to do a 8/16-bit two's complement
4550 emitcode ("cpl", "a"); // lsb
4551 if (AOP_SIZE(result)==1) {
4552 emitcode ("inc", "a");
4554 emitcode ("add", "a,#1");
4555 emitcode ("xch", "a,b");
4556 emitcode ("cpl", "a"); // msb
4557 emitcode ("addc", "a,#0");
4558 emitcode ("xch", "a,b");
4561 emitcode ("", "!tlabeldef", lbl->key+100);
4562 aopPut (AOP (result), "a", 0);
4563 _G.accInUse--;_G.bInUse--;
4564 if (AOP_SIZE(result)==2) {
4565 aopPut (AOP (result), "b", 1);
4569 /*-----------------------------------------------------------------*/
4570 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4571 /*-----------------------------------------------------------------*/
4572 static void genMultTwoByte (operand *left, operand *right,
4573 operand *result, iCode *ic)
4575 sym_link *retype = getSpec(operandType(right));
4576 sym_link *letype = getSpec(operandType(left));
4577 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4580 if (AOP_TYPE (left) == AOP_LIT) {
4585 /* save EA bit in F1 */
4586 lbl = newiTempLabel(NULL);
4587 emitcode ("setb","F1");
4588 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4589 emitcode ("clr","F1");
4590 emitcode("","!tlabeldef",lbl->key+100);
4592 /* load up MB with right */
4594 emitcode("clr","F0");
4595 if (AOP_TYPE(right) == AOP_LIT) {
4596 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4598 emitcode("setb","F0");
4601 emitcode ("mov","mb,#!constbyte",val & 0xff);
4602 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4604 lbl = newiTempLabel(NULL);
4605 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4606 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4607 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4608 emitcode ("xch", "a,b");
4609 emitcode ("cpl","a");
4610 emitcode ("add", "a,#1");
4611 emitcode ("xch", "a,b");
4612 emitcode ("cpl", "a"); // msb
4613 emitcode ("addc", "a,#0");
4614 emitcode ("setb","F0");
4615 emitcode ("","!tlabeldef",lbl->key+100);
4616 emitcode ("mov","mb,b");
4617 emitcode ("mov","mb,a");
4620 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4621 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4623 /* load up MA with left */
4625 lbl = newiTempLabel(NULL);
4626 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4627 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4628 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4629 emitcode ("xch", "a,b");
4630 emitcode ("cpl","a");
4631 emitcode ("add", "a,#1");
4632 emitcode ("xch", "a,b");
4633 emitcode ("cpl", "a"); // msb
4634 emitcode ("addc","a,#0");
4635 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4636 emitcode ("setb","F0");
4637 emitcode ("","!tlabeldef",lbl->key+100);
4638 emitcode ("mov","ma,b");
4639 emitcode ("mov","ma,a");
4641 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4642 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4644 /* wait for multiplication to finish */
4645 lbl = newiTempLabel(NULL);
4646 emitcode("","!tlabeldef", lbl->key+100);
4647 emitcode("mov","a,mcnt1");
4648 emitcode("anl","a,#!constbyte",0x80);
4649 emitcode("jnz","!tlabel",lbl->key+100);
4651 freeAsmop (left, NULL, ic, TRUE);
4652 freeAsmop (right, NULL, ic,TRUE);
4653 aopOp(result, ic, TRUE, FALSE);
4655 /* if unsigned then simple */
4657 emitcode ("mov","a,ma");
4658 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4659 emitcode ("mov","a,ma");
4660 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4661 aopPut(AOP(result),"ma",1);
4662 aopPut(AOP(result),"ma",0);
4664 emitcode("push","ma");
4665 emitcode("push","ma");
4666 emitcode("push","ma");
4668 /* negate result if needed */
4669 lbl = newiTempLabel(NULL);
4670 emitcode("jnb","F0,!tlabel",lbl->key+100);
4671 emitcode("cpl","a");
4672 emitcode("add","a,#1");
4673 emitcode("","!tlabeldef", lbl->key+100);
4674 if (AOP_TYPE(result) == AOP_ACC)
4676 D(emitcode(";", "ACC special case."););
4677 /* We know result is the only live aop, and
4678 * it's obviously not a DPTR2, so AP is available.
4680 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4684 aopPut(AOP(result),"a",0);
4687 emitcode("pop","acc");
4688 lbl = newiTempLabel(NULL);
4689 emitcode("jnb","F0,!tlabel",lbl->key+100);
4690 emitcode("cpl","a");
4691 emitcode("addc","a,#0");
4692 emitcode("","!tlabeldef", lbl->key+100);
4693 aopPut(AOP(result),"a",1);
4694 emitcode("pop","acc");
4695 if (AOP_SIZE(result) >= 3) {
4696 lbl = newiTempLabel(NULL);
4697 emitcode("jnb","F0,!tlabel",lbl->key+100);
4698 emitcode("cpl","a");
4699 emitcode("addc","a,#0");
4700 emitcode("","!tlabeldef", lbl->key+100);
4701 aopPut(AOP(result),"a",2);
4703 emitcode("pop","acc");
4704 if (AOP_SIZE(result) >= 4) {
4705 lbl = newiTempLabel(NULL);
4706 emitcode("jnb","F0,!tlabel",lbl->key+100);
4707 emitcode("cpl","a");
4708 emitcode("addc","a,#0");
4709 emitcode("","!tlabeldef", lbl->key+100);
4710 aopPut(AOP(result),"a",3);
4712 if (AOP_TYPE(result) == AOP_ACC)
4714 /* We stashed the result away above. */
4715 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4719 freeAsmop (result, NULL, ic, TRUE);
4721 /* restore EA bit in F1 */
4722 lbl = newiTempLabel(NULL);
4723 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4724 emitcode ("setb","EA");
4725 emitcode("","!tlabeldef",lbl->key+100);
4729 /*-----------------------------------------------------------------*/
4730 /* genMult - generates code for multiplication */
4731 /*-----------------------------------------------------------------*/
4733 genMult (iCode * ic)
4735 operand *left = IC_LEFT (ic);
4736 operand *right = IC_RIGHT (ic);
4737 operand *result = IC_RESULT (ic);
4739 D (emitcode (";", "genMult "););
4741 /* assign the amsops */
4744 /* special cases first */
4746 if (AOP_TYPE (left) == AOP_CRY &&
4747 AOP_TYPE (right) == AOP_CRY)
4749 genMultbits (left, right, result, ic);
4753 /* if both are of size == 1 */
4754 if (AOP_SIZE (left) == 1 &&
4755 AOP_SIZE (right) == 1)
4757 genMultOneByte (left, right, result, ic);
4761 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4762 /* use the ds390 ARITHMETIC accel UNIT */
4763 genMultTwoByte (left, right, result, ic);
4766 /* should have been converted to function call */
4770 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4771 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4772 freeAsmop (result, NULL, ic, TRUE);
4775 /*-----------------------------------------------------------------*/
4776 /* genDivbits :- division of bits */
4777 /*-----------------------------------------------------------------*/
4779 genDivbits (operand * left,
4787 /* the result must be bit */
4788 LOAD_AB_FOR_DIV (left, right, l);
4789 emitcode ("div", "ab");
4790 emitcode ("rrc", "a");
4791 aopOp(result, ic, TRUE, FALSE);
4793 aopPut (AOP (result), "c", 0);
4796 /*-----------------------------------------------------------------*/
4797 /* genDivOneByte : 8 bit division */
4798 /*-----------------------------------------------------------------*/
4800 genDivOneByte (operand * left,
4805 sym_link *opetype = operandType (result);
4811 /* signed or unsigned */
4812 if (SPEC_USIGN (opetype))
4814 /* unsigned is easy */
4815 LOAD_AB_FOR_DIV (left, right, l);
4816 emitcode ("div", "ab");
4819 aopOp(result, ic, TRUE, FALSE);
4820 aopPut (AOP (result), "a", 0);
4823 size = AOP_SIZE (result) - 1;
4827 aopPut (AOP (result), zero, offset++);
4832 /* signed is a little bit more difficult */
4834 /* save the signs of the operands */
4835 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4836 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4837 emitcode ("push", "acc"); /* save it on the stack */
4839 /* now sign adjust for both left & right */
4840 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4841 lbl = newiTempLabel (NULL);
4842 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4843 emitcode ("cpl", "a");
4844 emitcode ("inc", "a");
4845 emitcode ("", "!tlabeldef", (lbl->key + 100));
4846 emitcode ("mov", "b,a");
4848 /* sign adjust left side */
4849 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4851 lbl = newiTempLabel (NULL);
4852 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4853 emitcode ("cpl", "a");
4854 emitcode ("inc", "a");
4855 emitcode ("", "!tlabeldef", (lbl->key + 100));
4857 /* now the division */
4858 emitcode ("nop", "; workaround for DS80C390 div bug.");
4859 emitcode ("div", "ab");
4860 /* we are interested in the lower order
4862 emitcode ("mov", "b,a");
4863 lbl = newiTempLabel (NULL);
4864 emitcode ("pop", "acc");
4865 /* if there was an over flow we don't
4866 adjust the sign of the result */
4867 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4868 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4870 emitcode ("clr", "a");
4871 emitcode ("subb", "a,b");
4872 emitcode ("mov", "b,a");
4873 emitcode ("", "!tlabeldef", (lbl->key + 100));
4875 /* now we are done */
4876 _G.accInUse++; _G.bInUse++;
4877 aopOp(result, ic, TRUE, FALSE);
4879 aopPut (AOP (result), "b", 0);
4881 size = AOP_SIZE (result) - 1;
4885 emitcode ("mov", "c,b.7");
4886 emitcode ("subb", "a,acc");
4890 aopPut (AOP (result), "a", offset++);
4892 _G.accInUse--; _G.bInUse--;
4896 /*-----------------------------------------------------------------*/
4897 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4898 /*-----------------------------------------------------------------*/
4899 static void genDivTwoByte (operand *left, operand *right,
4900 operand *result, iCode *ic)
4902 sym_link *retype = getSpec(operandType(right));
4903 sym_link *letype = getSpec(operandType(left));
4904 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4907 /* save EA bit in F1 */
4908 lbl = newiTempLabel(NULL);
4909 emitcode ("setb","F1");
4910 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4911 emitcode ("clr","F1");
4912 emitcode("","!tlabeldef",lbl->key+100);
4914 /* load up MA with left */
4916 emitcode("clr","F0");
4917 lbl = newiTempLabel(NULL);
4918 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4919 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4920 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4921 emitcode ("xch", "a,b");
4922 emitcode ("cpl","a");
4923 emitcode ("add", "a,#1");
4924 emitcode ("xch", "a,b");
4925 emitcode ("cpl", "a"); // msb
4926 emitcode ("addc","a,#0");
4927 emitcode ("setb","F0");
4928 emitcode ("","!tlabeldef",lbl->key+100);
4929 emitcode ("mov","ma,b");
4930 emitcode ("mov","ma,a");
4932 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4933 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4936 /* load up MB with right */
4938 if (AOP_TYPE(right) == AOP_LIT) {
4939 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4941 lbl = newiTempLabel(NULL);
4942 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4943 emitcode("setb","F0");
4944 emitcode ("","!tlabeldef",lbl->key+100);
4947 emitcode ("mov","mb,#!constbyte",val & 0xff);
4948 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4950 lbl = newiTempLabel(NULL);
4951 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4952 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4953 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4954 emitcode ("xch", "a,b");
4955 emitcode ("cpl","a");
4956 emitcode ("add", "a,#1");
4957 emitcode ("xch", "a,b");
4958 emitcode ("cpl", "a"); // msb
4959 emitcode ("addc", "a,#0");
4960 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4961 emitcode ("setb","F0");
4962 emitcode ("","!tlabeldef",lbl->key+100);
4963 emitcode ("mov","mb,b");
4964 emitcode ("mov","mb,a");
4967 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4968 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4971 /* wait for multiplication to finish */
4972 lbl = newiTempLabel(NULL);
4973 emitcode("","!tlabeldef", lbl->key+100);
4974 emitcode("mov","a,mcnt1");
4975 emitcode("anl","a,#!constbyte",0x80);
4976 emitcode("jnz","!tlabel",lbl->key+100);
4978 freeAsmop (left, NULL, ic, TRUE);
4979 freeAsmop (right, NULL, ic,TRUE);
4980 aopOp(result, ic, TRUE, FALSE);
4982 /* if unsigned then simple */
4984 aopPut(AOP(result),"ma",1);
4985 aopPut(AOP(result),"ma",0);
4987 emitcode("push","ma");
4989 /* negate result if needed */
4990 lbl = newiTempLabel(NULL);
4991 emitcode("jnb","F0,!tlabel",lbl->key+100);
4992 emitcode("cpl","a");
4993 emitcode("add","a,#1");
4994 emitcode("","!tlabeldef", lbl->key+100);
4995 aopPut(AOP(result),"a",0);
4996 emitcode("pop","acc");
4997 lbl = newiTempLabel(NULL);
4998 emitcode("jnb","F0,!tlabel",lbl->key+100);
4999 emitcode("cpl","a");
5000 emitcode("addc","a,#0");
5001 emitcode("","!tlabeldef", lbl->key+100);
5002 aopPut(AOP(result),"a",1);
5004 freeAsmop (result, NULL, ic, TRUE);
5005 /* restore EA bit in F1 */
5006 lbl = newiTempLabel(NULL);
5007 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5008 emitcode ("setb","EA");
5009 emitcode("","!tlabeldef",lbl->key+100);
5013 /*-----------------------------------------------------------------*/
5014 /* genDiv - generates code for division */
5015 /*-----------------------------------------------------------------*/
5019 operand *left = IC_LEFT (ic);
5020 operand *right = IC_RIGHT (ic);
5021 operand *result = IC_RESULT (ic);
5023 D (emitcode (";", "genDiv "););
5025 /* assign the amsops */
5028 /* special cases first */
5030 if (AOP_TYPE (left) == AOP_CRY &&
5031 AOP_TYPE (right) == AOP_CRY)
5033 genDivbits (left, right, result, ic);
5037 /* if both are of size == 1 */
5038 if (AOP_SIZE (left) == 1 &&
5039 AOP_SIZE (right) == 1)
5041 genDivOneByte (left, right, result, ic);
5045 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5046 /* use the ds390 ARITHMETIC accel UNIT */
5047 genDivTwoByte (left, right, result, ic);
5050 /* should have been converted to function call */
5053 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5054 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5055 freeAsmop (result, NULL, ic, TRUE);
5058 /*-----------------------------------------------------------------*/
5059 /* genModbits :- modulus of bits */
5060 /*-----------------------------------------------------------------*/
5062 genModbits (operand * left,
5070 /* the result must be bit */
5071 LOAD_AB_FOR_DIV (left, right, l);
5072 emitcode ("div", "ab");
5073 emitcode ("mov", "a,b");
5074 emitcode ("rrc", "a");
5075 aopOp(result, ic, TRUE, FALSE);
5076 aopPut (AOP (result), "c", 0);
5079 /*-----------------------------------------------------------------*/
5080 /* genModOneByte : 8 bit modulus */
5081 /*-----------------------------------------------------------------*/
5083 genModOneByte (operand * left,
5088 sym_link *opetype = operandType (result);
5092 /* signed or unsigned */
5093 if (SPEC_USIGN (opetype))
5095 /* unsigned is easy */
5096 LOAD_AB_FOR_DIV (left, right, l);
5097 emitcode ("div", "ab");
5098 aopOp(result, ic, TRUE, FALSE);
5099 aopPut (AOP (result), "b", 0);
5103 /* signed is a little bit more difficult */
5105 /* save the signs of the operands */
5106 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5108 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5109 emitcode ("push", "acc"); /* save it on the stack */
5111 /* now sign adjust for both left & right */
5112 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5114 lbl = newiTempLabel (NULL);
5115 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5116 emitcode ("cpl", "a");
5117 emitcode ("inc", "a");
5118 emitcode ("", "!tlabeldef", (lbl->key + 100));
5119 emitcode ("mov", "b,a");
5121 /* sign adjust left side */
5122 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5124 lbl = newiTempLabel (NULL);
5125 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5126 emitcode ("cpl", "a");
5127 emitcode ("inc", "a");
5128 emitcode ("", "!tlabeldef", (lbl->key + 100));
5130 /* now the multiplication */
5131 emitcode ("nop", "; workaround for DS80C390 div bug.");
5132 emitcode ("div", "ab");
5133 /* we are interested in the lower order
5135 lbl = newiTempLabel (NULL);
5136 emitcode ("pop", "acc");
5137 /* if there was an over flow we don't
5138 adjust the sign of the result */
5139 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5140 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5142 emitcode ("clr", "a");
5143 emitcode ("subb", "a,b");
5144 emitcode ("mov", "b,a");
5145 emitcode ("", "!tlabeldef", (lbl->key + 100));
5148 /* now we are done */
5149 aopOp(result, ic, TRUE, FALSE);
5150 aopPut (AOP (result), "b", 0);
5155 /*-----------------------------------------------------------------*/
5156 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
5157 /*-----------------------------------------------------------------*/
5158 static void genModTwoByte (operand *left, operand *right,
5159 operand *result, iCode *ic)
5161 sym_link *retype = getSpec(operandType(right));
5162 sym_link *letype = getSpec(operandType(left));
5163 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5166 /* load up MA with left */
5167 /* save EA bit in F1 */
5168 lbl = newiTempLabel(NULL);
5169 emitcode ("setb","F1");
5170 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5171 emitcode ("clr","F1");
5172 emitcode("","!tlabeldef",lbl->key+100);
5175 lbl = newiTempLabel(NULL);
5176 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5177 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5178 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5179 emitcode ("xch", "a,b");
5180 emitcode ("cpl","a");
5181 emitcode ("add", "a,#1");
5182 emitcode ("xch", "a,b");
5183 emitcode ("cpl", "a"); // msb
5184 emitcode ("addc","a,#0");
5185 emitcode ("","!tlabeldef",lbl->key+100);
5186 emitcode ("mov","ma,b");
5187 emitcode ("mov","ma,a");
5189 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5190 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5193 /* load up MB with right */
5195 if (AOP_TYPE(right) == AOP_LIT) {
5196 int val=floatFromVal (AOP (right)->aopu.aop_lit);
5200 emitcode ("mov","mb,#!constbyte",val & 0xff);
5201 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5203 lbl = newiTempLabel(NULL);
5204 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5205 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5206 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5207 emitcode ("xch", "a,b");
5208 emitcode ("cpl","a");
5209 emitcode ("add", "a,#1");
5210 emitcode ("xch", "a,b");
5211 emitcode ("cpl", "a"); // msb
5212 emitcode ("addc", "a,#0");
5213 emitcode ("","!tlabeldef",lbl->key+100);
5214 emitcode ("mov","mb,b");
5215 emitcode ("mov","mb,a");
5218 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5219 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5222 /* wait for multiplication to finish */
5223 lbl = newiTempLabel(NULL);
5224 emitcode("","!tlabeldef", lbl->key+100);
5225 emitcode("mov","a,mcnt1");
5226 emitcode("anl","a,#!constbyte",0x80);
5227 emitcode("jnz","!tlabel",lbl->key+100);
5229 freeAsmop (left, NULL, ic, TRUE);
5230 freeAsmop (right, NULL, ic,TRUE);
5231 aopOp(result, ic, TRUE, FALSE);
5233 aopPut(AOP(result),"mb",1);
5234 aopPut(AOP(result),"mb",0);
5235 freeAsmop (result, NULL, ic, TRUE);
5237 /* restore EA bit in F1 */
5238 lbl = newiTempLabel(NULL);
5239 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5240 emitcode ("setb","EA");
5241 emitcode("","!tlabeldef",lbl->key+100);
5245 /*-----------------------------------------------------------------*/
5246 /* genMod - generates code for division */
5247 /*-----------------------------------------------------------------*/
5251 operand *left = IC_LEFT (ic);
5252 operand *right = IC_RIGHT (ic);
5253 operand *result = IC_RESULT (ic);
5255 D (emitcode (";", "genMod "); );
5257 /* assign the amsops */
5260 /* special cases first */
5262 if (AOP_TYPE (left) == AOP_CRY &&
5263 AOP_TYPE (right) == AOP_CRY)
5265 genModbits (left, right, result, ic);
5269 /* if both are of size == 1 */
5270 if (AOP_SIZE (left) == 1 &&
5271 AOP_SIZE (right) == 1)
5273 genModOneByte (left, right, result, ic);
5277 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5278 /* use the ds390 ARITHMETIC accel UNIT */
5279 genModTwoByte (left, right, result, ic);
5283 /* should have been converted to function call */
5287 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5288 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5289 freeAsmop (result, NULL, ic, TRUE);
5292 /*-----------------------------------------------------------------*/
5293 /* genIfxJump :- will create a jump depending on the ifx */
5294 /*-----------------------------------------------------------------*/
5296 genIfxJump (iCode * ic, char *jval)
5299 symbol *tlbl = newiTempLabel (NULL);
5302 D (emitcode (";", "genIfxJump"););
5304 /* if true label then we jump if condition
5308 jlbl = IC_TRUE (ic);
5309 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5310 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5314 /* false label is present */
5315 jlbl = IC_FALSE (ic);
5316 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5317 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5319 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5320 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5322 emitcode (inst, "!tlabel", tlbl->key + 100);
5323 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5324 emitcode ("", "!tlabeldef", tlbl->key + 100);
5326 /* mark the icode as generated */
5330 /*-----------------------------------------------------------------*/
5331 /* genCmp :- greater or less than comparison */
5332 /*-----------------------------------------------------------------*/
5334 genCmp (operand * left, operand * right,
5335 iCode * ic, iCode * ifx, int sign)
5337 int size, offset = 0;
5338 unsigned long lit = 0L;
5341 D (emitcode (";", "genCmp"););
5343 result = IC_RESULT (ic);
5345 /* if left & right are bit variables */
5346 if (AOP_TYPE (left) == AOP_CRY &&
5347 AOP_TYPE (right) == AOP_CRY)
5349 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5350 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
5354 /* subtract right from left if at the
5355 end the carry flag is set then we know that
5356 left is greater than right */
5357 size = max (AOP_SIZE (left), AOP_SIZE (right));
5359 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5360 if ((size == 1) && !sign
5361 && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5363 symbol *lbl = newiTempLabel (NULL);
5364 emitcode ("cjne", "%s,%s,!tlabel",
5365 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5366 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5368 emitcode ("", "!tlabeldef", lbl->key + 100);
5372 if (AOP_TYPE (right) == AOP_LIT)
5374 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5375 /* optimize if(x < 0) or if(x >= 0) */
5384 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5386 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5387 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5389 aopOp (result, ic, FALSE, FALSE);
5391 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5393 freeAsmop (result, NULL, ic, TRUE);
5394 genIfxJump (ifx, "acc.7");
5399 emitcode ("rlc", "a");
5401 goto release_freedLR;
5409 //emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5410 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5411 //emitcode (";", "genCmp #2");
5412 if (sign && (size == 0))
5414 //emitcode (";", "genCmp #3");
5415 emitcode ("xrl", "a,#!constbyte",0x80);
5416 if (AOP_TYPE (right) == AOP_LIT)
5418 unsigned long lit = (unsigned long)
5419 floatFromVal (AOP (right)->aopu.aop_lit);
5420 //emitcode (";", "genCmp #3.1");
5421 emitcode ("subb", "a,#!constbyte",
5422 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5426 //emitcode (";", "genCmp #3.2");
5427 if (AOP_NEEDSACC (right) && AOP_TYPE(right) != AOP_DPTR2)
5429 emitcode ("push", "acc");
5432 MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5433 emitcode ("xrl", "b,#!constbyte",0x80);
5435 if (AOP_NEEDSACC (right) && AOP_TYPE(right) != AOP_DPTR2)
5437 emitcode ("pop", "acc");
5439 emitcode ("subb", "a,b");
5446 //emitcode (";", "genCmp #4");
5447 if (AOP_NEEDSACC (right))
5450 //emitcode (";", "genCmp #4.1");
5451 emitcode ("xch", "a, b");
5452 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
5453 emitcode ("xch", "a, b");
5458 //emitcode (";", "genCmp #4.2");
5459 s = aopGet (AOP (right), offset++, FALSE, FALSE, DP2_RESULT_REG);
5462 emitcode ("subb", "a,%s", s);
5469 /* Don't need the left & right operands any more; do need the result. */
5470 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5471 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5473 aopOp (result, ic, FALSE, FALSE);
5477 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5483 /* if the result is used in the next
5484 ifx conditional branch then generate
5485 code a little differently */
5488 genIfxJump (ifx, "c");
5494 /* leave the result in acc */
5496 freeAsmop (result, NULL, ic, TRUE);
5499 /*-----------------------------------------------------------------*/
5500 /* genCmpGt :- greater than comparison */
5501 /*-----------------------------------------------------------------*/
5503 genCmpGt (iCode * ic, iCode * ifx)
5505 operand *left, *right;
5506 sym_link *letype, *retype;
5509 D (emitcode (";", "genCmpGt ");
5512 left = IC_LEFT (ic);
5513 right = IC_RIGHT (ic);
5515 letype = getSpec (operandType (left));
5516 retype = getSpec (operandType (right));
5517 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5519 /* assign the left & right amsops */
5522 genCmp (right, left, ic, ifx, sign);
5525 /*-----------------------------------------------------------------*/
5526 /* genCmpLt - less than comparisons */
5527 /*-----------------------------------------------------------------*/
5529 genCmpLt (iCode * ic, iCode * ifx)
5531 operand *left, *right;
5532 sym_link *letype, *retype;
5535 D (emitcode (";", "genCmpLt "););
5537 left = IC_LEFT (ic);
5538 right = IC_RIGHT (ic);
5540 letype = getSpec (operandType (left));
5541 retype = getSpec (operandType (right));
5542 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5544 /* assign the left & right amsops */
5547 genCmp (left, right, ic, ifx, sign);
5550 /*-----------------------------------------------------------------*/
5551 /* gencjneshort - compare and jump if not equal */
5552 /*-----------------------------------------------------------------*/
5554 gencjneshort (operand * left, operand * right, symbol * lbl)
5556 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5558 unsigned long lit = 0L;
5560 D (emitcode (";", "gencjneshort");
5563 /* if the left side is a literal or
5564 if the right is in a pointer register and left
5566 if ((AOP_TYPE (left) == AOP_LIT) ||
5567 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5574 if (AOP_TYPE (right) == AOP_LIT)
5575 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5577 if (opIsGptr (left) || opIsGptr (right))
5579 /* We are comparing a generic pointer to something.
5580 * Exclude the generic type byte from the comparison.
5583 D (emitcode (";", "cjneshort: generic ptr special case."););
5587 /* if the right side is a literal then anything goes */
5588 if (AOP_TYPE (right) == AOP_LIT &&
5589 AOP_TYPE (left) != AOP_DIR)
5593 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5594 emitcode ("cjne", "a,%s,!tlabel",
5595 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG),
5601 /* if the right side is in a register or in direct space or
5602 if the left is a pointer register & right is not */
5603 else if (AOP_TYPE (right) == AOP_REG ||
5604 AOP_TYPE (right) == AOP_DIR ||
5605 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5606 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5610 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5611 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5612 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5613 emitcode ("jnz", "!tlabel", lbl->key + 100);
5615 emitcode ("cjne", "a,%s,!tlabel",
5616 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5623 /* right is a pointer reg need both a & b */
5626 MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5627 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5628 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5634 /*-----------------------------------------------------------------*/
5635 /* gencjne - compare and jump if not equal */
5636 /*-----------------------------------------------------------------*/
5638 gencjne (operand * left, operand * right, symbol * lbl)
5640 symbol *tlbl = newiTempLabel (NULL);
5642 D (emitcode (";", "gencjne");
5645 gencjneshort (left, right, lbl);
5647 emitcode ("mov", "a,%s", one);
5648 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5649 emitcode ("", "!tlabeldef", lbl->key + 100);
5650 emitcode ("clr", "a");
5651 emitcode ("", "!tlabeldef", tlbl->key + 100);
5654 /*-----------------------------------------------------------------*/
5655 /* genCmpEq - generates code for equal to */
5656 /*-----------------------------------------------------------------*/
5658 genCmpEq (iCode * ic, iCode * ifx)
5660 operand *left, *right, *result;
5662 D (emitcode (";", "genCmpEq ");
5666 AOP_SET_LOCALS (ic);
5668 /* if literal, literal on the right or
5669 if the right is in a pointer register and left
5671 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5672 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5674 operand *t = IC_RIGHT (ic);
5675 IC_RIGHT (ic) = IC_LEFT (ic);
5679 if (ifx && /* !AOP_SIZE(result) */
5680 OP_SYMBOL (result) &&
5681 OP_SYMBOL (result)->regType == REG_CND)
5684 /* if they are both bit variables */
5685 if (AOP_TYPE (left) == AOP_CRY &&
5686 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5688 if (AOP_TYPE (right) == AOP_LIT)
5690 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5693 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5694 emitcode ("cpl", "c");
5698 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5702 emitcode ("clr", "c");
5704 /* AOP_TYPE(right) == AOP_CRY */
5708 symbol *lbl = newiTempLabel (NULL);
5709 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5710 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5711 emitcode ("cpl", "c");
5712 emitcode ("", "!tlabeldef", (lbl->key + 100));
5714 /* if true label then we jump if condition
5716 tlbl = newiTempLabel (NULL);
5719 emitcode ("jnc", "!tlabel", tlbl->key + 100);
5720 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5724 emitcode ("jc", "!tlabel", tlbl->key + 100);
5725 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5727 emitcode ("", "!tlabeldef", tlbl->key + 100);
5731 tlbl = newiTempLabel (NULL);
5732 gencjneshort (left, right, tlbl);
5735 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5736 emitcode ("", "!tlabeldef", tlbl->key + 100);
5740 symbol *lbl = newiTempLabel (NULL);
5741 emitcode ("sjmp", "!tlabel", lbl->key + 100);
5742 emitcode ("", "!tlabeldef", tlbl->key + 100);
5743 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5744 emitcode ("", "!tlabeldef", lbl->key + 100);
5747 /* mark the icode as generated */
5750 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5751 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5755 /* if they are both bit variables */
5756 if (AOP_TYPE (left) == AOP_CRY &&
5757 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5759 if (AOP_TYPE (right) == AOP_LIT)
5761 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5764 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5765 emitcode ("cpl", "c");
5769 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5773 emitcode ("clr", "c");
5775 /* AOP_TYPE(right) == AOP_CRY */
5779 symbol *lbl = newiTempLabel (NULL);
5780 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5781 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5782 emitcode ("cpl", "c");
5783 emitcode ("", "!tlabeldef", (lbl->key + 100));
5786 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5787 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5789 aopOp (result, ic, TRUE, FALSE);
5792 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5799 genIfxJump (ifx, "c");
5802 /* if the result is used in an arithmetic operation
5803 then put the result in place */
5808 gencjne (left, right, newiTempLabel (NULL));
5810 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5811 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5813 aopOp (result, ic, TRUE, FALSE);
5815 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5817 aopPut (AOP (result), "a", 0);
5822 genIfxJump (ifx, "a");
5825 /* if the result is used in an arithmetic operation
5826 then put the result in place */
5827 if (AOP_TYPE (result) != AOP_CRY)
5829 /* leave the result in acc */
5833 freeAsmop (result, NULL, ic, TRUE);
5836 /*-----------------------------------------------------------------*/
5837 /* ifxForOp - returns the icode containing the ifx for operand */
5838 /*-----------------------------------------------------------------*/
5840 ifxForOp (operand * op, iCode * ic)
5842 /* if true symbol then needs to be assigned */
5843 if (IS_TRUE_SYMOP (op))
5846 /* if this has register type condition and
5847 the next instruction is ifx with the same operand
5848 and live to of the operand is upto the ifx only then */
5850 ic->next->op == IFX &&
5851 IC_COND (ic->next)->key == op->key &&
5852 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5857 /*-----------------------------------------------------------------*/
5858 /* hasInc - operand is incremented before any other use */
5859 /*-----------------------------------------------------------------*/
5861 hasInc (operand *op, iCode *ic, int osize)
5863 sym_link *type = operandType(op);
5864 sym_link *retype = getSpec (type);
5865 iCode *lic = ic->next;
5868 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5869 if (!IS_SYMOP(op)) return NULL;
5871 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5872 if (IS_AGGREGATE(type->next)) return NULL;
5873 if (osize != (isize = getSize(type->next))) return NULL;
5876 /* if operand of the form op = op + <sizeof *op> */
5877 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5878 isOperandEqual(IC_RESULT(lic),op) &&
5879 isOperandLiteral(IC_RIGHT(lic)) &&
5880 operandLitValue(IC_RIGHT(lic)) == isize) {
5883 /* if the operand used or deffed */
5884 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5887 /* if GOTO or IFX */
5888 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5894 /*-----------------------------------------------------------------*/
5895 /* genAndOp - for && operation */
5896 /*-----------------------------------------------------------------*/
5898 genAndOp (iCode * ic)
5900 operand *left, *right, *result;
5903 D (emitcode (";", "genAndOp "););
5905 /* note here that && operations that are in an
5906 if statement are taken away by backPatchLabels
5907 only those used in arthmetic operations remain */
5909 AOP_SET_LOCALS (ic);
5911 /* if both are bit variables */
5912 if (AOP_TYPE (left) == AOP_CRY &&
5913 AOP_TYPE (right) == AOP_CRY)
5915 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5916 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5917 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5918 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5920 aopOp (result,ic,FALSE, FALSE);
5925 tlbl = newiTempLabel (NULL);
5927 emitcode ("jz", "!tlabel", tlbl->key + 100);
5929 emitcode ("", "!tlabeldef", tlbl->key + 100);
5930 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5931 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5933 aopOp (result,ic,FALSE, FALSE);
5936 freeAsmop (result, NULL, ic, TRUE);
5940 /*-----------------------------------------------------------------*/
5941 /* genOrOp - for || operation */
5942 /*-----------------------------------------------------------------*/
5944 genOrOp (iCode * ic)
5946 operand *left, *right, *result;
5949 D (emitcode (";", "genOrOp "););
5951 /* note here that || operations that are in an
5952 if statement are taken away by backPatchLabels
5953 only those used in arthmetic operations remain */
5955 AOP_SET_LOCALS (ic);
5957 /* if both are bit variables */
5958 if (AOP_TYPE (left) == AOP_CRY &&
5959 AOP_TYPE (right) == AOP_CRY)
5961 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5962 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5963 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5964 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5966 aopOp (result,ic,FALSE, FALSE);
5972 tlbl = newiTempLabel (NULL);
5974 emitcode ("jnz", "!tlabel", tlbl->key + 100);
5976 emitcode ("", "!tlabeldef", tlbl->key + 100);
5977 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5978 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5980 aopOp (result,ic,FALSE, FALSE);
5985 freeAsmop (result, NULL, ic, TRUE);
5988 /*-----------------------------------------------------------------*/
5989 /* isLiteralBit - test if lit == 2^n */
5990 /*-----------------------------------------------------------------*/
5992 isLiteralBit (unsigned long lit)
5994 unsigned long pw[32] =
5995 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5996 0x100L, 0x200L, 0x400L, 0x800L,
5997 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5998 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5999 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6000 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6001 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6004 for (idx = 0; idx < 32; idx++)
6010 /*-----------------------------------------------------------------*/
6011 /* continueIfTrue - */
6012 /*-----------------------------------------------------------------*/
6014 continueIfTrue (iCode * ic)
6017 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6021 /*-----------------------------------------------------------------*/
6023 /*-----------------------------------------------------------------*/
6025 jumpIfTrue (iCode * ic)
6028 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6032 /*-----------------------------------------------------------------*/
6033 /* jmpTrueOrFalse - */
6034 /*-----------------------------------------------------------------*/
6036 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6038 // ugly but optimized by peephole
6041 symbol *nlbl = newiTempLabel (NULL);
6042 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6043 emitcode ("", "!tlabeldef", tlbl->key + 100);
6044 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6045 emitcode ("", "!tlabeldef", nlbl->key + 100);
6049 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6050 emitcode ("", "!tlabeldef", tlbl->key + 100);
6055 // Generate code to perform a bit-wise logic operation
6056 // on two operands in far space (assumed to already have been
6057 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6058 // in far space. This requires pushing the result on the stack
6059 // then popping it into the result.
6061 genFarFarLogicOp(iCode *ic, char *logicOp)
6063 int size, resultSize, compSize;
6067 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6068 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
6069 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6071 _startLazyDPSEvaluation();
6072 for (size = compSize; (size--); offset++)
6074 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6075 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6076 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6078 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6079 emitcode ("push", "acc");
6081 _endLazyDPSEvaluation();
6083 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6084 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6085 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6087 resultSize = AOP_SIZE(IC_RESULT(ic));
6089 ADJUST_PUSHED_RESULT(compSize, resultSize);
6091 _startLazyDPSEvaluation();
6094 emitcode ("pop", "acc");
6095 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6097 _endLazyDPSEvaluation();
6098 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6102 /*-----------------------------------------------------------------*/
6103 /* genAnd - code for and */
6104 /*-----------------------------------------------------------------*/
6106 genAnd (iCode * ic, iCode * ifx)
6108 operand *left, *right, *result;
6109 int size, offset = 0;
6110 unsigned long lit = 0L;
6115 D (emitcode (";", "genAnd "););
6117 AOP_OP_3_NOFATAL (ic, pushResult);
6118 AOP_SET_LOCALS (ic);
6122 genFarFarLogicOp(ic, "anl");
6127 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6129 AOP_TYPE (left), AOP_TYPE (right));
6130 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6132 AOP_SIZE (left), AOP_SIZE (right));
6135 /* if left is a literal & right is not then exchange them */
6136 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6137 #ifdef LOGIC_OPS_BROKEN
6138 || AOP_NEEDSACC (left)
6142 operand *tmp = right;
6147 /* if result = right then exchange them */
6148 if (sameRegs (AOP (result), AOP (right)))
6150 operand *tmp = right;
6155 /* if right is bit then exchange them */
6156 if (AOP_TYPE (right) == AOP_CRY &&
6157 AOP_TYPE (left) != AOP_CRY)
6159 operand *tmp = right;
6163 if (AOP_TYPE (right) == AOP_LIT)
6164 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6166 size = AOP_SIZE (result);
6169 // result = bit & yy;
6170 if (AOP_TYPE (left) == AOP_CRY)
6172 // c = bit & literal;
6173 if (AOP_TYPE (right) == AOP_LIT)
6177 if (size && sameRegs (AOP (result), AOP (left)))
6180 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6185 if (size && (AOP_TYPE (result) == AOP_CRY))
6187 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6190 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6195 emitcode ("clr", "c");
6200 if (AOP_TYPE (right) == AOP_CRY)
6203 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6204 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6209 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6211 emitcode ("rrc", "a");
6212 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6220 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6221 genIfxJump (ifx, "c");
6225 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6226 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6227 if ((AOP_TYPE (right) == AOP_LIT) &&
6228 (AOP_TYPE (result) == AOP_CRY) &&
6229 (AOP_TYPE (left) != AOP_CRY))
6231 int posbit = isLiteralBit (lit);
6236 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6239 emitcode ("mov", "c,acc.%d", posbit & 0x07);
6245 SNPRINTF (buff, sizeof(buff),
6246 "acc.%d", posbit & 0x07);
6247 genIfxJump (ifx, buff);
6251 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6258 symbol *tlbl = newiTempLabel (NULL);
6259 int sizel = AOP_SIZE (left);
6261 emitcode ("setb", "c");
6264 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6266 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6268 if ((posbit = isLiteralBit (bytelit)) != 0)
6269 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6272 if (bytelit != 0x0FFL)
6273 emitcode ("anl", "a,%s",
6274 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6275 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6280 // bit = left & literal
6283 emitcode ("clr", "c");
6284 emitcode ("", "!tlabeldef", tlbl->key + 100);
6286 // if(left & literal)
6290 jmpTrueOrFalse (ifx, tlbl);
6298 /* if left is same as result */
6299 if (sameRegs (AOP (result), AOP (left)))
6301 for (; size--; offset++)
6303 if (AOP_TYPE (right) == AOP_LIT)
6305 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6307 else if (bytelit == 0)
6308 aopPut (AOP (result), zero, offset);
6309 else if (IS_AOP_PREG (result))
6311 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6312 emitcode ("anl", "a,%s",
6313 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6314 aopPut (AOP (result), "a", offset);
6317 emitcode ("anl", "%s,%s",
6318 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6319 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6323 if (AOP_TYPE (left) == AOP_ACC)
6324 emitcode ("anl", "a,%s",
6325 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6328 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6329 if (IS_AOP_PREG (result))
6331 emitcode ("anl", "a,%s",
6332 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6333 aopPut (AOP (result), "a", offset);
6336 emitcode ("anl", "%s,a",
6337 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6344 // left & result in different registers
6345 if (AOP_TYPE (result) == AOP_CRY)
6348 // if(size), result in bit
6349 // if(!size && ifx), conditional oper: if(left & right)
6350 symbol *tlbl = newiTempLabel (NULL);
6351 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6353 emitcode ("setb", "c");
6356 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6357 emitcode ("anl", "a,%s",
6358 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6360 if (AOP_TYPE(left)==AOP_ACC) {
6361 emitcode("mov", "b,a");
6362 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6363 emitcode("anl", "a,b");
6365 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6366 emitcode ("anl", "a,%s",
6367 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6370 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6376 emitcode ("", "!tlabeldef", tlbl->key + 100);
6380 jmpTrueOrFalse (ifx, tlbl);
6384 for (; (size--); offset++)
6387 // result = left & right
6388 if (AOP_TYPE (right) == AOP_LIT)
6390 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6392 aopPut (AOP (result),
6393 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6397 else if (bytelit == 0)
6399 aopPut (AOP (result), zero, offset);
6402 D (emitcode (";", "better literal AND."););
6403 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6404 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6405 FALSE, FALSE, DP2_RESULT_REG));
6410 // faster than result <- left, anl result,right
6411 // and better if result is SFR
6412 if (AOP_TYPE (left) == AOP_ACC)
6414 emitcode ("anl", "a,%s",
6415 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6419 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6420 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6422 emitcode("mov", "b,a");
6426 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6427 emitcode ("anl", "a,%s", rOp);
6430 aopPut (AOP (result), "a", offset);
6436 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6437 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6438 freeAsmop (result, NULL, ic, TRUE);
6442 /*-----------------------------------------------------------------*/
6443 /* genOr - code for or */
6444 /*-----------------------------------------------------------------*/
6446 genOr (iCode * ic, iCode * ifx)
6448 operand *left, *right, *result;
6449 int size, offset = 0;
6450 unsigned long lit = 0L;
6453 D (emitcode (";", "genOr "););
6455 AOP_OP_3_NOFATAL (ic, pushResult);
6456 AOP_SET_LOCALS (ic);
6460 genFarFarLogicOp(ic, "orl");
6466 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6468 AOP_TYPE (left), AOP_TYPE (right));
6469 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6471 AOP_SIZE (left), AOP_SIZE (right));
6474 /* if left is a literal & right is not then exchange them */
6475 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6476 #ifdef LOGIC_OPS_BROKEN
6477 || AOP_NEEDSACC (left) // I think this is a net loss now.
6481 operand *tmp = right;
6486 /* if result = right then exchange them */
6487 if (sameRegs (AOP (result), AOP (right)))
6489 operand *tmp = right;
6494 /* if right is bit then exchange them */
6495 if (AOP_TYPE (right) == AOP_CRY &&
6496 AOP_TYPE (left) != AOP_CRY)
6498 operand *tmp = right;
6502 if (AOP_TYPE (right) == AOP_LIT)
6503 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6505 size = AOP_SIZE (result);
6509 if (AOP_TYPE (left) == AOP_CRY)
6511 if (AOP_TYPE (right) == AOP_LIT)
6513 // c = bit & literal;
6516 // lit != 0 => result = 1
6517 if (AOP_TYPE (result) == AOP_CRY)
6520 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6522 continueIfTrue (ifx);
6525 emitcode ("setb", "c");
6529 // lit == 0 => result = left
6530 if (size && sameRegs (AOP (result), AOP (left)))
6532 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6537 if (AOP_TYPE (right) == AOP_CRY)
6540 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6541 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6546 symbol *tlbl = newiTempLabel (NULL);
6547 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6548 emitcode ("setb", "c");
6549 emitcode ("jb", "%s,!tlabel",
6550 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6552 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6553 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6555 jmpTrueOrFalse (ifx, tlbl);
6561 emitcode ("", "!tlabeldef", tlbl->key + 100);
6570 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6571 genIfxJump (ifx, "c");
6575 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6576 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6577 if ((AOP_TYPE (right) == AOP_LIT) &&
6578 (AOP_TYPE (result) == AOP_CRY) &&
6579 (AOP_TYPE (left) != AOP_CRY))
6585 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6587 continueIfTrue (ifx);
6592 // lit = 0, result = boolean(left)
6594 emitcode ("setb", "c");
6598 symbol *tlbl = newiTempLabel (NULL);
6599 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6601 emitcode ("", "!tlabeldef", tlbl->key + 100);
6605 genIfxJump (ifx, "a");
6613 /* if left is same as result */
6614 if (sameRegs (AOP (result), AOP (left)))
6616 for (; size--; offset++)
6618 if (AOP_TYPE (right) == AOP_LIT)
6620 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6626 if (IS_AOP_PREG (left))
6628 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6629 emitcode ("orl", "a,%s",
6630 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6631 aopPut (AOP (result), "a", offset);
6635 emitcode ("orl", "%s,%s",
6636 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6637 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6643 if (AOP_TYPE (left) == AOP_ACC)
6645 emitcode ("orl", "a,%s",
6646 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6650 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6651 if (IS_AOP_PREG (left))
6653 emitcode ("orl", "a,%s",
6654 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6655 aopPut (AOP (result), "a", offset);
6659 emitcode ("orl", "%s,a",
6660 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6668 // left & result in different registers
6669 if (AOP_TYPE (result) == AOP_CRY)
6672 // if(size), result in bit
6673 // if(!size && ifx), conditional oper: if(left | right)
6674 symbol *tlbl = newiTempLabel (NULL);
6675 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6677 emitcode ("setb", "c");
6680 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6681 emitcode ("orl", "a,%s",
6682 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6684 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6685 emitcode ("orl", "a,%s",
6686 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6688 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6694 emitcode ("", "!tlabeldef", tlbl->key + 100);
6698 jmpTrueOrFalse (ifx, tlbl);
6702 _startLazyDPSEvaluation();
6703 for (; (size--); offset++)
6706 // result = left & right
6707 if (AOP_TYPE (right) == AOP_LIT)
6709 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6711 aopPut (AOP (result),
6712 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6716 D (emitcode (";", "better literal OR."););
6717 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6718 emitcode ("orl", "a, %s",
6719 aopGet (AOP (right), offset,
6720 FALSE, FALSE, DP2_RESULT_REG));
6725 // faster than result <- left, anl result,right
6726 // and better if result is SFR
6727 if (AOP_TYPE (left) == AOP_ACC)
6729 emitcode ("orl", "a,%s",
6730 aopGet (AOP (right), offset,
6731 FALSE, FALSE, DP2_RESULT_REG));
6735 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6737 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6739 emitcode("mov", "b,a");
6743 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6744 emitcode ("orl", "a,%s", rOp);
6747 aopPut (AOP (result), "a", offset);
6749 _endLazyDPSEvaluation();
6754 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6755 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6756 freeAsmop (result, NULL, ic, TRUE);
6759 /*-----------------------------------------------------------------*/
6760 /* genXor - code for xclusive or */
6761 /*-----------------------------------------------------------------*/
6763 genXor (iCode * ic, iCode * ifx)
6765 operand *left, *right, *result;
6766 int size, offset = 0;
6767 unsigned long lit = 0L;
6770 D (emitcode (";", "genXor "););
6772 AOP_OP_3_NOFATAL (ic, pushResult);
6773 AOP_SET_LOCALS (ic);
6777 genFarFarLogicOp(ic, "xrl");
6782 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6784 AOP_TYPE (left), AOP_TYPE (right));
6785 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6787 AOP_SIZE (left), AOP_SIZE (right));
6790 /* if left is a literal & right is not ||
6791 if left needs acc & right does not */
6792 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6793 #ifdef LOGIC_OPS_BROKEN
6794 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6798 operand *tmp = right;
6803 /* if result = right then exchange them */
6804 if (sameRegs (AOP (result), AOP (right)))
6806 operand *tmp = right;
6811 /* if right is bit then exchange them */
6812 if (AOP_TYPE (right) == AOP_CRY &&
6813 AOP_TYPE (left) != AOP_CRY)
6815 operand *tmp = right;
6819 if (AOP_TYPE (right) == AOP_LIT)
6820 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6822 size = AOP_SIZE (result);
6826 if (AOP_TYPE (left) == AOP_CRY)
6828 if (AOP_TYPE (right) == AOP_LIT)
6830 // c = bit & literal;
6833 // lit>>1 != 0 => result = 1
6834 if (AOP_TYPE (result) == AOP_CRY)
6837 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6839 continueIfTrue (ifx);
6842 emitcode ("setb", "c");
6849 // lit == 0, result = left
6850 if (size && sameRegs (AOP (result), AOP (left)))
6852 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6856 // lit == 1, result = not(left)
6857 if (size && sameRegs (AOP (result), AOP (left)))
6859 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6864 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6865 emitcode ("cpl", "c");
6874 symbol *tlbl = newiTempLabel (NULL);
6875 if (AOP_TYPE (right) == AOP_CRY)
6878 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6882 int sizer = AOP_SIZE (right);
6884 // if val>>1 != 0, result = 1
6885 emitcode ("setb", "c");
6888 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
6890 // test the msb of the lsb
6891 emitcode ("anl", "a,#!constbyte",0xfe);
6892 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6896 emitcode ("rrc", "a");
6898 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6899 emitcode ("cpl", "c");
6900 emitcode ("", "!tlabeldef", (tlbl->key + 100));
6907 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6908 genIfxJump (ifx, "c");
6912 if (sameRegs (AOP (result), AOP (left)))
6914 /* if left is same as result */
6915 for (; size--; offset++)
6917 if (AOP_TYPE (right) == AOP_LIT)
6919 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6921 else if (IS_AOP_PREG (left))
6923 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6924 emitcode ("xrl", "a,%s",
6925 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6926 aopPut (AOP (result), "a", offset);
6929 emitcode ("xrl", "%s,%s",
6930 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6931 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6935 if (AOP_TYPE (left) == AOP_ACC)
6936 emitcode ("xrl", "a,%s",
6937 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6940 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6941 if (IS_AOP_PREG (left))
6943 emitcode ("xrl", "a,%s",
6944 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6945 aopPut (AOP (result), "a", offset);
6948 emitcode ("xrl", "%s,a",
6949 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6956 // left & result in different registers
6957 if (AOP_TYPE (result) == AOP_CRY)
6960 // if(size), result in bit
6961 // if(!size && ifx), conditional oper: if(left ^ right)
6962 symbol *tlbl = newiTempLabel (NULL);
6963 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6966 emitcode ("setb", "c");
6969 if ((AOP_TYPE (right) == AOP_LIT) &&
6970 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6972 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6976 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6977 emitcode ("xrl", "a,%s",
6978 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6980 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6981 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6983 emitcode("mov", "b,a");
6987 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6988 emitcode ("xrl", "a,%s", rOp);
6991 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6997 emitcode ("", "!tlabeldef", tlbl->key + 100);
7001 jmpTrueOrFalse (ifx, tlbl);
7005 for (; (size--); offset++)
7008 // result = left & right
7009 if (AOP_TYPE (right) == AOP_LIT)
7011 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7013 aopPut (AOP (result),
7014 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7018 D (emitcode (";", "better literal XOR."););
7019 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7020 emitcode ("xrl", "a, %s",
7021 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7025 // faster than result <- left, anl result,right
7026 // and better if result is SFR
7027 if (AOP_TYPE (left) == AOP_ACC)
7029 emitcode ("xrl", "a,%s",
7030 aopGet (AOP (right), offset,
7031 FALSE, FALSE, DP2_RESULT_REG));
7035 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7036 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7038 emitcode("mov", "b,a");
7042 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7043 emitcode ("xrl", "a,%s", rOp);
7046 aopPut (AOP (result), "a", offset);
7053 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7054 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7055 freeAsmop (result, NULL, ic, TRUE);
7058 /*-----------------------------------------------------------------*/
7059 /* genInline - write the inline code out */
7060 /*-----------------------------------------------------------------*/
7062 genInline (iCode * ic)
7064 char *buffer, *bp, *bp1;
7066 D (emitcode (";", "genInline "); );
7068 _G.inLine += (!options.asmpeep);
7070 buffer = Safe_strdup(IC_INLINE(ic));
7074 /* emit each line as a code */
7099 /* emitcode("",buffer); */
7100 _G.inLine -= (!options.asmpeep);
7103 /*-----------------------------------------------------------------*/
7104 /* genRRC - rotate right with carry */
7105 /*-----------------------------------------------------------------*/
7109 operand *left, *result;
7112 D (emitcode (";", "genRRC "););
7114 /* rotate right with carry */
7115 left = IC_LEFT (ic);
7116 result = IC_RESULT (ic);
7117 aopOp (left, ic, FALSE, FALSE);
7118 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7120 /* move it to the result */
7121 size = AOP_SIZE (result);
7125 _startLazyDPSEvaluation ();
7128 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7129 emitcode ("rrc", "a");
7130 if (AOP_SIZE (result) > 1)
7131 aopPut (AOP (result), "a", offset--);
7133 _endLazyDPSEvaluation ();
7135 /* now we need to put the carry into the
7136 highest order byte of the result */
7137 if (AOP_SIZE (result) > 1)
7139 MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7141 emitcode ("mov", "acc.7,c");
7142 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7143 freeAsmop (left, NULL, ic, TRUE);
7144 freeAsmop (result, NULL, ic, TRUE);
7147 /*-----------------------------------------------------------------*/
7148 /* genRLC - generate code for rotate left with carry */
7149 /*-----------------------------------------------------------------*/
7153 operand *left, *result;
7157 D (emitcode (";", "genRLC "););
7159 /* rotate right with carry */
7160 left = IC_LEFT (ic);
7161 result = IC_RESULT (ic);
7162 aopOp (left, ic, FALSE, FALSE);
7163 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7165 /* move it to the result */
7166 size = AOP_SIZE (result);
7170 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7172 emitcode ("add", "a,acc");
7173 if (AOP_SIZE (result) > 1)
7175 aopPut (AOP (result), "a", offset++);
7178 _startLazyDPSEvaluation ();
7181 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7183 emitcode ("rlc", "a");
7184 if (AOP_SIZE (result) > 1)
7185 aopPut (AOP (result), "a", offset++);
7187 _endLazyDPSEvaluation ();
7189 /* now we need to put the carry into the
7190 highest order byte of the result */
7191 if (AOP_SIZE (result) > 1)
7193 l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7196 emitcode ("mov", "acc.0,c");
7197 aopPut (AOP (result), "a", 0);
7198 freeAsmop (left, NULL, ic, TRUE);
7199 freeAsmop (result, NULL, ic, TRUE);
7202 /*-----------------------------------------------------------------*/
7203 /* genGetHbit - generates code get highest order bit */
7204 /*-----------------------------------------------------------------*/
7206 genGetHbit (iCode * ic)
7208 operand *left, *result;
7209 left = IC_LEFT (ic);
7210 result = IC_RESULT (ic);
7211 aopOp (left, ic, FALSE, FALSE);
7212 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7214 D (emitcode (";", "genGetHbit "););
7216 /* get the highest order byte into a */
7217 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7218 if (AOP_TYPE (result) == AOP_CRY)
7220 emitcode ("rlc", "a");
7225 emitcode ("rl", "a");
7226 emitcode ("anl", "a,#1");
7231 freeAsmop (left, NULL, ic, TRUE);
7232 freeAsmop (result, NULL, ic, TRUE);
7235 /*-----------------------------------------------------------------*/
7236 /* AccRol - rotate left accumulator by known count */
7237 /*-----------------------------------------------------------------*/
7239 AccRol (int shCount)
7241 shCount &= 0x0007; // shCount : 0..7
7248 emitcode ("rl", "a");
7251 emitcode ("rl", "a");
7252 emitcode ("rl", "a");
7255 emitcode ("swap", "a");
7256 emitcode ("rr", "a");
7259 emitcode ("swap", "a");
7262 emitcode ("swap", "a");
7263 emitcode ("rl", "a");
7266 emitcode ("rr", "a");
7267 emitcode ("rr", "a");
7270 emitcode ("rr", "a");
7275 /*-----------------------------------------------------------------*/
7276 /* AccLsh - left shift accumulator by known count */
7277 /*-----------------------------------------------------------------*/
7279 AccLsh (int shCount)
7284 emitcode ("add", "a,acc");
7285 else if (shCount == 2)
7287 emitcode ("add", "a,acc");
7288 emitcode ("add", "a,acc");
7292 /* rotate left accumulator */
7294 /* and kill the lower order bits */
7295 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7300 /*-----------------------------------------------------------------*/
7301 /* AccRsh - right shift accumulator by known count */
7302 /*-----------------------------------------------------------------*/
7304 AccRsh (int shCount)
7311 emitcode ("rrc", "a");
7315 /* rotate right accumulator */
7316 AccRol (8 - shCount);
7317 /* and kill the higher order bits */
7318 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7323 #ifdef BETTER_LITERAL_SHIFT
7324 /*-----------------------------------------------------------------*/
7325 /* AccSRsh - signed right shift accumulator by known count */
7326 /*-----------------------------------------------------------------*/
7328 AccSRsh (int shCount)
7335 emitcode ("mov", "c,acc.7");
7336 emitcode ("rrc", "a");
7338 else if (shCount == 2)
7340 emitcode ("mov", "c,acc.7");
7341 emitcode ("rrc", "a");
7342 emitcode ("mov", "c,acc.7");
7343 emitcode ("rrc", "a");
7347 tlbl = newiTempLabel (NULL);
7348 /* rotate right accumulator */
7349 AccRol (8 - shCount);
7350 /* and kill the higher order bits */
7351 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7352 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7353 emitcode ("orl", "a,#!constbyte",
7354 (unsigned char) ~SRMask[shCount]);
7355 emitcode ("", "!tlabeldef", tlbl->key + 100);
7361 #ifdef BETTER_LITERAL_SHIFT
7362 /*-----------------------------------------------------------------*/
7363 /* shiftR1Left2Result - shift right one byte from left to result */
7364 /*-----------------------------------------------------------------*/
7366 shiftR1Left2Result (operand * left, int offl,
7367 operand * result, int offr,
7368 int shCount, int sign)
7370 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7371 /* shift right accumulator */
7376 aopPut (AOP (result), "a", offr);
7380 #ifdef BETTER_LITERAL_SHIFT
7381 /*-----------------------------------------------------------------*/
7382 /* shiftL1Left2Result - shift left one byte from left to result */
7383 /*-----------------------------------------------------------------*/
7385 shiftL1Left2Result (operand * left, int offl,
7386 operand * result, int offr, int shCount)
7388 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7389 /* shift left accumulator */
7391 aopPut (AOP (result), "a", offr);
7395 #ifdef BETTER_LITERAL_SHIFT
7396 /*-----------------------------------------------------------------*/
7397 /* movLeft2Result - move byte from left to result */
7398 /*-----------------------------------------------------------------*/
7400 movLeft2Result (operand * left, int offl,
7401 operand * result, int offr, int sign)
7404 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7406 l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7408 if (*l == '@' && (IS_AOP_PREG (result)))
7410 emitcode ("mov", "a,%s", l);
7411 aopPut (AOP (result), "a", offr);
7417 aopPut (AOP (result), l, offr);
7421 /* MSB sign in acc.7 ! */
7422 if (getDataSize (left) == offl + 1)
7424 emitcode ("mov", "a,%s", l);
7425 aopPut (AOP (result), "a", offr);
7433 #ifdef BETTER_LITERAL_SHIFT
7434 /*-----------------------------------------------------------------*/
7435 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7436 /*-----------------------------------------------------------------*/
7440 emitcode ("rrc", "a");
7441 emitcode ("xch", "a,%s", x);
7442 emitcode ("rrc", "a");
7443 emitcode ("xch", "a,%s", x);
7447 #ifdef BETTER_LITERAL_SHIFT
7449 /*-----------------------------------------------------------------*/
7450 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7451 /*-----------------------------------------------------------------*/
7455 emitcode ("xch", "a,%s", x);
7456 emitcode ("rlc", "a");
7457 emitcode ("xch", "a,%s", x);
7458 emitcode ("rlc", "a");
7462 #ifdef BETTER_LITERAL_SHIFT
7463 /*-----------------------------------------------------------------*/
7464 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7465 /*-----------------------------------------------------------------*/
7469 emitcode ("xch", "a,%s", x);
7470 emitcode ("add", "a,acc");
7471 emitcode ("xch", "a,%s", x);
7472 emitcode ("rlc", "a");
7476 #ifdef BETTER_LITERAL_SHIFT
7477 /*-----------------------------------------------------------------*/
7478 /* AccAXLsh - left shift a:x by known count (0..7) */
7479 /*-----------------------------------------------------------------*/
7481 AccAXLsh (char *x, int shCount)
7496 case 5: // AAAAABBB:CCCCCDDD
7498 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7500 emitcode ("anl", "a,#!constbyte",
7501 SLMask[shCount]); // BBB00000:CCCCCDDD
7503 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7505 AccRol (shCount); // DDDCCCCC:BBB00000
7507 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7509 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7511 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7513 emitcode ("anl", "a,#!constbyte",
7514 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7516 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7518 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7521 case 6: // AAAAAABB:CCCCCCDD
7522 emitcode ("anl", "a,#!constbyte",
7523 SRMask[shCount]); // 000000BB:CCCCCCDD
7524 emitcode ("mov", "c,acc.0"); // c = B
7525 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7527 AccAXRrl1 (x); // BCCCCCCD:D000000B
7528 AccAXRrl1 (x); // BBCCCCCC:DD000000
7530 emitcode("rrc","a");
7531 emitcode("xch","a,%s", x);
7532 emitcode("rrc","a");
7533 emitcode("mov","c,acc.0"); //<< get correct bit
7534 emitcode("xch","a,%s", x);
7536 emitcode("rrc","a");
7537 emitcode("xch","a,%s", x);
7538 emitcode("rrc","a");
7539 emitcode("xch","a,%s", x);
7542 case 7: // a:x <<= 7
7544 emitcode ("anl", "a,#!constbyte",
7545 SRMask[shCount]); // 0000000B:CCCCCCCD
7547 emitcode ("mov", "c,acc.0"); // c = B
7549 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7551 AccAXRrl1 (x); // BCCCCCCC:D0000000
7560 #ifdef BETTER_LITERAL_SHIFT
7562 /*-----------------------------------------------------------------*/
7563 /* AccAXRsh - right shift a:x known count (0..7) */
7564 /*-----------------------------------------------------------------*/
7566 AccAXRsh (char *x, int shCount)
7574 AccAXRrl1 (x); // 0->a:x
7579 AccAXRrl1 (x); // 0->a:x
7582 AccAXRrl1 (x); // 0->a:x
7587 case 5: // AAAAABBB:CCCCCDDD = a:x
7589 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7591 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7593 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7595 emitcode ("anl", "a,#!constbyte",
7596 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7598 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7600 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7602 emitcode ("anl", "a,#!constbyte",
7603 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7605 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7607 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7609 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7612 case 6: // AABBBBBB:CCDDDDDD
7614 emitcode ("mov", "c,acc.7");
7615 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7617 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7619 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7621 emitcode ("anl", "a,#!constbyte",
7622 SRMask[shCount]); // 000000AA:BBBBBBCC
7625 case 7: // ABBBBBBB:CDDDDDDD
7627 emitcode ("mov", "c,acc.7"); // c = A
7629 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7631 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7633 emitcode ("anl", "a,#!constbyte",
7634 SRMask[shCount]); // 0000000A:BBBBBBBC
7643 #ifdef BETTER_LITERAL_SHIFT
7644 /*-----------------------------------------------------------------*/
7645 /* AccAXRshS - right shift signed a:x known count (0..7) */
7646 /*-----------------------------------------------------------------*/
7648 AccAXRshS (char *x, int shCount)
7656 emitcode ("mov", "c,acc.7");
7657 AccAXRrl1 (x); // s->a:x
7661 emitcode ("mov", "c,acc.7");
7662 AccAXRrl1 (x); // s->a:x
7664 emitcode ("mov", "c,acc.7");
7665 AccAXRrl1 (x); // s->a:x
7670 case 5: // AAAAABBB:CCCCCDDD = a:x
7672 tlbl = newiTempLabel (NULL);
7673 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7675 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7677 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7679 emitcode ("anl", "a,#!constbyte",
7680 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7682 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7684 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7686 emitcode ("anl", "a,#!constbyte",
7687 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7689 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7691 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7693 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7695 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7696 emitcode ("orl", "a,#!constbyte",
7697 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7699 emitcode ("", "!tlabeldef", tlbl->key + 100);
7700 break; // SSSSAAAA:BBBCCCCC
7702 case 6: // AABBBBBB:CCDDDDDD
7704 tlbl = newiTempLabel (NULL);
7705 emitcode ("mov", "c,acc.7");
7706 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7708 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7710 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7712 emitcode ("anl", "a,#!constbyte",
7713 SRMask[shCount]); // 000000AA:BBBBBBCC
7715 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7716 emitcode ("orl", "a,#!constbyte",
7717 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7719 emitcode ("", "!tlabeldef", tlbl->key + 100);
7721 case 7: // ABBBBBBB:CDDDDDDD
7723 tlbl = newiTempLabel (NULL);
7724 emitcode ("mov", "c,acc.7"); // c = A
7726 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7728 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7730 emitcode ("anl", "a,#!constbyte",
7731 SRMask[shCount]); // 0000000A:BBBBBBBC
7733 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7734 emitcode ("orl", "a,#!constbyte",
7735 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7737 emitcode ("", "!tlabeldef", tlbl->key + 100);
7745 #ifdef BETTER_LITERAL_SHIFT
7747 _loadLeftIntoAx(char **lsb,
7753 // Get the initial value from left into a pair of registers.
7754 // MSB must be in A, LSB can be any register.
7756 // If the result is held in registers, it is an optimization
7757 // if the LSB can be held in the register which will hold the,
7758 // result LSB since this saves us from having to copy it into
7759 // the result following AccAXLsh.
7761 // If the result is addressed indirectly, this is not a gain.
7762 if (AOP_NEEDSACC(result))
7766 _startLazyDPSEvaluation();
7767 if (AOP_TYPE(left) == AOP_DPTR2)
7770 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7771 // get LSB in DP2_RESULT_REG.
7772 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7773 assert(!strcmp(leftByte, DP2_RESULT_REG));
7777 // get LSB into DP2_RESULT_REG
7778 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7779 if (strcmp(leftByte, DP2_RESULT_REG))
7782 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7785 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7786 assert(strcmp(leftByte, DP2_RESULT_REG));
7789 _endLazyDPSEvaluation();
7790 *lsb = DP2_RESULT_REG;
7794 if (sameRegs (AOP (result), AOP (left)) &&
7795 ((offl + MSB16) == offr))
7797 /* don't crash result[offr] */
7798 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
7799 emitcode ("xch", "a,%s",
7800 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
7804 movLeft2Result (left, offl, result, offr, 0);
7805 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
7807 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
7808 assert(strcmp(*lsb,"a"));
7813 _storeAxResults(char *lsb,
7817 _startLazyDPSEvaluation();
7818 if (AOP_NEEDSACC(result))
7820 /* We have to explicitly update the result LSB.
7822 emitcode("xch","a,%s", lsb);
7823 aopPut(AOP(result), "a", offr);
7824 emitcode("mov","a,%s", lsb);
7826 if (getDataSize (result) > 1)
7828 aopPut (AOP (result), "a", offr + MSB16);
7830 _endLazyDPSEvaluation();
7833 /*-----------------------------------------------------------------*/
7834 /* shiftL2Left2Result - shift left two bytes from left to result */
7835 /*-----------------------------------------------------------------*/
7837 shiftL2Left2Result (operand * left, int offl,
7838 operand * result, int offr, int shCount)
7842 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7844 AccAXLsh (lsb, shCount);
7846 _storeAxResults(lsb, result, offr);
7850 #ifdef BETTER_LITERAL_SHIFT
7851 /*-----------------------------------------------------------------*/
7852 /* shiftR2Left2Result - shift right two bytes from left to result */
7853 /*-----------------------------------------------------------------*/
7855 shiftR2Left2Result (operand * left, int offl,
7856 operand * result, int offr,
7857 int shCount, int sign)
7861 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7863 /* a:x >> shCount (x = lsb(result)) */
7866 AccAXRshS(lsb, shCount);
7870 AccAXRsh(lsb, shCount);
7873 _storeAxResults(lsb, result, offr);
7879 /*-----------------------------------------------------------------*/
7880 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7881 /*-----------------------------------------------------------------*/
7883 shiftLLeftOrResult (operand * left, int offl,
7884 operand * result, int offr, int shCount)
7886 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7887 /* shift left accumulator */
7889 /* or with result */
7890 emitcode ("orl", "a,%s",
7891 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7892 /* back to result */
7893 aopPut (AOP (result), "a", offr);
7899 /*-----------------------------------------------------------------*/
7900 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7901 /*-----------------------------------------------------------------*/
7903 shiftRLeftOrResult (operand * left, int offl,
7904 operand * result, int offr, int shCount)
7906 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7907 /* shift right accumulator */
7909 /* or with result */
7910 emitcode ("orl", "a,%s",
7911 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7912 /* back to result */
7913 aopPut (AOP (result), "a", offr);
7917 #ifdef BETTER_LITERAL_SHIFT
7918 /*-----------------------------------------------------------------*/
7919 /* genlshOne - left shift a one byte quantity by known count */
7920 /*-----------------------------------------------------------------*/
7922 genlshOne (operand * result, operand * left, int shCount)
7924 D (emitcode (";", "genlshOne "););
7925 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7929 #ifdef BETTER_LITERAL_SHIFT
7930 /*-----------------------------------------------------------------*/
7931 /* genlshTwo - left shift two bytes by known amount != 0 */
7932 /*-----------------------------------------------------------------*/
7934 genlshTwo (operand * result, operand * left, int shCount)
7938 D (emitcode (";", "genlshTwo "););
7940 size = getDataSize (result);
7942 /* if shCount >= 8 */
7947 _startLazyDPSEvaluation();
7953 _endLazyDPSEvaluation();
7954 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7955 aopPut (AOP (result), zero, LSB);
7959 movLeft2Result (left, LSB, result, MSB16, 0);
7960 aopPut (AOP (result), zero, LSB);
7961 _endLazyDPSEvaluation();
7966 aopPut (AOP (result), zero, LSB);
7967 _endLazyDPSEvaluation();
7971 /* 1 <= shCount <= 7 */
7976 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7980 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7988 /*-----------------------------------------------------------------*/
7989 /* shiftLLong - shift left one long from left to result */
7990 /* offl = LSB or MSB16 */
7991 /*-----------------------------------------------------------------*/
7993 shiftLLong (operand * left, operand * result, int offr)
7996 int size = AOP_SIZE (result);
7998 if (size >= LSB + offr)
8000 l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8002 emitcode ("add", "a,acc");
8003 if (sameRegs (AOP (left), AOP (result)) &&
8004 size >= MSB16 + offr && offr != LSB)
8005 emitcode ("xch", "a,%s",
8006 aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8008 aopPut (AOP (result), "a", LSB + offr);
8011 if (size >= MSB16 + offr)
8013 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8015 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8017 emitcode ("rlc", "a");
8018 if (sameRegs (AOP (left), AOP (result)) &&
8019 size >= MSB24 + offr && offr != LSB)
8020 emitcode ("xch", "a,%s",
8021 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8023 aopPut (AOP (result), "a", MSB16 + offr);
8026 if (size >= MSB24 + offr)
8028 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8030 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8032 emitcode ("rlc", "a");
8033 if (sameRegs (AOP (left), AOP (result)) &&
8034 size >= MSB32 + offr && offr != LSB)
8035 emitcode ("xch", "a,%s",
8036 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8038 aopPut (AOP (result), "a", MSB24 + offr);
8041 if (size > MSB32 + offr)
8043 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8045 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8047 emitcode ("rlc", "a");
8048 aopPut (AOP (result), "a", MSB32 + offr);
8051 aopPut (AOP (result), zero, LSB);
8057 /*-----------------------------------------------------------------*/
8058 /* genlshFour - shift four byte by a known amount != 0 */
8059 /*-----------------------------------------------------------------*/
8061 genlshFour (operand * result, operand * left, int shCount)
8065 D (emitcode (";", "genlshFour ");
8068 size = AOP_SIZE (result);
8070 /* if shifting more that 3 bytes */
8075 /* lowest order of left goes to the highest
8076 order of the destination */
8077 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8079 movLeft2Result (left, LSB, result, MSB32, 0);
8080 aopPut (AOP (result), zero, LSB);
8081 aopPut (AOP (result), zero, MSB16);
8082 aopPut (AOP (result), zero, MSB24);
8086 /* more than two bytes */
8087 else if (shCount >= 16)
8089 /* lower order two bytes goes to higher order two bytes */
8091 /* if some more remaining */
8093 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8096 movLeft2Result (left, MSB16, result, MSB32, 0);
8097 movLeft2Result (left, LSB, result, MSB24, 0);
8099 aopPut (AOP (result), zero, MSB16);
8100 aopPut (AOP (result), zero, LSB);
8104 /* if more than 1 byte */
8105 else if (shCount >= 8)
8107 /* lower order three bytes goes to higher order three bytes */
8112 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8114 movLeft2Result (left, LSB, result, MSB16, 0);
8120 movLeft2Result (left, MSB24, result, MSB32, 0);
8121 movLeft2Result (left, MSB16, result, MSB24, 0);
8122 movLeft2Result (left, LSB, result, MSB16, 0);
8123 aopPut (AOP (result), zero, LSB);
8125 else if (shCount == 1)
8126 shiftLLong (left, result, MSB16);
8129 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8130 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8131 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8132 aopPut (AOP (result), zero, LSB);
8137 /* 1 <= shCount <= 7 */
8138 else if (shCount <= 2)
8140 shiftLLong (left, result, LSB);
8142 shiftLLong (result, result, LSB);
8144 /* 3 <= shCount <= 7, optimize */
8147 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8148 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8149 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8154 #ifdef BETTER_LITERAL_SHIFT
8155 /*-----------------------------------------------------------------*/
8156 /* genLeftShiftLiteral - left shifting by known count */
8157 /*-----------------------------------------------------------------*/
8159 genLeftShiftLiteral (operand * left,
8164 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8167 size = getSize (operandType (result));
8169 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8171 /* We only handle certain easy cases so far. */
8173 && (shCount < (size * 8))
8177 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8181 freeAsmop (right, NULL, ic, TRUE);
8183 aopOp(left, ic, FALSE, FALSE);
8184 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8187 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8189 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8190 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8192 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8195 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8197 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8198 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8200 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8206 emitcode ("; shift left ", "result %d, left %d", size,
8210 /* I suppose that the left size >= result size */
8213 _startLazyDPSEvaluation();
8216 movLeft2Result (left, size, result, size, 0);
8218 _endLazyDPSEvaluation();
8220 else if (shCount >= (size * 8))
8222 _startLazyDPSEvaluation();
8225 aopPut (AOP (result), zero, size);
8227 _endLazyDPSEvaluation();
8234 genlshOne (result, left, shCount);
8238 genlshTwo (result, left, shCount);
8242 genlshFour (result, left, shCount);
8246 fprintf(stderr, "*** ack! mystery literal shift!\n");
8250 freeAsmop (left, NULL, ic, TRUE);
8251 freeAsmop (result, NULL, ic, TRUE);
8256 /*-----------------------------------------------------------------*/
8257 /* genLeftShift - generates code for left shifting */
8258 /*-----------------------------------------------------------------*/
8260 genLeftShift (iCode * ic)
8262 operand *left, *right, *result;
8265 symbol *tlbl, *tlbl1;
8267 D (emitcode (";", "genLeftShift "););
8269 right = IC_RIGHT (ic);
8270 left = IC_LEFT (ic);
8271 result = IC_RESULT (ic);
8273 aopOp (right, ic, FALSE, FALSE);
8276 #ifdef BETTER_LITERAL_SHIFT
8277 /* if the shift count is known then do it
8278 as efficiently as possible */
8279 if (AOP_TYPE (right) == AOP_LIT)
8281 if (genLeftShiftLiteral (left, right, result, ic))
8288 /* shift count is unknown then we have to form
8289 a loop get the loop count in B : Note: we take
8290 only the lower order byte since shifting
8291 more that 32 bits make no sense anyway, ( the
8292 largest size of an object can be only 32 bits ) */
8294 if (AOP_TYPE (right) == AOP_LIT)
8296 /* Really should be handled by genLeftShiftLiteral,
8297 * but since I'm too lazy to fix that today, at least we can make
8298 * some small improvement.
8300 emitcode("mov", "b,#!constbyte",
8301 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8305 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8306 emitcode ("inc", "b");
8308 freeAsmop (right, NULL, ic, TRUE);
8309 aopOp (left, ic, FALSE, FALSE);
8310 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8312 /* now move the left to the result if they are not the
8314 if (!sameRegs (AOP (left), AOP (result)) &&
8315 AOP_SIZE (result) > 1)
8318 size = AOP_SIZE (result);
8320 _startLazyDPSEvaluation ();
8323 l = aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG);
8324 if (*l == '@' && (IS_AOP_PREG (result)))
8327 emitcode ("mov", "a,%s", l);
8328 aopPut (AOP (result), "a", offset);
8331 aopPut (AOP (result), l, offset);
8334 _endLazyDPSEvaluation ();
8337 tlbl = newiTempLabel (NULL);
8338 size = AOP_SIZE (result);
8340 tlbl1 = newiTempLabel (NULL);
8342 /* if it is only one byte then */
8345 symbol *tlbl1 = newiTempLabel (NULL);
8347 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8348 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8349 emitcode ("", "!tlabeldef", tlbl->key + 100);
8350 emitcode ("add", "a,acc");
8351 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8352 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8353 aopPut (AOP (result), "a", 0);
8357 reAdjustPreg (AOP (result));
8359 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8360 emitcode ("", "!tlabeldef", tlbl->key + 100);
8361 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8362 emitcode ("add", "a,acc");
8363 aopPut (AOP (result), "a", offset++);
8364 _startLazyDPSEvaluation ();
8367 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8368 emitcode ("rlc", "a");
8369 aopPut (AOP (result), "a", offset++);
8371 _endLazyDPSEvaluation ();
8372 reAdjustPreg (AOP (result));
8374 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8375 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8377 freeAsmop (left, NULL, ic, TRUE);
8378 freeAsmop (result, NULL, ic, TRUE);
8381 #ifdef BETTER_LITERAL_SHIFT
8382 /*-----------------------------------------------------------------*/
8383 /* genrshOne - right shift a one byte quantity by known count */
8384 /*-----------------------------------------------------------------*/
8386 genrshOne (operand * result, operand * left,
8387 int shCount, int sign)
8389 D (emitcode (";", "genrshOne"););
8390 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8394 #ifdef BETTER_LITERAL_SHIFT
8395 /*-----------------------------------------------------------------*/
8396 /* genrshTwo - right shift two bytes by known amount != 0 */
8397 /*-----------------------------------------------------------------*/
8399 genrshTwo (operand * result, operand * left,
8400 int shCount, int sign)
8402 D (emitcode (";", "genrshTwo"););
8404 /* if shCount >= 8 */
8408 _startLazyDPSEvaluation();
8411 shiftR1Left2Result (left, MSB16, result, LSB,
8416 movLeft2Result (left, MSB16, result, LSB, sign);
8418 addSign (result, MSB16, sign);
8419 _endLazyDPSEvaluation();
8422 /* 1 <= shCount <= 7 */
8425 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8432 /*-----------------------------------------------------------------*/
8433 /* shiftRLong - shift right one long from left to result */
8434 /* offl = LSB or MSB16 */
8435 /*-----------------------------------------------------------------*/
8437 shiftRLong (operand * left, int offl,
8438 operand * result, int sign)
8440 int isSameRegs=sameRegs(AOP(left),AOP(result));
8442 if (isSameRegs && offl>1) {
8443 // we are in big trouble, but this shouldn't happen
8444 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8447 MOVA (aopGet (AOP (left), MSB32, FALSE, NULL));
8452 emitcode ("rlc", "a");
8453 emitcode ("subb", "a,acc");
8454 emitcode ("xch", "a,%s",
8455 aopGet(AOP(left), MSB32, FALSE, DP2_RESULT_REG));
8457 aopPut (AOP(result), zero, MSB32);
8462 emitcode ("clr", "c");
8464 emitcode ("mov", "c,acc.7");
8467 emitcode ("rrc", "a");
8469 if (isSameRegs && offl==MSB16) {
8471 "a,%s",aopGet (AOP (left), MSB24, FALSE, DP2_RESULT_REG));
8473 aopPut (AOP (result), "a", MSB32);
8474 MOVA (aopGet (AOP (left), MSB24, FALSE, NULL));
8477 emitcode ("rrc", "a");
8478 if (isSameRegs && offl==1) {
8479 emitcode ("xch", "a,%s",
8480 aopGet (AOP (left), MSB16, FALSE, DP2_RESULT_REG));
8482 aopPut (AOP (result), "a", MSB24);
8483 MOVA (aopGet (AOP (left), MSB16, FALSE, NULL));
8485 emitcode ("rrc", "a");
8486 aopPut (AOP (result), "a", MSB16 - offl);
8490 MOVA (aopGet (AOP (left), LSB, FALSE, NULL));
8491 emitcode ("rrc", "a");
8492 aopPut (AOP (result), "a", LSB);
8499 /*-----------------------------------------------------------------*/
8500 /* genrshFour - shift four byte by a known amount != 0 */
8501 /*-----------------------------------------------------------------*/
8503 genrshFour (operand * result, operand * left,
8504 int shCount, int sign)
8506 D (emitcode (";", "genrshFour");
8509 /* if shifting more that 3 bytes */
8514 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8516 movLeft2Result (left, MSB32, result, LSB, sign);
8517 addSign (result, MSB16, sign);
8519 else if (shCount >= 16)
8523 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8526 movLeft2Result (left, MSB24, result, LSB, 0);
8527 movLeft2Result (left, MSB32, result, MSB16, sign);
8529 addSign (result, MSB24, sign);
8531 else if (shCount >= 8)
8535 shiftRLong (left, MSB16, result, sign);
8536 else if (shCount == 0)
8538 movLeft2Result (left, MSB16, result, LSB, 0);
8539 movLeft2Result (left, MSB24, result, MSB16, 0);
8540 movLeft2Result (left, MSB32, result, MSB24, sign);
8541 addSign (result, MSB32, sign);
8545 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8546 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8547 /* the last shift is signed */
8548 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8549 addSign (result, MSB32, sign);
8553 { /* 1 <= shCount <= 7 */
8556 shiftRLong (left, LSB, result, sign);
8558 shiftRLong (result, LSB, result, sign);
8562 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8563 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8564 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8570 #ifdef BETTER_LITERAL_SHIFT
8571 /*-----------------------------------------------------------------*/
8572 /* genRightShiftLiteral - right shifting by known count */
8573 /*-----------------------------------------------------------------*/
8575 genRightShiftLiteral (operand * left,
8581 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8584 size = getSize (operandType (result));
8586 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8588 /* We only handle certain easy cases so far. */
8590 && (shCount < (size * 8))
8594 D(emitcode (";", "genRightShiftLiteral wimping out"););
8598 freeAsmop (right, NULL, ic, TRUE);
8600 aopOp (left, ic, FALSE, FALSE);
8601 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8604 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8608 /* test the LEFT size !!! */
8610 /* I suppose that the left size >= result size */
8613 size = getDataSize (result);
8614 _startLazyDPSEvaluation();
8617 movLeft2Result (left, size, result, size, 0);
8619 _endLazyDPSEvaluation();
8621 else if (shCount >= (size * 8))
8625 /* get sign in acc.7 */
8626 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8628 addSign (result, LSB, sign);
8635 genrshOne (result, left, shCount, sign);
8639 genrshTwo (result, left, shCount, sign);
8643 genrshFour (result, left, shCount, sign);
8650 freeAsmop (left, NULL, ic, TRUE);
8651 freeAsmop (result, NULL, ic, TRUE);
8657 /*-----------------------------------------------------------------*/
8658 /* genSignedRightShift - right shift of signed number */
8659 /*-----------------------------------------------------------------*/
8661 genSignedRightShift (iCode * ic)
8663 operand *right, *left, *result;
8666 symbol *tlbl, *tlbl1;
8668 D (emitcode (";", "genSignedRightShift "););
8670 /* we do it the hard way put the shift count in b
8671 and loop thru preserving the sign */
8673 right = IC_RIGHT (ic);
8674 left = IC_LEFT (ic);
8675 result = IC_RESULT (ic);
8677 aopOp (right, ic, FALSE, FALSE);
8679 #ifdef BETTER_LITERAL_SHIFT
8680 if (AOP_TYPE (right) == AOP_LIT)
8682 if (genRightShiftLiteral (left, right, result, ic, 1))
8688 /* shift count is unknown then we have to form
8689 a loop get the loop count in B : Note: we take
8690 only the lower order byte since shifting
8691 more that 32 bits make no sense anyway, ( the
8692 largest size of an object can be only 32 bits ) */
8694 if (AOP_TYPE (right) == AOP_LIT)
8696 /* Really should be handled by genRightShiftLiteral,
8697 * but since I'm too lazy to fix that today, at least we can make
8698 * some small improvement.
8700 emitcode("mov", "b,#!constbyte",
8701 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8705 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8706 emitcode ("inc", "b");
8708 freeAsmop (right, NULL, ic, TRUE);
8709 aopOp (left, ic, FALSE, FALSE);
8710 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8712 /* now move the left to the result if they are not the
8714 if (!sameRegs (AOP (left), AOP (result)) &&
8715 AOP_SIZE (result) > 1)
8718 size = AOP_SIZE (result);
8720 _startLazyDPSEvaluation ();
8723 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8724 if (*l == '@' && IS_AOP_PREG (result))
8727 emitcode ("mov", "a,%s", l);
8728 aopPut (AOP (result), "a", offset);
8731 aopPut (AOP (result), l, offset);
8734 _endLazyDPSEvaluation ();
8737 /* mov the highest order bit to OVR */
8738 tlbl = newiTempLabel (NULL);
8739 tlbl1 = newiTempLabel (NULL);
8741 size = AOP_SIZE (result);
8743 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8744 emitcode ("rlc", "a");
8745 emitcode ("mov", "ov,c");
8746 /* if it is only one byte then */
8749 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8750 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8751 emitcode ("", "!tlabeldef", tlbl->key + 100);
8752 emitcode ("mov", "c,ov");
8753 emitcode ("rrc", "a");
8754 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8755 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8756 aopPut (AOP (result), "a", 0);
8760 reAdjustPreg (AOP (result));
8761 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8762 emitcode ("", "!tlabeldef", tlbl->key + 100);
8763 emitcode ("mov", "c,ov");
8764 _startLazyDPSEvaluation ();
8767 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8768 emitcode ("rrc", "a");
8769 aopPut (AOP (result), "a", offset--);
8771 _endLazyDPSEvaluation ();
8772 reAdjustPreg (AOP (result));
8773 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8774 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8777 freeAsmop (left, NULL, ic, TRUE);
8778 freeAsmop (result, NULL, ic, TRUE);
8781 /*-----------------------------------------------------------------*/
8782 /* genRightShift - generate code for right shifting */
8783 /*-----------------------------------------------------------------*/
8785 genRightShift (iCode * ic)
8787 operand *right, *left, *result;
8791 symbol *tlbl, *tlbl1;
8793 D (emitcode (";", "genRightShift "););
8795 /* if signed then we do it the hard way preserve the
8796 sign bit moving it inwards */
8797 retype = getSpec (operandType (IC_RESULT (ic)));
8799 if (!SPEC_USIGN (retype))
8801 genSignedRightShift (ic);
8805 /* signed & unsigned types are treated the same : i.e. the
8806 signed is NOT propagated inwards : quoting from the
8807 ANSI - standard : "for E1 >> E2, is equivalent to division
8808 by 2**E2 if unsigned or if it has a non-negative value,
8809 otherwise the result is implementation defined ", MY definition
8810 is that the sign does not get propagated */
8812 right = IC_RIGHT (ic);
8813 left = IC_LEFT (ic);
8814 result = IC_RESULT (ic);
8816 aopOp (right, ic, FALSE, FALSE);
8818 #ifdef BETTER_LITERAL_SHIFT
8819 /* if the shift count is known then do it
8820 as efficiently as possible */
8821 if (AOP_TYPE (right) == AOP_LIT)
8823 if (genRightShiftLiteral (left, right, result, ic, 0))
8830 /* shift count is unknown then we have to form
8831 a loop get the loop count in B : Note: we take
8832 only the lower order byte since shifting
8833 more that 32 bits make no sense anyway, ( the
8834 largest size of an object can be only 32 bits ) */
8836 if (AOP_TYPE (right) == AOP_LIT)
8838 /* Really should be handled by genRightShiftLiteral,
8839 * but since I'm too lazy to fix that today, at least we can make
8840 * some small improvement.
8842 emitcode("mov", "b,#!constbyte",
8843 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8847 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8848 emitcode ("inc", "b");
8850 freeAsmop (right, NULL, ic, TRUE);
8851 aopOp (left, ic, FALSE, FALSE);
8852 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8854 /* now move the left to the result if they are not the
8856 if (!sameRegs (AOP (left), AOP (result)) &&
8857 AOP_SIZE (result) > 1)
8860 size = AOP_SIZE (result);
8862 _startLazyDPSEvaluation ();
8865 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8866 if (*l == '@' && IS_AOP_PREG (result))
8869 emitcode ("mov", "a,%s", l);
8870 aopPut (AOP (result), "a", offset);
8873 aopPut (AOP (result), l, offset);
8876 _endLazyDPSEvaluation ();
8879 tlbl = newiTempLabel (NULL);
8880 tlbl1 = newiTempLabel (NULL);
8881 size = AOP_SIZE (result);
8884 /* if it is only one byte then */
8887 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8888 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8889 emitcode ("", "!tlabeldef", tlbl->key + 100);
8891 emitcode ("rrc", "a");
8892 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8893 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8894 aopPut (AOP (result), "a", 0);
8898 reAdjustPreg (AOP (result));
8899 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8900 emitcode ("", "!tlabeldef", tlbl->key + 100);
8902 _startLazyDPSEvaluation ();
8905 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8906 emitcode ("rrc", "a");
8907 aopPut (AOP (result), "a", offset--);
8909 _endLazyDPSEvaluation ();
8910 reAdjustPreg (AOP (result));
8912 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8913 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8916 freeAsmop (left, NULL, ic, TRUE);
8917 freeAsmop (result, NULL, ic, TRUE);
8920 /*-----------------------------------------------------------------*/
8921 /* genUnpackBits - generates code for unpacking bits */
8922 /*-----------------------------------------------------------------*/
8924 genUnpackBits (operand * result, char *rname, int ptype)
8931 D (emitcode (";", "genUnpackBits "););
8933 etype = getSpec (operandType (result));
8935 /* read the first byte */
8941 emitcode ("mov", "a,@%s", rname);
8945 emitcode ("movx", "a,@%s", rname);
8949 emitcode ("movx", "a,@dptr");
8953 emitcode ("clr", "a");
8954 emitcode ("movc", "a,@a+dptr");
8958 emitcode ("lcall", "__gptrget");
8962 /* if we have bitdisplacement then it fits */
8963 /* into this byte completely or if length is */
8964 /* less than a byte */
8965 if (((shCnt = SPEC_BSTR (etype)) != 0) || (SPEC_BLEN (etype) <= 8))
8968 /* shift right acc */
8971 emitcode ("anl", "a,#!constbyte",
8972 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8973 aopPut (AOP (result), "a", offset);
8977 /* bit field did not fit in a byte */
8978 rlen = SPEC_BLEN (etype) - 8;
8979 aopPut (AOP (result), "a", offset++);
8988 emitcode ("inc", "%s", rname);
8989 emitcode ("mov", "a,@%s", rname);
8993 emitcode ("inc", "%s", rname);
8994 emitcode ("movx", "a,@%s", rname);
8998 emitcode ("inc", "dptr");
8999 emitcode ("movx", "a,@dptr");
9003 emitcode ("clr", "a");
9004 emitcode ("inc", "dptr");
9005 emitcode ("movc", "a,@a+dptr");
9009 emitcode ("inc", "dptr");
9010 emitcode ("lcall", "__gptrget");
9015 /* if we are done */
9019 aopPut (AOP (result), "a", offset++);
9025 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
9026 aopPut (AOP (result), "a", offset);
9033 /*-----------------------------------------------------------------*/
9034 /* genDataPointerGet - generates code when ptr offset is known */
9035 /*-----------------------------------------------------------------*/
9037 genDataPointerGet (operand * left,
9043 int size, offset = 0;
9044 aopOp (result, ic, TRUE, FALSE);
9046 /* get the string representation of the name */
9047 l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9048 size = AOP_SIZE (result);
9049 _startLazyDPSEvaluation ();
9054 SNPRINTF (buff, sizeof(buff),
9055 "(%s + %d)", l + 1, offset);
9059 SNPRINTF (buff, sizeof(buff),
9062 aopPut (AOP (result), buff, offset++);
9064 _endLazyDPSEvaluation ();
9066 freeAsmop (left, NULL, ic, TRUE);
9067 freeAsmop (result, NULL, ic, TRUE);
9070 /*-----------------------------------------------------------------*/
9071 /* genNearPointerGet - emitcode for near pointer fetch */
9072 /*-----------------------------------------------------------------*/
9074 genNearPointerGet (operand * left,
9082 sym_link *rtype, *retype, *letype;
9083 sym_link *ltype = operandType (left);
9086 rtype = operandType (result);
9087 retype = getSpec (rtype);
9088 letype = getSpec (ltype);
9090 aopOp (left, ic, FALSE, FALSE);
9092 /* if left is rematerialisable and
9093 result is not bit variable type and
9094 the left is pointer to data space i.e
9095 lower 128 bytes of space */
9096 if (AOP_TYPE (left) == AOP_IMMD &&
9097 !IS_BITVAR (retype) &&
9098 !IS_BITVAR (letype) &&
9099 DCL_TYPE (ltype) == POINTER)
9101 genDataPointerGet (left, result, ic);
9105 /* if the value is already in a pointer register
9106 then don't need anything more */
9107 if (!AOP_INPREG (AOP (left)))
9109 /* otherwise get a free pointer register */
9111 preg = getFreePtr (ic, &aop, FALSE);
9112 emitcode ("mov", "%s,%s",
9114 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9118 rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9120 freeAsmop (left, NULL, ic, TRUE);
9121 aopOp (result, ic, FALSE, FALSE);
9123 /* if bitfield then unpack the bits */
9124 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9125 genUnpackBits (result, rname, POINTER);
9128 /* we have can just get the values */
9129 int size = AOP_SIZE (result);
9134 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9137 emitcode ("mov", "a,@%s", rname);
9138 aopPut (AOP (result), "a", offset);
9142 SNPRINTF (buff, sizeof(buff), "@%s", rname);
9143 aopPut (AOP (result), buff, offset);
9148 emitcode ("inc", "%s", rname);
9153 /* now some housekeeping stuff */
9156 /* we had to allocate for this iCode */
9157 if (pi) { /* post increment present */
9158 aopPut(AOP ( left ),rname,0);
9160 freeAsmop (NULL, aop, ic, TRUE);
9164 /* we did not allocate which means left
9165 already in a pointer register, then
9166 if size > 0 && this could be used again
9167 we have to point it back to where it
9169 if (AOP_SIZE (result) > 1 &&
9170 !OP_SYMBOL (left)->remat &&
9171 (OP_SYMBOL (left)->liveTo > ic->seq ||
9175 int size = AOP_SIZE (result) - 1;
9177 emitcode ("dec", "%s", rname);
9182 freeAsmop (result, NULL, ic, TRUE);
9183 if (pi) pi->generated = 1;
9186 /*-----------------------------------------------------------------*/
9187 /* genPagedPointerGet - emitcode for paged pointer fetch */
9188 /*-----------------------------------------------------------------*/
9190 genPagedPointerGet (operand * left,
9198 sym_link *rtype, *retype, *letype;
9200 rtype = operandType (result);
9201 retype = getSpec (rtype);
9202 letype = getSpec (operandType (left));
9203 aopOp (left, ic, FALSE, FALSE);
9205 /* if the value is already in a pointer register
9206 then don't need anything more */
9207 if (!AOP_INPREG (AOP (left)))
9209 /* otherwise get a free pointer register */
9211 preg = getFreePtr (ic, &aop, FALSE);
9212 emitcode ("mov", "%s,%s",
9214 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9218 rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9220 freeAsmop (left, NULL, ic, TRUE);
9221 aopOp (result, ic, FALSE, FALSE);
9223 /* if bitfield then unpack the bits */
9224 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9225 genUnpackBits (result, rname, PPOINTER);
9228 /* we have can just get the values */
9229 int size = AOP_SIZE (result);
9235 emitcode ("movx", "a,@%s", rname);
9236 aopPut (AOP (result), "a", offset);
9241 emitcode ("inc", "%s", rname);
9245 /* now some housekeeping stuff */
9248 /* we had to allocate for this iCode */
9249 if (pi) aopPut ( AOP (left), rname, 0);
9250 freeAsmop (NULL, aop, ic, TRUE);
9254 /* we did not allocate which means left
9255 already in a pointer register, then
9256 if size > 0 && this could be used again
9257 we have to point it back to where it
9259 if (AOP_SIZE (result) > 1 &&
9260 !OP_SYMBOL (left)->remat &&
9261 (OP_SYMBOL (left)->liveTo > ic->seq ||
9265 int size = AOP_SIZE (result) - 1;
9267 emitcode ("dec", "%s", rname);
9272 freeAsmop (result, NULL, ic, TRUE);
9273 if (pi) pi->generated = 1;
9276 /*-----------------------------------------------------------------*/
9277 /* genFarPointerGet - gget value from far space */
9278 /*-----------------------------------------------------------------*/
9280 genFarPointerGet (operand * left,
9281 operand * result, iCode * ic, iCode *pi)
9283 int size, offset, dopi=1;
9284 sym_link *retype = getSpec (operandType (result));
9285 sym_link *letype = getSpec (operandType (left));
9286 D (emitcode (";", "genFarPointerGet"););
9288 aopOp (left, ic, FALSE, FALSE);
9290 /* if the operand is already in dptr
9291 then we do nothing else we move the value to dptr */
9292 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9294 /* if this is remateriazable */
9295 if (AOP_TYPE (left) == AOP_IMMD)
9297 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9301 /* we need to get it byte by byte */
9302 _startLazyDPSEvaluation ();
9303 if (AOP_TYPE (left) != AOP_DPTR)
9305 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9306 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9307 if (options.model == MODEL_FLAT24)
9308 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9312 /* We need to generate a load to DPTR indirect through DPTR. */
9313 D (emitcode (";", "genFarPointerGet -- indirection special case.");
9315 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9316 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9317 if (options.model == MODEL_FLAT24)
9318 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9319 emitcode ("pop", "dph");
9320 emitcode ("pop", "dpl");
9323 _endLazyDPSEvaluation ();
9326 /* so dptr know contains the address */
9327 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9329 /* if bit then unpack */
9330 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9331 if (AOP_INDPTRn(left)) {
9332 genSetDPTR(AOP(left)->aopu.dptr);
9334 genUnpackBits (result, "dptr", FPOINTER);
9335 if (AOP_INDPTRn(left)) {
9340 size = AOP_SIZE (result);
9343 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9345 genSetDPTR(AOP(left)->aopu.dptr);
9346 emitcode ("movx", "a,@dptr");
9347 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9348 emitcode ("inc", "dptr");
9350 aopPut (AOP (result), "a", offset++);
9353 _startLazyDPSEvaluation ();
9355 if (AOP_INDPTRn(left)) {
9356 genSetDPTR(AOP(left)->aopu.dptr);
9362 emitcode ("movx", "a,@dptr");
9363 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9364 emitcode ("inc", "dptr");
9366 aopPut (AOP (result), "a", offset++);
9368 _endLazyDPSEvaluation ();
9371 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9372 if (!AOP_INDPTRn(left)) {
9373 aopPut ( AOP (left), "dpl", 0);
9374 aopPut ( AOP (left), "dph", 1);
9375 if (options.model == MODEL_FLAT24)
9376 aopPut ( AOP (left), "dpx", 2);
9379 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9380 AOP_SIZE(result) > 1 &&
9381 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9383 size = AOP_SIZE (result) - 1;
9384 if (AOP_INDPTRn(left)) {
9385 genSetDPTR(AOP(left)->aopu.dptr);
9387 while (size--) emitcode ("lcall","__decdptr");
9388 if (AOP_INDPTRn(left)) {
9393 freeAsmop (left, NULL, ic, TRUE);
9394 freeAsmop (result, NULL, ic, TRUE);
9397 /*-----------------------------------------------------------------*/
9398 /* genCodePointerGet - get value from code space */
9399 /*-----------------------------------------------------------------*/
9401 genCodePointerGet (operand * left,
9402 operand * result, iCode * ic, iCode *pi)
9404 int size, offset, dopi=1;
9405 sym_link *retype = getSpec (operandType (result));
9407 aopOp (left, ic, FALSE, FALSE);
9409 /* if the operand is already in dptr
9410 then we do nothing else we move the value to dptr */
9411 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9413 /* if this is remateriazable */
9414 if (AOP_TYPE (left) == AOP_IMMD)
9416 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9419 { /* we need to get it byte by byte */
9420 _startLazyDPSEvaluation ();
9421 if (AOP_TYPE (left) != AOP_DPTR)
9423 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9424 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9425 if (options.model == MODEL_FLAT24)
9426 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9430 /* We need to generate a load to DPTR indirect through DPTR. */
9431 D (emitcode (";", "gencodePointerGet -- indirection special case.");
9433 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9434 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9435 if (options.model == MODEL_FLAT24)
9436 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9437 emitcode ("pop", "dph");
9438 emitcode ("pop", "dpl");
9441 _endLazyDPSEvaluation ();
9444 /* so dptr know contains the address */
9445 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9447 /* if bit then unpack */
9448 if (IS_BITVAR (retype)) {
9449 if (AOP_INDPTRn(left)) {
9450 genSetDPTR(AOP(left)->aopu.dptr);
9452 genUnpackBits (result, "dptr", CPOINTER);
9453 if (AOP_INDPTRn(left)) {
9458 size = AOP_SIZE (result);
9460 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9462 genSetDPTR(AOP(left)->aopu.dptr);
9463 emitcode ("clr", "a");
9464 emitcode ("movc", "a,@a+dptr");
9465 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9466 emitcode ("inc", "dptr");
9468 aopPut (AOP (result), "a", offset++);
9471 _startLazyDPSEvaluation ();
9474 if (AOP_INDPTRn(left)) {
9475 genSetDPTR(AOP(left)->aopu.dptr);
9481 emitcode ("clr", "a");
9482 emitcode ("movc", "a,@a+dptr");
9483 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9484 emitcode ("inc", "dptr");
9485 aopPut (AOP (result), "a", offset++);
9487 _endLazyDPSEvaluation ();
9490 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9491 if (!AOP_INDPTRn(left)) {
9492 aopPut ( AOP (left), "dpl", 0);
9493 aopPut ( AOP (left), "dph", 1);
9494 if (options.model == MODEL_FLAT24)
9495 aopPut ( AOP (left), "dpx", 2);
9498 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9499 AOP_SIZE(result) > 1 &&
9500 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9502 size = AOP_SIZE (result) - 1;
9503 if (AOP_INDPTRn(left)) {
9504 genSetDPTR(AOP(left)->aopu.dptr);
9506 while (size--) emitcode ("lcall","__decdptr");
9507 if (AOP_INDPTRn(left)) {
9512 freeAsmop (left, NULL, ic, TRUE);
9513 freeAsmop (result, NULL, ic, TRUE);
9516 /*-----------------------------------------------------------------*/
9517 /* genGenPointerGet - gget value from generic pointer space */
9518 /*-----------------------------------------------------------------*/
9520 genGenPointerGet (operand * left,
9521 operand * result, iCode * ic, iCode * pi)
9524 sym_link *retype = getSpec (operandType (result));
9525 sym_link *letype = getSpec (operandType (left));
9527 D (emitcode (";", "genGenPointerGet "); );
9529 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9531 /* if the operand is already in dptr
9532 then we do nothing else we move the value to dptr */
9533 if (AOP_TYPE (left) != AOP_STR)
9535 /* if this is remateriazable */
9536 if (AOP_TYPE (left) == AOP_IMMD)
9538 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9539 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9541 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9545 emitcode ("mov", "b,#%d", pointerCode (retype));
9549 { /* we need to get it byte by byte */
9550 _startLazyDPSEvaluation ();
9551 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9552 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9553 if (options.model == MODEL_FLAT24) {
9554 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9555 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9557 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9559 _endLazyDPSEvaluation ();
9563 /* so dptr-b now contains the address */
9565 aopOp (result, ic, FALSE, TRUE);
9568 /* if bit then unpack */
9569 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9571 genUnpackBits (result, "dptr", GPOINTER);
9575 size = AOP_SIZE (result);
9582 // Get two bytes at a time, results in _AP & A.
9583 // dptr will be incremented ONCE by __gptrgetWord.
9585 // Note: any change here must be coordinated
9586 // with the implementation of __gptrgetWord
9587 // in device/lib/_gptrget.c
9588 emitcode ("lcall", "__gptrgetWord");
9589 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9590 aopPut (AOP (result), "a", offset++);
9595 // Only one byte to get.
9596 emitcode ("lcall", "__gptrget");
9597 aopPut (AOP (result), "a", offset++);
9600 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9602 emitcode ("inc", "dptr");
9607 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9608 aopPut ( AOP (left), "dpl", 0);
9609 aopPut ( AOP (left), "dph", 1);
9610 if (options.model == MODEL_FLAT24) {
9611 aopPut ( AOP (left), "dpx", 2);
9612 aopPut ( AOP (left), "b", 3);
9613 } else aopPut ( AOP (left), "b", 2);
9615 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9616 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9618 size = AOP_SIZE (result) - 1;
9619 while (size--) emitcode ("lcall","__decdptr");
9622 freeAsmop (left, NULL, ic, TRUE);
9623 freeAsmop (result, NULL, ic, TRUE);
9626 /*-----------------------------------------------------------------*/
9627 /* genPointerGet - generate code for pointer get */
9628 /*-----------------------------------------------------------------*/
9630 genPointerGet (iCode * ic, iCode *pi)
9632 operand *left, *result;
9633 sym_link *type, *etype;
9636 D (emitcode (";", "genPointerGet ");
9639 left = IC_LEFT (ic);
9640 result = IC_RESULT (ic);
9642 /* depending on the type of pointer we need to
9643 move it to the correct pointer register */
9644 type = operandType (left);
9645 etype = getSpec (type);
9646 /* if left is of type of pointer then it is simple */
9647 if (IS_PTR (type) && !IS_FUNC (type->next))
9648 p_type = DCL_TYPE (type);
9651 /* we have to go by the storage class */
9652 p_type = PTR_TYPE (SPEC_OCLS (etype));
9654 /* special case when cast remat */
9655 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9656 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9657 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9658 type = operandType (left);
9659 p_type = DCL_TYPE (type);
9661 /* now that we have the pointer type we assign
9662 the pointer values */
9668 genNearPointerGet (left, result, ic, pi);
9672 genPagedPointerGet (left, result, ic, pi);
9676 genFarPointerGet (left, result, ic, pi);
9680 genCodePointerGet (left, result, ic, pi);
9684 genGenPointerGet (left, result, ic, pi);
9690 /*-----------------------------------------------------------------*/
9691 /* genPackBits - generates code for packed bit storage */
9692 /*-----------------------------------------------------------------*/
9694 genPackBits (sym_link * etype,
9696 char *rname, int p_type)
9703 blen = SPEC_BLEN (etype);
9704 bstr = SPEC_BSTR (etype);
9706 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9708 /* if the bit lenth is less than or */
9709 /* it exactly fits a byte then */
9710 if (SPEC_BLEN (etype) <= 8)
9712 /* shift left acc */
9713 AccLsh (SPEC_BSTR (etype));
9715 if (SPEC_BLEN (etype) < 8)
9716 { /* if smaller than a byte */
9722 emitcode ("mov", "b,a");
9723 emitcode ("mov", "a,@%s", rname);
9727 emitcode ("mov", "b,a");
9728 emitcode ("movx", "a,@dptr");
9732 emitcode ("push", "b");
9733 emitcode ("push", "acc");
9734 emitcode ("lcall", "__gptrget");
9735 emitcode ("pop", "b");
9739 emitcode ("anl", "a,#!constbyte", (unsigned char)
9740 ((unsigned char) (0xFF << (blen + bstr)) |
9741 (unsigned char) (0xFF >> (8 - bstr))));
9742 emitcode ("orl", "a,b");
9743 if (p_type == GPOINTER)
9744 emitcode ("pop", "b");
9751 emitcode ("mov", "@%s,a", rname);
9755 emitcode ("movx", "@dptr,a");
9759 emitcode ("lcall", "__gptrput");
9764 if (SPEC_BLEN (etype) <= 8)
9767 emitcode ("inc", "%s", rname);
9768 rLen = SPEC_BLEN (etype);
9770 /* now generate for lengths greater than one byte */
9774 l = aopGet (AOP (right), offset++, FALSE, TRUE, NULL);
9786 emitcode ("mov", "@%s,a", rname);
9789 emitcode ("mov", "@%s,%s", rname, l);
9794 emitcode ("movx", "@dptr,a");
9799 emitcode ("lcall", "__gptrput");
9802 emitcode ("inc", "%s", rname);
9807 /* last last was not complete */
9810 /* save the byte & read byte */
9814 emitcode ("mov", "b,a");
9815 emitcode ("mov", "a,@%s", rname);
9819 emitcode ("mov", "b,a");
9820 emitcode ("movx", "a,@dptr");
9824 emitcode ("push", "b");
9825 emitcode ("push", "acc");
9826 emitcode ("lcall", "__gptrget");
9827 emitcode ("pop", "b");
9831 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9832 emitcode ("orl", "a,b");
9835 if (p_type == GPOINTER)
9836 emitcode ("pop", "b");
9842 emitcode ("mov", "@%s,a", rname);
9846 emitcode ("movx", "@dptr,a");
9850 emitcode ("lcall", "__gptrput");
9854 /*-----------------------------------------------------------------*/
9855 /* genDataPointerSet - remat pointer to data space */
9856 /*-----------------------------------------------------------------*/
9858 genDataPointerSet (operand * right,
9862 int size, offset = 0;
9865 aopOp (right, ic, FALSE, FALSE);
9867 l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
9868 size = AOP_SIZE (right);
9873 SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
9877 SNPRINTF (buff, sizeof(buff), "%s", l + 1);
9880 emitcode ("mov", "%s,%s", buff,
9881 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9884 freeAsmop (right, NULL, ic, TRUE);
9885 freeAsmop (result, NULL, ic, TRUE);
9888 /*-----------------------------------------------------------------*/
9889 /* genNearPointerSet - emitcode for near pointer put */
9890 /*-----------------------------------------------------------------*/
9892 genNearPointerSet (operand * right,
9899 sym_link *retype, *letype;
9900 sym_link *ptype = operandType (result);
9902 retype = getSpec (operandType (right));
9903 letype = getSpec (ptype);
9905 aopOp (result, ic, FALSE, FALSE);
9907 /* if the result is rematerializable &
9908 in data space & not a bit variable */
9909 if (AOP_TYPE (result) == AOP_IMMD &&
9910 DCL_TYPE (ptype) == POINTER &&
9911 !IS_BITVAR (retype) &&
9912 !IS_BITVAR (letype))
9914 genDataPointerSet (right, result, ic);
9918 /* if the value is already in a pointer register
9919 then don't need anything more */
9920 if (!AOP_INPREG (AOP (result)))
9922 /* otherwise get a free pointer register */
9926 preg = getFreePtr (ic, &aop, FALSE);
9927 emitcode ("mov", "%s,%s",
9929 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
9933 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
9935 aopOp (right, ic, FALSE, FALSE);
9937 /* if bitfield then unpack the bits */
9938 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9939 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9942 /* we have can just get the values */
9943 int size = AOP_SIZE (right);
9948 l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
9952 emitcode ("mov", "@%s,a", rname);
9955 emitcode ("mov", "@%s,%s", rname, l);
9957 emitcode ("inc", "%s", rname);
9962 /* now some housekeeping stuff */
9965 /* we had to allocate for this iCode */
9966 if (pi) aopPut (AOP (result),rname,0);
9967 freeAsmop (NULL, aop, ic, TRUE);
9971 /* we did not allocate which means left
9972 already in a pointer register, then
9973 if size > 0 && this could be used again
9974 we have to point it back to where it
9976 if (AOP_SIZE (right) > 1 &&
9977 !OP_SYMBOL (result)->remat &&
9978 (OP_SYMBOL (result)->liveTo > ic->seq ||
9982 int size = AOP_SIZE (right) - 1;
9984 emitcode ("dec", "%s", rname);
9989 if (pi) pi->generated = 1;
9990 freeAsmop (result, NULL, ic, TRUE);
9991 freeAsmop (right, NULL, ic, TRUE);
9996 /*-----------------------------------------------------------------*/
9997 /* genPagedPointerSet - emitcode for Paged pointer put */
9998 /*-----------------------------------------------------------------*/
10000 genPagedPointerSet (operand * right,
10007 sym_link *retype, *letype;
10009 retype = getSpec (operandType (right));
10010 letype = getSpec (operandType (result));
10012 aopOp (result, ic, FALSE, FALSE);
10014 /* if the value is already in a pointer register
10015 then don't need anything more */
10016 if (!AOP_INPREG (AOP (result)))
10018 /* otherwise get a free pointer register */
10021 aop = newAsmop (0);
10022 preg = getFreePtr (ic, &aop, FALSE);
10023 emitcode ("mov", "%s,%s",
10025 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10026 rname = preg->name;
10029 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10031 aopOp (right, ic, FALSE, FALSE);
10033 /* if bitfield then unpack the bits */
10034 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10035 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10038 /* we have can just get the values */
10039 int size = AOP_SIZE (right);
10044 MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10046 emitcode ("movx", "@%s,a", rname);
10049 emitcode ("inc", "%s", rname);
10055 /* now some housekeeping stuff */
10058 if (pi) aopPut (AOP (result),rname,0);
10059 /* we had to allocate for this iCode */
10060 freeAsmop (NULL, aop, ic, TRUE);
10064 /* we did not allocate which means left
10065 already in a pointer register, then
10066 if size > 0 && this could be used again
10067 we have to point it back to where it
10069 if (AOP_SIZE (right) > 1 &&
10070 !OP_SYMBOL (result)->remat &&
10071 (OP_SYMBOL (result)->liveTo > ic->seq ||
10075 int size = AOP_SIZE (right) - 1;
10077 emitcode ("dec", "%s", rname);
10082 if (pi) pi->generated = 1;
10083 freeAsmop (result, NULL, ic, TRUE);
10084 freeAsmop (right, NULL, ic, TRUE);
10089 /*-----------------------------------------------------------------*/
10090 /* genFarPointerSet - set value from far space */
10091 /*-----------------------------------------------------------------*/
10093 genFarPointerSet (operand * right,
10094 operand * result, iCode * ic, iCode *pi)
10096 int size, offset, dopi=1;
10097 sym_link *retype = getSpec (operandType (right));
10098 sym_link *letype = getSpec (operandType (result));
10100 aopOp (result, ic, FALSE, FALSE);
10102 /* if the operand is already in dptr
10103 then we do nothing else we move the value to dptr */
10104 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10106 /* if this is remateriazable */
10107 if (AOP_TYPE (result) == AOP_IMMD)
10108 emitcode ("mov", "dptr,%s",
10109 aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10112 /* we need to get it byte by byte */
10113 _startLazyDPSEvaluation ();
10114 if (AOP_TYPE (result) != AOP_DPTR)
10116 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10117 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10118 if (options.model == MODEL_FLAT24)
10119 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10123 /* We need to generate a load to DPTR indirect through DPTR. */
10124 D (emitcode (";", "genFarPointerSet -- indirection special case."););
10126 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10127 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10128 if (options.model == MODEL_FLAT24)
10129 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10130 emitcode ("pop", "dph");
10131 emitcode ("pop", "dpl");
10134 _endLazyDPSEvaluation ();
10137 /* so dptr know contains the address */
10138 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10140 /* if bit then unpack */
10141 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10142 if (AOP_INDPTRn(result)) {
10143 genSetDPTR(AOP(result)->aopu.dptr);
10145 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10146 if (AOP_INDPTRn(result)) {
10150 size = AOP_SIZE (right);
10152 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10154 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10156 genSetDPTR(AOP(result)->aopu.dptr);
10157 emitcode ("movx", "@dptr,a");
10158 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10159 emitcode ("inc", "dptr");
10163 _startLazyDPSEvaluation ();
10165 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10167 if (AOP_INDPTRn(result)) {
10168 genSetDPTR(AOP(result)->aopu.dptr);
10174 emitcode ("movx", "@dptr,a");
10175 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10176 emitcode ("inc", "dptr");
10178 _endLazyDPSEvaluation ();
10182 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10183 if (!AOP_INDPTRn(result)) {
10184 aopPut (AOP(result),"dpl",0);
10185 aopPut (AOP(result),"dph",1);
10186 if (options.model == MODEL_FLAT24)
10187 aopPut (AOP(result),"dpx",2);
10190 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10191 AOP_SIZE(right) > 1 &&
10192 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10194 size = AOP_SIZE (right) - 1;
10195 if (AOP_INDPTRn(result)) {
10196 genSetDPTR(AOP(result)->aopu.dptr);
10198 while (size--) emitcode ("lcall","__decdptr");
10199 if (AOP_INDPTRn(result)) {
10203 freeAsmop (result, NULL, ic, TRUE);
10204 freeAsmop (right, NULL, ic, TRUE);
10207 /*-----------------------------------------------------------------*/
10208 /* genGenPointerSet - set value from generic pointer space */
10209 /*-----------------------------------------------------------------*/
10211 genGenPointerSet (operand * right,
10212 operand * result, iCode * ic, iCode *pi)
10215 sym_link *retype = getSpec (operandType (right));
10216 sym_link *letype = getSpec (operandType (result));
10218 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10220 /* if the operand is already in dptr
10221 then we do nothing else we move the value to dptr */
10222 if (AOP_TYPE (result) != AOP_STR)
10224 _startLazyDPSEvaluation ();
10225 /* if this is remateriazable */
10226 if (AOP_TYPE (result) == AOP_IMMD)
10228 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10229 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10231 MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10236 "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10240 { /* we need to get it byte by byte */
10241 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10242 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10243 if (options.model == MODEL_FLAT24) {
10244 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10245 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10247 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10250 _endLazyDPSEvaluation ();
10252 /* so dptr know contains the address */
10253 aopOp (right, ic, FALSE, TRUE);
10255 /* if bit then unpack */
10256 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10257 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10260 size = AOP_SIZE (right);
10263 _startLazyDPSEvaluation ();
10266 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10271 emitcode ("lcall", "__gptrput");
10272 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10273 emitcode ("inc", "dptr");
10275 _endLazyDPSEvaluation ();
10278 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10279 aopPut (AOP(result),"dpl",0);
10280 aopPut (AOP(result),"dph",1);
10281 if (options.model == MODEL_FLAT24) {
10282 aopPut (AOP(result),"dpx",2);
10283 aopPut (AOP(result),"b",3);
10285 aopPut (AOP(result),"b",2);
10288 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10289 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10291 size = AOP_SIZE (right) - 1;
10292 while (size--) emitcode ("lcall","__decdptr");
10294 freeAsmop (result, NULL, ic, TRUE);
10295 freeAsmop (right, NULL, ic, TRUE);
10298 /*-----------------------------------------------------------------*/
10299 /* genPointerSet - stores the value into a pointer location */
10300 /*-----------------------------------------------------------------*/
10302 genPointerSet (iCode * ic, iCode *pi)
10304 operand *right, *result;
10305 sym_link *type, *etype;
10308 D (emitcode (";", "genPointerSet "););
10310 right = IC_RIGHT (ic);
10311 result = IC_RESULT (ic);
10313 /* depending on the type of pointer we need to
10314 move it to the correct pointer register */
10315 type = operandType (result);
10316 etype = getSpec (type);
10317 /* if left is of type of pointer then it is simple */
10318 if (IS_PTR (type) && !IS_FUNC (type->next))
10320 p_type = DCL_TYPE (type);
10324 /* we have to go by the storage class */
10325 p_type = PTR_TYPE (SPEC_OCLS (etype));
10327 /* special case when cast remat */
10328 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10329 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10330 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10331 type = operandType (result);
10332 p_type = DCL_TYPE (type);
10335 /* now that we have the pointer type we assign
10336 the pointer values */
10342 genNearPointerSet (right, result, ic, pi);
10346 genPagedPointerSet (right, result, ic, pi);
10350 genFarPointerSet (right, result, ic, pi);
10354 genGenPointerSet (right, result, ic, pi);
10358 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10359 "genPointerSet: illegal pointer type");
10364 /*-----------------------------------------------------------------*/
10365 /* genIfx - generate code for Ifx statement */
10366 /*-----------------------------------------------------------------*/
10368 genIfx (iCode * ic, iCode * popIc)
10370 operand *cond = IC_COND (ic);
10373 D (emitcode (";", "genIfx "););
10375 aopOp (cond, ic, FALSE, FALSE);
10377 /* get the value into acc */
10378 if (AOP_TYPE (cond) != AOP_CRY)
10387 /* the result is now in the accumulator */
10388 freeAsmop (cond, NULL, ic, TRUE);
10390 /* if there was something to be popped then do it */
10394 /* if the condition is a bit variable */
10395 if (isbit && IS_ITEMP (cond) &&
10398 genIfxJump (ic, SPIL_LOC (cond)->rname);
10400 else if (isbit && !IS_ITEMP (cond))
10402 genIfxJump (ic, OP_SYMBOL (cond)->rname);
10406 genIfxJump (ic, "a");
10412 /*-----------------------------------------------------------------*/
10413 /* genAddrOf - generates code for address of */
10414 /*-----------------------------------------------------------------*/
10416 genAddrOf (iCode * ic)
10418 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10421 D (emitcode (";", "genAddrOf ");
10424 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10426 /* if the operand is on the stack then we
10427 need to get the stack offset of this
10429 if (sym->onStack) {
10431 /* if 10 bit stack */
10432 if (options.stack10bit) {
10434 tsprintf(buff, sizeof(buff),
10435 "#!constbyte",(options.stack_loc >> 16) & 0xff);
10436 /* if it has an offset then we need to compute it */
10437 /* emitcode ("subb", "a,#!constbyte", */
10438 /* -((sym->stack < 0) ? */
10439 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10440 /* ((short) sym->stack)) & 0xff); */
10441 /* emitcode ("mov","b,a"); */
10442 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10443 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10444 /* ((short) sym->stack)) >> 8) & 0xff); */
10446 emitcode ("mov", "a,_bpx");
10447 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
10448 ((char) (sym->stack - _G.nRegsSaved)) :
10449 ((char) sym->stack )) & 0xff);
10450 emitcode ("mov", "b,a");
10451 emitcode ("mov", "a,_bpx+1");
10452 emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ?
10453 ((short) (sym->stack - _G.nRegsSaved)) :
10454 ((short) sym->stack )) >> 8) & 0xff);
10455 aopPut (AOP (IC_RESULT (ic)), "b", 0);
10456 aopPut (AOP (IC_RESULT (ic)), "a", 1);
10457 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10459 /* we can just move _bp */
10460 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10461 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10462 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10465 /* if it has an offset then we need to compute it */
10467 emitcode ("mov", "a,_bp");
10468 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10469 aopPut (AOP (IC_RESULT (ic)), "a", 0);
10471 /* we can just move _bp */
10472 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10474 /* fill the result with zero */
10475 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10478 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10480 "*** warning: pointer to stack var truncated.\n");
10485 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10491 /* object not on stack then we need the name */
10492 size = AOP_SIZE (IC_RESULT (ic));
10497 char s[SDCC_NAME_MAX];
10501 tsprintf(s, sizeof(s), "!his",sym->rname);
10504 tsprintf(s, sizeof(s), "!hihis",sym->rname);
10507 tsprintf(s, sizeof(s), "!hihihis",sym->rname);
10509 default: /* should not need this (just in case) */
10510 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10517 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10520 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10524 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10528 /*-----------------------------------------------------------------*/
10529 /* genArrayInit - generates code for address of */
10530 /*-----------------------------------------------------------------*/
10532 genArrayInit (iCode * ic)
10534 literalList *iLoop;
10536 int elementSize = 0, eIndex;
10537 unsigned val, lastVal;
10539 operand *left=IC_LEFT(ic);
10541 D (emitcode (";", "genArrayInit "););
10543 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10545 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10547 // Load immediate value into DPTR.
10548 emitcode("mov", "dptr, %s",
10549 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10551 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10554 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10555 "Unexpected operand to genArrayInit.\n");
10558 // a regression because of SDCCcse.c:1.52
10559 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10560 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10561 if (options.model == MODEL_FLAT24)
10562 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10566 type = operandType(IC_LEFT(ic));
10568 if (type && type->next)
10570 elementSize = getSize(type->next);
10574 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10575 "can't determine element size in genArrayInit.\n");
10579 iLoop = IC_ARRAYILIST(ic);
10584 bool firstpass = TRUE;
10586 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10587 iLoop->count, (int)iLoop->literalValue, elementSize);
10593 symbol *tlbl = NULL;
10595 count = ix > 256 ? 256 : ix;
10599 tlbl = newiTempLabel (NULL);
10600 if (firstpass || (count & 0xff))
10602 emitcode("mov", "b, #!constbyte", count & 0xff);
10605 emitcode ("", "!tlabeldef", tlbl->key + 100);
10610 for (eIndex = 0; eIndex < elementSize; eIndex++)
10612 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10613 if (val != lastVal)
10615 emitcode("mov", "a, #!constbyte", val);
10619 emitcode("movx", "@dptr, a");
10620 emitcode("inc", "dptr");
10625 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10631 iLoop = iLoop->next;
10634 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10637 /*-----------------------------------------------------------------*/
10638 /* genFarFarAssign - assignment when both are in far space */
10639 /*-----------------------------------------------------------------*/
10641 genFarFarAssign (operand * result, operand * right, iCode * ic)
10643 int size = AOP_SIZE (right);
10645 symbol *rSym = NULL;
10649 /* quick & easy case. */
10650 D(emitcode(";","genFarFarAssign (1 byte case)"););
10651 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10652 freeAsmop (right, NULL, ic, FALSE);
10653 /* now assign DPTR to result */
10655 aopOp(result, ic, FALSE, FALSE);
10657 aopPut(AOP(result), "a", 0);
10658 freeAsmop(result, NULL, ic, FALSE);
10662 /* See if we've got an underlying symbol to abuse. */
10663 if (IS_SYMOP(result) && OP_SYMBOL(result))
10665 if (IS_TRUE_SYMOP(result))
10667 rSym = OP_SYMBOL(result);
10669 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10671 rSym = OP_SYMBOL(result)->usl.spillLoc;
10675 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10677 /* We can use the '390 auto-toggle feature to good effect here. */
10679 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10680 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10681 emitcode ("mov", "dptr,#%s", rSym->rname);
10682 /* DP2 = result, DP1 = right, DP1 is current. */
10685 emitcode("movx", "a,@dptr");
10686 emitcode("movx", "@dptr,a");
10689 emitcode("inc", "dptr");
10690 emitcode("inc", "dptr");
10693 emitcode("mov", "dps,#0");
10694 freeAsmop (right, NULL, ic, FALSE);
10696 some alternative code for processors without auto-toggle
10697 no time to test now, so later well put in...kpb
10698 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10699 emitcode("mov", "dps,#1"); /* Select DPTR2. */
10700 emitcode ("mov", "dptr,#%s", rSym->rname);
10701 /* DP2 = result, DP1 = right, DP1 is current. */
10705 emitcode("movx", "a,@dptr");
10707 emitcode("inc", "dptr");
10708 emitcode("inc", "dps");
10709 emitcode("movx", "@dptr,a");
10711 emitcode("inc", "dptr");
10712 emitcode("inc", "dps");
10714 emitcode("mov", "dps,#0");
10715 freeAsmop (right, NULL, ic, FALSE);
10720 D (emitcode (";", "genFarFarAssign"););
10721 aopOp (result, ic, TRUE, TRUE);
10723 _startLazyDPSEvaluation ();
10727 aopPut (AOP (result),
10728 aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10731 _endLazyDPSEvaluation ();
10732 freeAsmop (result, NULL, ic, FALSE);
10733 freeAsmop (right, NULL, ic, FALSE);
10737 /*-----------------------------------------------------------------*/
10738 /* genAssign - generate code for assignment */
10739 /*-----------------------------------------------------------------*/
10741 genAssign (iCode * ic)
10743 operand *result, *right;
10745 unsigned long lit = 0L;
10747 D (emitcode (";", "genAssign ");
10750 result = IC_RESULT (ic);
10751 right = IC_RIGHT (ic);
10753 /* if they are the same */
10754 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10757 aopOp (right, ic, FALSE, FALSE);
10759 emitcode (";", "genAssign: resultIsFar = %s",
10760 isOperandInFarSpace (result) ?
10763 /* special case both in far space */
10764 if ((AOP_TYPE (right) == AOP_DPTR ||
10765 AOP_TYPE (right) == AOP_DPTR2) &&
10766 /* IS_TRUE_SYMOP(result) && */
10767 isOperandInFarSpace (result))
10769 genFarFarAssign (result, right, ic);
10773 aopOp (result, ic, TRUE, FALSE);
10775 /* if they are the same registers */
10776 if (sameRegs (AOP (right), AOP (result)))
10779 /* if the result is a bit */
10780 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10782 /* if the right size is a literal then
10783 we know what the value is */
10784 if (AOP_TYPE (right) == AOP_LIT)
10786 if (((int) operandLitValue (right)))
10787 aopPut (AOP (result), one, 0);
10789 aopPut (AOP (result), zero, 0);
10793 /* the right is also a bit variable */
10794 if (AOP_TYPE (right) == AOP_CRY)
10796 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10797 aopPut (AOP (result), "c", 0);
10801 /* we need to or */
10803 aopPut (AOP (result), "a", 0);
10807 /* bit variables done */
10809 size = AOP_SIZE (result);
10811 if (AOP_TYPE (right) == AOP_LIT)
10812 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10815 (AOP_TYPE (result) != AOP_REG) &&
10816 (AOP_TYPE (right) == AOP_LIT) &&
10817 !IS_FLOAT (operandType (right)))
10819 _startLazyDPSEvaluation ();
10820 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10822 aopPut (AOP (result),
10823 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10828 /* And now fill the rest with zeros. */
10831 emitcode ("clr", "a");
10835 aopPut (AOP (result), "a", offset++);
10837 _endLazyDPSEvaluation ();
10841 _startLazyDPSEvaluation ();
10844 aopPut (AOP (result),
10845 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10849 _endLazyDPSEvaluation ();
10853 freeAsmop (right, NULL, ic, FALSE);
10854 freeAsmop (result, NULL, ic, TRUE);
10857 /*-----------------------------------------------------------------*/
10858 /* genJumpTab - generates code for jump table */
10859 /*-----------------------------------------------------------------*/
10861 genJumpTab (iCode * ic)
10866 D (emitcode (";", "genJumpTab ");
10869 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10870 /* get the condition into accumulator */
10871 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
10873 /* multiply by four! */
10874 emitcode ("add", "a,acc");
10875 emitcode ("add", "a,acc");
10876 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10878 jtab = newiTempLabel (NULL);
10879 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10880 emitcode ("jmp", "@a+dptr");
10881 emitcode ("", "!tlabeldef", jtab->key + 100);
10882 /* now generate the jump labels */
10883 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10884 jtab = setNextItem (IC_JTLABELS (ic)))
10885 emitcode ("ljmp", "!tlabel", jtab->key + 100);
10889 /*-----------------------------------------------------------------*/
10890 /* genCast - gen code for casting */
10891 /*-----------------------------------------------------------------*/
10893 genCast (iCode * ic)
10895 operand *result = IC_RESULT (ic);
10896 sym_link *ctype = operandType (IC_LEFT (ic));
10897 sym_link *rtype = operandType (IC_RIGHT (ic));
10898 operand *right = IC_RIGHT (ic);
10901 D (emitcode (";", "genCast "););
10903 /* if they are equivalent then do nothing */
10904 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10907 aopOp (right, ic, FALSE, FALSE);
10908 aopOp (result, ic, FALSE, AOP_USESDPTR(right));
10910 /* if the result is a bit */
10911 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10912 if (IS_BITVAR(OP_SYMBOL(result)->type))
10914 /* if the right size is a literal then
10915 we know what the value is */
10916 if (AOP_TYPE (right) == AOP_LIT)
10918 if (((int) operandLitValue (right)))
10919 aopPut (AOP (result), one, 0);
10921 aopPut (AOP (result), zero, 0);
10926 /* the right is also a bit variable */
10927 if (AOP_TYPE (right) == AOP_CRY)
10929 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10930 aopPut (AOP (result), "c", 0);
10934 /* we need to or */
10936 aopPut (AOP (result), "a", 0);
10940 /* if they are the same size : or less */
10941 if (AOP_SIZE (result) <= AOP_SIZE (right))
10944 /* if they are in the same place */
10945 if (sameRegs (AOP (right), AOP (result)))
10948 /* if they in different places then copy */
10949 size = AOP_SIZE (result);
10951 _startLazyDPSEvaluation ();
10954 aopPut (AOP (result),
10955 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10959 _endLazyDPSEvaluation ();
10964 /* if the result is of type pointer */
10965 if (IS_PTR (ctype))
10969 sym_link *type = operandType (right);
10971 /* pointer to generic pointer */
10972 if (IS_GENPTR (ctype))
10976 p_type = DCL_TYPE (type);
10980 #if OLD_CAST_BEHAVIOR
10981 /* KV: we are converting a non-pointer type to
10982 * a generic pointer. This (ifdef'd out) code
10983 * says that the resulting generic pointer
10984 * should have the same class as the storage
10985 * location of the non-pointer variable.
10987 * For example, converting an int (which happens
10988 * to be stored in DATA space) to a pointer results
10989 * in a DATA generic pointer; if the original int
10990 * in XDATA space, so will be the resulting pointer.
10992 * I don't like that behavior, and thus this change:
10993 * all such conversions will be forced to XDATA and
10994 * throw a warning. If you want some non-XDATA
10995 * type, or you want to suppress the warning, you
10996 * must go through an intermediate cast, like so:
10998 * char _generic *gp = (char _xdata *)(intVar);
11000 sym_link *etype = getSpec (type);
11002 /* we have to go by the storage class */
11003 if (SPEC_OCLS (etype) != generic)
11005 p_type = PTR_TYPE (SPEC_OCLS (etype));
11010 /* Converting unknown class (i.e. register variable)
11011 * to generic pointer. This is not good, but
11012 * we'll make a guess (and throw a warning).
11015 werror (W_INT_TO_GEN_PTR_CAST);
11019 /* the first two bytes are known */
11020 size = GPTRSIZE - 1;
11022 _startLazyDPSEvaluation ();
11025 aopPut (AOP (result),
11026 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11030 _endLazyDPSEvaluation ();
11032 /* the last byte depending on type */
11034 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11039 // pointerTypeToGPByte will have bitched.
11043 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11044 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11049 /* just copy the pointers */
11050 size = AOP_SIZE (result);
11052 _startLazyDPSEvaluation ();
11055 aopPut (AOP (result),
11056 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11060 _endLazyDPSEvaluation ();
11064 /* so we now know that the size of destination is greater
11065 than the size of the source */
11066 /* we move to result for the size of source */
11067 size = AOP_SIZE (right);
11069 _startLazyDPSEvaluation ();
11072 aopPut (AOP (result),
11073 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11077 _endLazyDPSEvaluation ();
11079 /* now depending on the sign of the source && destination */
11080 size = AOP_SIZE (result) - AOP_SIZE (right);
11081 /* if unsigned or not an integral type */
11082 /* also, if the source is a bit, we don't need to sign extend, because
11083 * it can't possibly have set the sign bit.
11085 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
11089 aopPut (AOP (result), zero, offset++);
11094 /* we need to extend the sign :{ */
11095 MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11096 FALSE, FALSE, NULL));
11097 emitcode ("rlc", "a");
11098 emitcode ("subb", "a,acc");
11100 aopPut (AOP (result), "a", offset++);
11103 /* we are done hurray !!!! */
11106 freeAsmop (right, NULL, ic, TRUE);
11107 freeAsmop (result, NULL, ic, TRUE);
11111 /*-----------------------------------------------------------------*/
11112 /* genDjnz - generate decrement & jump if not zero instrucion */
11113 /*-----------------------------------------------------------------*/
11115 genDjnz (iCode * ic, iCode * ifx)
11117 symbol *lbl, *lbl1;
11121 /* if the if condition has a false label
11122 then we cannot save */
11123 if (IC_FALSE (ifx))
11126 /* if the minus is not of the form
11128 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11129 !IS_OP_LITERAL (IC_RIGHT (ic)))
11132 if (operandLitValue (IC_RIGHT (ic)) != 1)
11135 /* if the size of this greater than one then no
11137 if (getSize (operandType (IC_RESULT (ic))) > 1)
11140 /* otherwise we can save BIG */
11141 D(emitcode(";", "genDjnz"););
11143 lbl = newiTempLabel (NULL);
11144 lbl1 = newiTempLabel (NULL);
11146 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11148 if (AOP_NEEDSACC(IC_RESULT(ic)))
11150 /* If the result is accessed indirectly via
11151 * the accumulator, we must explicitly write
11152 * it back after the decrement.
11154 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11156 if (strcmp(rByte, "a"))
11158 /* Something is hopelessly wrong */
11159 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11160 __FILE__, __LINE__);
11161 /* We can just give up; the generated code will be inefficient,
11162 * but what the hey.
11164 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11167 emitcode ("dec", "%s", rByte);
11168 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11169 emitcode ("jnz", "!tlabel", lbl->key + 100);
11171 else if (IS_AOP_PREG (IC_RESULT (ic)))
11173 emitcode ("dec", "%s",
11174 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11175 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11176 emitcode ("jnz", "!tlabel", lbl->key + 100);
11180 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11183 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11184 emitcode ("", "!tlabeldef", lbl->key + 100);
11185 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11186 emitcode ("", "!tlabeldef", lbl1->key + 100);
11188 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11189 ifx->generated = 1;
11193 /*-----------------------------------------------------------------*/
11194 /* genReceive - generate code for a receive iCode */
11195 /*-----------------------------------------------------------------*/
11197 genReceive (iCode * ic)
11200 int size = getSize (operandType (IC_RESULT (ic)));
11204 D (emitcode (";", "genReceive ");
11207 if (ic->argreg == 1) { /* first parameter */
11208 if (isOperandInFarSpace (IC_RESULT (ic)) &&
11209 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11210 IS_TRUE_SYMOP (IC_RESULT (ic))))
11212 offset = fReturnSizeDS390 - size;
11215 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
11216 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
11219 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11220 size = AOP_SIZE (IC_RESULT (ic));
11224 emitcode ("pop", "acc");
11225 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
11230 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11232 assignResultValue (IC_RESULT (ic));
11234 } else { /* second receive onwards */
11235 /* this gets a little tricky since unused recevies will be
11236 eliminated, we have saved the reg in the type field . and
11237 we use that to figure out which register to use */
11238 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11239 rb1off = ic->argreg;
11241 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11245 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11248 /*-----------------------------------------------------------------*/
11249 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11250 /*-----------------------------------------------------------------*/
11251 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11253 operand *from , *to , *count;
11258 /* we know it has to be 3 parameters */
11259 assert (nparms == 3);
11261 rsave = newBitVect(16);
11262 /* save DPTR if it needs to be saved */
11263 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11264 if (bitVectBitValue(ic->rMask,i))
11265 rsave = bitVectSetBit(rsave,i);
11267 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11268 ds390_rUmaskForOp (IC_RESULT(ic))));
11275 aopOp (from, ic->next, FALSE, FALSE);
11277 /* get from into DPTR1 */
11278 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11279 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11280 if (options.model == MODEL_FLAT24) {
11281 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11284 freeAsmop (from, NULL, ic, FALSE);
11285 aopOp (to, ic, FALSE, FALSE);
11286 /* get "to" into DPTR */
11287 /* if the operand is already in dptr
11288 then we do nothing else we move the value to dptr */
11289 if (AOP_TYPE (to) != AOP_STR) {
11290 /* if already in DPTR then we need to push */
11291 if (AOP_TYPE(to) == AOP_DPTR) {
11292 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11293 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11294 if (options.model == MODEL_FLAT24)
11295 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11296 emitcode ("pop", "dph");
11297 emitcode ("pop", "dpl");
11299 _startLazyDPSEvaluation ();
11300 /* if this is remateriazable */
11301 if (AOP_TYPE (to) == AOP_IMMD) {
11302 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11303 } else { /* we need to get it byte by byte */
11304 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11305 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11306 if (options.model == MODEL_FLAT24) {
11307 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11310 _endLazyDPSEvaluation ();
11313 freeAsmop (to, NULL, ic, FALSE);
11314 _G.dptrInUse = _G.dptr1InUse = 1;
11315 aopOp (count, ic->next->next, FALSE,FALSE);
11316 lbl =newiTempLabel(NULL);
11318 /* now for the actual copy */
11319 if (AOP_TYPE(count) == AOP_LIT &&
11320 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11321 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11323 emitcode ("lcall","__bi_memcpyc2x_s");
11325 emitcode ("lcall","__bi_memcpyx2x_s");
11327 freeAsmop (count, NULL, ic, FALSE);
11329 symbol *lbl1 = newiTempLabel(NULL);
11331 emitcode (";"," Auto increment but no djnz");
11332 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11333 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11334 freeAsmop (count, NULL, ic, FALSE);
11335 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11336 emitcode ("","!tlabeldef",lbl->key+100);
11338 emitcode ("clr","a");
11339 emitcode ("movc", "a,@a+dptr");
11341 emitcode ("movx", "a,@dptr");
11342 emitcode ("movx", "@dptr,a");
11343 emitcode ("inc", "dptr");
11344 emitcode ("inc", "dptr");
11345 emitcode ("mov","a,b");
11346 emitcode ("orl","a,_ap");
11347 emitcode ("jz","!tlabel",lbl1->key+100);
11348 emitcode ("mov","a,_ap");
11349 emitcode ("add","a,#!constbyte",0xFF);
11350 emitcode ("mov","_ap,a");
11351 emitcode ("mov","a,b");
11352 emitcode ("addc","a,#!constbyte",0xFF);
11353 emitcode ("mov","b,a");
11354 emitcode ("sjmp","!tlabel",lbl->key+100);
11355 emitcode ("","!tlabeldef",lbl1->key+100);
11357 emitcode ("mov", "dps,#0");
11358 _G.dptrInUse = _G.dptr1InUse = 0;
11359 unsavermask(rsave);
11363 /*-----------------------------------------------------------------*/
11364 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
11365 /*-----------------------------------------------------------------*/
11366 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11368 operand *from , *to , *count;
11373 /* we know it has to be 3 parameters */
11374 assert (nparms == 3);
11376 rsave = newBitVect(16);
11377 /* save DPTR if it needs to be saved */
11378 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11379 if (bitVectBitValue(ic->rMask,i))
11380 rsave = bitVectSetBit(rsave,i);
11382 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11383 ds390_rUmaskForOp (IC_RESULT(ic))));
11390 aopOp (from, ic->next, FALSE, FALSE);
11392 /* get from into DPTR1 */
11393 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11394 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11395 if (options.model == MODEL_FLAT24) {
11396 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11399 freeAsmop (from, NULL, ic, FALSE);
11400 aopOp (to, ic, FALSE, FALSE);
11401 /* get "to" into DPTR */
11402 /* if the operand is already in dptr
11403 then we do nothing else we move the value to dptr */
11404 if (AOP_TYPE (to) != AOP_STR) {
11405 /* if already in DPTR then we need to push */
11406 if (AOP_TYPE(to) == AOP_DPTR) {
11407 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11408 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11409 if (options.model == MODEL_FLAT24)
11410 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11411 emitcode ("pop", "dph");
11412 emitcode ("pop", "dpl");
11414 _startLazyDPSEvaluation ();
11415 /* if this is remateriazable */
11416 if (AOP_TYPE (to) == AOP_IMMD) {
11417 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11418 } else { /* we need to get it byte by byte */
11419 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11420 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11421 if (options.model == MODEL_FLAT24) {
11422 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11425 _endLazyDPSEvaluation ();
11428 freeAsmop (to, NULL, ic, FALSE);
11429 _G.dptrInUse = _G.dptr1InUse = 1;
11430 aopOp (count, ic->next->next, FALSE,FALSE);
11431 lbl =newiTempLabel(NULL);
11432 lbl2 =newiTempLabel(NULL);
11434 /* now for the actual compare */
11435 if (AOP_TYPE(count) == AOP_LIT &&
11436 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11437 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11439 emitcode("lcall","__bi_memcmpc2x_s");
11441 emitcode("lcall","__bi_memcmpx2x_s");
11442 freeAsmop (count, NULL, ic, FALSE);
11443 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11444 aopPut(AOP(IC_RESULT(ic)),"a",0);
11445 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11447 symbol *lbl1 = newiTempLabel(NULL);
11449 emitcode("push","ar0");
11450 emitcode (";"," Auto increment but no djnz");
11451 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11452 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11453 freeAsmop (count, NULL, ic, FALSE);
11454 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11455 emitcode ("","!tlabeldef",lbl->key+100);
11457 emitcode ("clr","a");
11458 emitcode ("movc", "a,@a+dptr");
11460 emitcode ("movx", "a,@dptr");
11461 emitcode ("mov","r0,a");
11462 emitcode ("movx", "a,@dptr");
11463 emitcode ("clr","c");
11464 emitcode ("subb","a,r0");
11465 emitcode ("jnz","!tlabel",lbl2->key+100);
11466 emitcode ("inc", "dptr");
11467 emitcode ("inc", "dptr");
11468 emitcode ("mov","a,b");
11469 emitcode ("orl","a,_ap");
11470 emitcode ("jz","!tlabel",lbl1->key+100);
11471 emitcode ("mov","a,_ap");
11472 emitcode ("add","a,#!constbyte",0xFF);
11473 emitcode ("mov","_ap,a");
11474 emitcode ("mov","a,b");
11475 emitcode ("addc","a,#!constbyte",0xFF);
11476 emitcode ("mov","b,a");
11477 emitcode ("sjmp","!tlabel",lbl->key+100);
11478 emitcode ("","!tlabeldef",lbl1->key+100);
11479 emitcode ("clr","a");
11480 emitcode ("","!tlabeldef",lbl2->key+100);
11481 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11482 aopPut(AOP(IC_RESULT(ic)),"a",0);
11483 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11484 emitcode("pop","ar0");
11485 emitcode ("mov", "dps,#0");
11487 _G.dptrInUse = _G.dptr1InUse = 0;
11488 unsavermask(rsave);
11492 /*-----------------------------------------------------------------*/
11493 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11494 /* port, first parameter output area second parameter pointer to */
11495 /* port third parameter count */
11496 /*-----------------------------------------------------------------*/
11497 static void genInp( iCode *ic, int nparms, operand **parms)
11499 operand *from , *to , *count;
11504 /* we know it has to be 3 parameters */
11505 assert (nparms == 3);
11507 rsave = newBitVect(16);
11508 /* save DPTR if it needs to be saved */
11509 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11510 if (bitVectBitValue(ic->rMask,i))
11511 rsave = bitVectSetBit(rsave,i);
11513 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11514 ds390_rUmaskForOp (IC_RESULT(ic))));
11521 aopOp (from, ic->next, FALSE, FALSE);
11523 /* get from into DPTR1 */
11524 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11525 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11526 if (options.model == MODEL_FLAT24) {
11527 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11530 freeAsmop (from, NULL, ic, FALSE);
11531 aopOp (to, ic, FALSE, FALSE);
11532 /* get "to" into DPTR */
11533 /* if the operand is already in dptr
11534 then we do nothing else we move the value to dptr */
11535 if (AOP_TYPE (to) != AOP_STR) {
11536 /* if already in DPTR then we need to push */
11537 if (AOP_TYPE(to) == AOP_DPTR) {
11538 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11539 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11540 if (options.model == MODEL_FLAT24)
11541 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11542 emitcode ("pop", "dph");
11543 emitcode ("pop", "dpl");
11545 _startLazyDPSEvaluation ();
11546 /* if this is remateriazable */
11547 if (AOP_TYPE (to) == AOP_IMMD) {
11548 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11549 } else { /* we need to get it byte by byte */
11550 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11551 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11552 if (options.model == MODEL_FLAT24) {
11553 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11556 _endLazyDPSEvaluation ();
11559 freeAsmop (to, NULL, ic, FALSE);
11561 _G.dptrInUse = _G.dptr1InUse = 1;
11562 aopOp (count, ic->next->next, FALSE,FALSE);
11563 lbl =newiTempLabel(NULL);
11565 /* now for the actual copy */
11566 if (AOP_TYPE(count) == AOP_LIT &&
11567 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11568 emitcode (";","OH JOY auto increment with djnz (very fast)");
11569 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11570 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11571 freeAsmop (count, NULL, ic, FALSE);
11572 emitcode ("","!tlabeldef",lbl->key+100);
11573 emitcode ("movx", "a,@dptr"); /* read data from port */
11574 emitcode ("dec","dps"); /* switch to DPTR */
11575 emitcode ("movx", "@dptr,a"); /* save into location */
11576 emitcode ("inc", "dptr"); /* point to next area */
11577 emitcode ("inc","dps"); /* switch to DPTR2 */
11578 emitcode ("djnz","b,!tlabel",lbl->key+100);
11580 symbol *lbl1 = newiTempLabel(NULL);
11582 emitcode (";"," Auto increment but no djnz");
11583 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11584 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11585 freeAsmop (count, NULL, ic, FALSE);
11586 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11587 emitcode ("","!tlabeldef",lbl->key+100);
11588 emitcode ("movx", "a,@dptr");
11589 emitcode ("dec","dps"); /* switch to DPTR */
11590 emitcode ("movx", "@dptr,a");
11591 emitcode ("inc", "dptr");
11592 emitcode ("inc","dps"); /* switch to DPTR2 */
11593 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
11594 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11595 emitcode ("mov","a,b");
11596 emitcode ("orl","a,_ap");
11597 emitcode ("jz","!tlabel",lbl1->key+100);
11598 emitcode ("mov","a,_ap");
11599 emitcode ("add","a,#!constbyte",0xFF);
11600 emitcode ("mov","_ap,a");
11601 emitcode ("mov","a,b");
11602 emitcode ("addc","a,#!constbyte",0xFF);
11603 emitcode ("mov","b,a");
11604 emitcode ("sjmp","!tlabel",lbl->key+100);
11605 emitcode ("","!tlabeldef",lbl1->key+100);
11607 emitcode ("mov", "dps,#0");
11608 _G.dptrInUse = _G.dptr1InUse = 0;
11609 unsavermask(rsave);
11613 /*-----------------------------------------------------------------*/
11614 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11615 /* port, first parameter output area second parameter pointer to */
11616 /* port third parameter count */
11617 /*-----------------------------------------------------------------*/
11618 static void genOutp( iCode *ic, int nparms, operand **parms)
11620 operand *from , *to , *count;
11625 /* we know it has to be 3 parameters */
11626 assert (nparms == 3);
11628 rsave = newBitVect(16);
11629 /* save DPTR if it needs to be saved */
11630 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11631 if (bitVectBitValue(ic->rMask,i))
11632 rsave = bitVectSetBit(rsave,i);
11634 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11635 ds390_rUmaskForOp (IC_RESULT(ic))));
11642 aopOp (from, ic->next, FALSE, FALSE);
11644 /* get from into DPTR1 */
11645 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11646 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11647 if (options.model == MODEL_FLAT24) {
11648 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11651 freeAsmop (from, NULL, ic, FALSE);
11652 aopOp (to, ic, FALSE, FALSE);
11653 /* get "to" into DPTR */
11654 /* if the operand is already in dptr
11655 then we do nothing else we move the value to dptr */
11656 if (AOP_TYPE (to) != AOP_STR) {
11657 /* if already in DPTR then we need to push */
11658 if (AOP_TYPE(to) == AOP_DPTR) {
11659 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11660 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11661 if (options.model == MODEL_FLAT24)
11662 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11663 emitcode ("pop", "dph");
11664 emitcode ("pop", "dpl");
11666 _startLazyDPSEvaluation ();
11667 /* if this is remateriazable */
11668 if (AOP_TYPE (to) == AOP_IMMD) {
11669 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11670 } else { /* we need to get it byte by byte */
11671 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11672 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11673 if (options.model == MODEL_FLAT24) {
11674 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11677 _endLazyDPSEvaluation ();
11680 freeAsmop (to, NULL, ic, FALSE);
11682 _G.dptrInUse = _G.dptr1InUse = 1;
11683 aopOp (count, ic->next->next, FALSE,FALSE);
11684 lbl =newiTempLabel(NULL);
11686 /* now for the actual copy */
11687 if (AOP_TYPE(count) == AOP_LIT &&
11688 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11689 emitcode (";","OH JOY auto increment with djnz (very fast)");
11690 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11691 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11692 emitcode ("","!tlabeldef",lbl->key+100);
11693 emitcode ("movx", "a,@dptr"); /* read data from port */
11694 emitcode ("inc","dps"); /* switch to DPTR2 */
11695 emitcode ("movx", "@dptr,a"); /* save into location */
11696 emitcode ("inc", "dptr"); /* point to next area */
11697 emitcode ("dec","dps"); /* switch to DPTR */
11698 emitcode ("djnz","b,!tlabel",lbl->key+100);
11699 freeAsmop (count, NULL, ic, FALSE);
11701 symbol *lbl1 = newiTempLabel(NULL);
11703 emitcode (";"," Auto increment but no djnz");
11704 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11705 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11706 freeAsmop (count, NULL, ic, FALSE);
11707 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11708 emitcode ("","!tlabeldef",lbl->key+100);
11709 emitcode ("movx", "a,@dptr");
11710 emitcode ("inc", "dptr");
11711 emitcode ("inc","dps"); /* switch to DPTR2 */
11712 emitcode ("movx", "@dptr,a");
11713 emitcode ("dec","dps"); /* switch to DPTR */
11714 emitcode ("mov","a,b");
11715 emitcode ("orl","a,_ap");
11716 emitcode ("jz","!tlabel",lbl1->key+100);
11717 emitcode ("mov","a,_ap");
11718 emitcode ("add","a,#!constbyte",0xFF);
11719 emitcode ("mov","_ap,a");
11720 emitcode ("mov","a,b");
11721 emitcode ("addc","a,#!constbyte",0xFF);
11722 emitcode ("mov","b,a");
11723 emitcode ("sjmp","!tlabel",lbl->key+100);
11724 emitcode ("","!tlabeldef",lbl1->key+100);
11726 emitcode ("mov", "dps,#0");
11727 _G.dptrInUse = _G.dptr1InUse = 0;
11728 unsavermask(rsave);
11732 /*-----------------------------------------------------------------*/
11733 /* genSwapW - swap lower & high order bytes */
11734 /*-----------------------------------------------------------------*/
11735 static void genSwapW(iCode *ic, int nparms, operand **parms)
11739 assert (nparms==1);
11742 dest=IC_RESULT(ic);
11744 assert(getSize(operandType(src))==2);
11746 aopOp (src, ic, FALSE, FALSE);
11747 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11749 MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11751 freeAsmop (src, NULL, ic, FALSE);
11753 aopOp (dest,ic, FALSE, FALSE);
11754 aopPut(AOP(dest),"b",0);
11755 aopPut(AOP(dest),"a",1);
11756 freeAsmop (dest, NULL, ic, FALSE);
11759 /*-----------------------------------------------------------------*/
11760 /* genMemsetX - gencode for memSetX data */
11761 /*-----------------------------------------------------------------*/
11762 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11764 operand *to , *val , *count;
11770 /* we know it has to be 3 parameters */
11771 assert (nparms == 3);
11777 /* save DPTR if it needs to be saved */
11778 rsave = newBitVect(16);
11779 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11780 if (bitVectBitValue(ic->rMask,i))
11781 rsave = bitVectSetBit(rsave,i);
11783 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11784 ds390_rUmaskForOp (IC_RESULT(ic))));
11787 aopOp (to, ic, FALSE, FALSE);
11788 /* get "to" into DPTR */
11789 /* if the operand is already in dptr
11790 then we do nothing else we move the value to dptr */
11791 if (AOP_TYPE (to) != AOP_STR) {
11792 /* if already in DPTR then we need to push */
11793 if (AOP_TYPE(to) == AOP_DPTR) {
11794 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11795 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11796 if (options.model == MODEL_FLAT24)
11797 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11798 emitcode ("pop", "dph");
11799 emitcode ("pop", "dpl");
11801 _startLazyDPSEvaluation ();
11802 /* if this is remateriazable */
11803 if (AOP_TYPE (to) == AOP_IMMD) {
11804 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11805 } else { /* we need to get it byte by byte */
11806 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11807 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11808 if (options.model == MODEL_FLAT24) {
11809 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11812 _endLazyDPSEvaluation ();
11815 freeAsmop (to, NULL, ic, FALSE);
11817 aopOp (val, ic->next->next, FALSE,FALSE);
11818 aopOp (count, ic->next->next, FALSE,FALSE);
11819 lbl =newiTempLabel(NULL);
11820 /* now for the actual copy */
11821 if (AOP_TYPE(count) == AOP_LIT &&
11822 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11823 l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
11824 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11826 emitcode ("","!tlabeldef",lbl->key+100);
11827 emitcode ("movx", "@dptr,a");
11828 emitcode ("inc", "dptr");
11829 emitcode ("djnz","b,!tlabel",lbl->key+100);
11831 symbol *lbl1 = newiTempLabel(NULL);
11833 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11834 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11835 emitcode ("","!tlabeldef",lbl->key+100);
11836 MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
11837 emitcode ("movx", "@dptr,a");
11838 emitcode ("inc", "dptr");
11839 emitcode ("mov","a,b");
11840 emitcode ("orl","a,_ap");
11841 emitcode ("jz","!tlabel",lbl1->key+100);
11842 emitcode ("mov","a,_ap");
11843 emitcode ("add","a,#!constbyte",0xFF);
11844 emitcode ("mov","_ap,a");
11845 emitcode ("mov","a,b");
11846 emitcode ("addc","a,#!constbyte",0xFF);
11847 emitcode ("mov","b,a");
11848 emitcode ("sjmp","!tlabel",lbl->key+100);
11849 emitcode ("","!tlabeldef",lbl1->key+100);
11851 freeAsmop (count, NULL, ic, FALSE);
11852 unsavermask(rsave);
11855 /*-----------------------------------------------------------------*/
11856 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11857 /*-----------------------------------------------------------------*/
11858 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11861 operand *pnum, *result;
11864 assert (nparms==1);
11865 /* save registers that need to be saved */
11866 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11867 ds390_rUmaskForOp (IC_RESULT(ic))));
11870 aopOp (pnum, ic, FALSE, FALSE);
11871 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11872 freeAsmop (pnum, NULL, ic, FALSE);
11873 emitcode ("lcall","NatLib_LoadPrimitive");
11874 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11875 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
11876 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11877 for (i = (size-1) ; i >= 0 ; i-- ) {
11878 emitcode ("push","a%s",javaRet[i]);
11880 for (i=0; i < size ; i++ ) {
11881 emitcode ("pop","a%s",
11882 aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
11885 for (i = 0 ; i < size ; i++ ) {
11886 aopPut(AOP(result),javaRet[i],i);
11889 freeAsmop (result, NULL, ic, FALSE);
11890 unsavermask(rsave);
11893 /*-----------------------------------------------------------------*/
11894 /* genNatLibLoadPointer - calls TINI api function to load pointer */
11895 /*-----------------------------------------------------------------*/
11896 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11899 operand *pnum, *result;
11903 assert (nparms==1);
11904 /* save registers that need to be saved */
11905 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11906 ds390_rUmaskForOp (IC_RESULT(ic))));
11909 aopOp (pnum, ic, FALSE, FALSE);
11910 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11911 freeAsmop (pnum, NULL, ic, FALSE);
11912 emitcode ("lcall","NatLib_LoadPointer");
11913 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11914 if (AOP_TYPE(result)!=AOP_STR) {
11915 for (i = 0 ; i < size ; i++ ) {
11916 aopPut(AOP(result),fReturn[i],i);
11919 freeAsmop (result, NULL, ic, FALSE);
11920 unsavermask(rsave);
11923 /*-----------------------------------------------------------------*/
11924 /* genNatLibInstallStateBlock - */
11925 /*-----------------------------------------------------------------*/
11926 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
11927 operand **parms, const char *name)
11930 operand *psb, *handle;
11931 assert (nparms==2);
11933 /* save registers that need to be saved */
11934 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11935 ds390_rUmaskForOp (IC_RESULT(ic))));
11939 /* put pointer to state block into DPTR1 */
11940 aopOp (psb, ic, FALSE, FALSE);
11941 if (AOP_TYPE (psb) == AOP_IMMD) {
11942 emitcode ("mov","dps,#1");
11943 emitcode ("mov", "dptr,%s",
11944 aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
11945 emitcode ("mov","dps,#0");
11947 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
11948 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
11949 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
11951 freeAsmop (psb, NULL, ic, FALSE);
11953 /* put libraryID into DPTR */
11954 emitcode ("mov","dptr,#LibraryID");
11956 /* put handle into r3:r2 */
11957 aopOp (handle, ic, FALSE, FALSE);
11958 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11959 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
11960 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
11961 emitcode ("pop","ar3");
11962 emitcode ("pop","ar2");
11964 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
11965 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
11967 freeAsmop (psb, NULL, ic, FALSE);
11969 /* make the call */
11970 emitcode ("lcall","NatLib_Install%sStateBlock",name);
11972 /* put return value into place*/
11974 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
11976 aopPut(AOP(IC_RESULT(ic)),"a",0);
11977 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11978 unsavermask(rsave);
11981 /*-----------------------------------------------------------------*/
11982 /* genNatLibRemoveStateBlock - */
11983 /*-----------------------------------------------------------------*/
11984 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
11990 /* save registers that need to be saved */
11991 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11992 ds390_rUmaskForOp (IC_RESULT(ic))));
11994 /* put libraryID into DPTR */
11995 emitcode ("mov","dptr,#LibraryID");
11996 /* make the call */
11997 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11998 unsavermask(rsave);
12001 /*-----------------------------------------------------------------*/
12002 /* genNatLibGetStateBlock - */
12003 /*-----------------------------------------------------------------*/
12004 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12005 operand **parms,const char *name)
12008 symbol *lbl = newiTempLabel(NULL);
12011 /* save registers that need to be saved */
12012 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12013 ds390_rUmaskForOp (IC_RESULT(ic))));
12015 /* put libraryID into DPTR */
12016 emitcode ("mov","dptr,#LibraryID");
12017 /* make the call */
12018 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12019 emitcode ("jnz","!tlabel",lbl->key+100);
12021 /* put return value into place */
12022 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12023 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12024 emitcode ("push","ar3");
12025 emitcode ("push","ar2");
12026 emitcode ("pop","%s",
12027 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12028 emitcode ("pop","%s",
12029 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12031 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12032 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12034 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12035 emitcode ("","!tlabeldef",lbl->key+100);
12036 unsavermask(rsave);
12039 /*-----------------------------------------------------------------*/
12040 /* genMMMalloc - */
12041 /*-----------------------------------------------------------------*/
12042 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12043 int size, const char *name)
12048 symbol *lbl = newiTempLabel(NULL);
12050 assert (nparms == 1);
12051 /* save registers that need to be saved */
12052 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12053 ds390_rUmaskForOp (IC_RESULT(ic))));
12056 aopOp (bsize,ic,FALSE,FALSE);
12058 /* put the size in R4-R2 */
12059 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12060 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12061 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12063 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12064 emitcode("pop","ar4");
12066 emitcode("pop","ar3");
12067 emitcode("pop","ar2");
12069 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12070 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12072 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12075 freeAsmop (bsize, NULL, ic, FALSE);
12077 /* make the call */
12078 emitcode ("lcall","MM_%s",name);
12079 emitcode ("jz","!tlabel",lbl->key+100);
12080 emitcode ("mov","r2,#!constbyte",0xff);
12081 emitcode ("mov","r3,#!constbyte",0xff);
12082 emitcode ("","!tlabeldef",lbl->key+100);
12083 /* we don't care about the pointer : we just save the handle */
12084 rsym = OP_SYMBOL(IC_RESULT(ic));
12085 if (rsym->liveFrom != rsym->liveTo) {
12086 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12087 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12088 emitcode ("push","ar3");
12089 emitcode ("push","ar2");
12090 emitcode ("pop","%s",
12091 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12092 emitcode ("pop","%s",
12093 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12095 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12096 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12098 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12100 unsavermask(rsave);
12103 /*-----------------------------------------------------------------*/
12105 /*-----------------------------------------------------------------*/
12106 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12111 assert (nparms == 1);
12112 /* save registers that need to be saved */
12113 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12114 ds390_rUmaskForOp (IC_RESULT(ic))));
12117 aopOp (handle,ic,FALSE,FALSE);
12119 /* put the size in R4-R2 */
12120 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12121 emitcode("push","%s",
12122 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12123 emitcode("push","%s",
12124 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12125 emitcode("pop","ar3");
12126 emitcode("pop","ar2");
12128 emitcode ("mov","r2,%s",
12129 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12130 emitcode ("mov","r3,%s",
12131 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12133 freeAsmop (handle, NULL, ic, FALSE);
12135 /* make the call */
12136 emitcode ("lcall","MM_Deref");
12139 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12140 if (rsym->liveFrom != rsym->liveTo) {
12141 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12142 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12143 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12144 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12145 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12149 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12150 unsavermask(rsave);
12153 /*-----------------------------------------------------------------*/
12154 /* genMMUnrestrictedPersist - */
12155 /*-----------------------------------------------------------------*/
12156 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12161 assert (nparms == 1);
12162 /* save registers that need to be saved */
12163 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12164 ds390_rUmaskForOp (IC_RESULT(ic))));
12167 aopOp (handle,ic,FALSE,FALSE);
12169 /* put the size in R3-R2 */
12170 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12171 emitcode("push","%s",
12172 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12173 emitcode("push","%s",
12174 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12175 emitcode("pop","ar3");
12176 emitcode("pop","ar2");
12178 emitcode ("mov","r2,%s",
12179 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12180 emitcode ("mov","r3,%s",
12181 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12183 freeAsmop (handle, NULL, ic, FALSE);
12185 /* make the call */
12186 emitcode ("lcall","MM_UnrestrictedPersist");
12189 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12190 if (rsym->liveFrom != rsym->liveTo) {
12191 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12192 aopPut(AOP(IC_RESULT(ic)),"a",0);
12193 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12196 unsavermask(rsave);
12199 /*-----------------------------------------------------------------*/
12200 /* genSystemExecJavaProcess - */
12201 /*-----------------------------------------------------------------*/
12202 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12205 operand *handle, *pp;
12207 assert (nparms==2);
12208 /* save registers that need to be saved */
12209 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12210 ds390_rUmaskForOp (IC_RESULT(ic))));
12215 /* put the handle in R3-R2 */
12216 aopOp (handle,ic,FALSE,FALSE);
12217 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12218 emitcode("push","%s",
12219 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12220 emitcode("push","%s",
12221 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12222 emitcode("pop","ar3");
12223 emitcode("pop","ar2");
12225 emitcode ("mov","r2,%s",
12226 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12227 emitcode ("mov","r3,%s",
12228 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12230 freeAsmop (handle, NULL, ic, FALSE);
12232 /* put pointer in DPTR */
12233 aopOp (pp,ic,FALSE,FALSE);
12234 if (AOP_TYPE(pp) == AOP_IMMD) {
12235 emitcode ("mov", "dptr,%s",
12236 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12237 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12238 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12239 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12240 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12242 freeAsmop (handle, NULL, ic, FALSE);
12244 /* make the call */
12245 emitcode ("lcall","System_ExecJavaProcess");
12247 /* put result in place */
12249 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12250 if (rsym->liveFrom != rsym->liveTo) {
12251 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12252 aopPut(AOP(IC_RESULT(ic)),"a",0);
12253 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12257 unsavermask(rsave);
12260 /*-----------------------------------------------------------------*/
12261 /* genSystemRTCRegisters - */
12262 /*-----------------------------------------------------------------*/
12263 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12269 assert (nparms==1);
12270 /* save registers that need to be saved */
12271 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12272 ds390_rUmaskForOp (IC_RESULT(ic))));
12275 /* put pointer in DPTR */
12276 aopOp (pp,ic,FALSE,FALSE);
12277 if (AOP_TYPE (pp) == AOP_IMMD) {
12278 emitcode ("mov","dps,#1");
12279 emitcode ("mov", "dptr,%s",
12280 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12281 emitcode ("mov","dps,#0");
12283 emitcode ("mov","dpl1,%s",
12284 aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12285 emitcode ("mov","dph1,%s",
12286 aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12287 emitcode ("mov","dpx1,%s",
12288 aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12290 freeAsmop (pp, NULL, ic, FALSE);
12292 /* make the call */
12293 emitcode ("lcall","System_%sRTCRegisters",name);
12295 unsavermask(rsave);
12298 /*-----------------------------------------------------------------*/
12299 /* genSystemThreadSleep - */
12300 /*-----------------------------------------------------------------*/
12301 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12306 assert (nparms==1);
12307 /* save registers that need to be saved */
12308 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12309 ds390_rUmaskForOp (IC_RESULT(ic))));
12312 aopOp(to,ic,FALSE,FALSE);
12313 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12314 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12315 emitcode ("push","%s",
12316 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12317 emitcode ("push","%s",
12318 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12319 emitcode ("push","%s",
12320 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12321 emitcode ("push","%s",
12322 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12323 emitcode ("pop","ar3");
12324 emitcode ("pop","ar2");
12325 emitcode ("pop","ar1");
12326 emitcode ("pop","ar0");
12328 emitcode ("mov","r0,%s",
12329 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12330 emitcode ("mov","r1,%s",
12331 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12332 emitcode ("mov","r2,%s",
12333 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12334 emitcode ("mov","r3,%s",
12335 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12337 freeAsmop (to, NULL, ic, FALSE);
12339 /* suspend in acc */
12341 aopOp(s,ic,FALSE,FALSE);
12342 emitcode ("mov","a,%s",
12343 aopGet(AOP(s),0,FALSE,TRUE,NULL));
12344 freeAsmop (s, NULL, ic, FALSE);
12346 /* make the call */
12347 emitcode ("lcall","System_%s",name);
12349 unsavermask(rsave);
12352 /*-----------------------------------------------------------------*/
12353 /* genSystemThreadResume - */
12354 /*-----------------------------------------------------------------*/
12355 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12360 assert (nparms==2);
12361 /* save registers that need to be saved */
12362 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12363 ds390_rUmaskForOp (IC_RESULT(ic))));
12369 aopOp(pid,ic,FALSE,FALSE);
12370 emitcode ("mov","r0,%s",
12371 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12372 freeAsmop (pid, NULL, ic, FALSE);
12375 aopOp(tid,ic,FALSE,FALSE);
12376 emitcode ("mov","a,%s",
12377 aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12378 freeAsmop (tid, NULL, ic, FALSE);
12380 emitcode ("lcall","System_ThreadResume");
12382 /* put result into place */
12384 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12385 if (rsym->liveFrom != rsym->liveTo) {
12386 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12387 aopPut(AOP(IC_RESULT(ic)),"a",0);
12388 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12391 unsavermask(rsave);
12394 /*-----------------------------------------------------------------*/
12395 /* genSystemProcessResume - */
12396 /*-----------------------------------------------------------------*/
12397 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12402 assert (nparms==1);
12403 /* save registers that need to be saved */
12404 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12405 ds390_rUmaskForOp (IC_RESULT(ic))));
12410 aopOp(pid,ic,FALSE,FALSE);
12411 emitcode ("mov","a,%s",
12412 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12413 freeAsmop (pid, NULL, ic, FALSE);
12415 emitcode ("lcall","System_ProcessResume");
12417 unsavermask(rsave);
12420 /*-----------------------------------------------------------------*/
12422 /*-----------------------------------------------------------------*/
12423 static void genSystem (iCode *ic,int nparms,char *name)
12425 assert(nparms == 0);
12427 emitcode ("lcall","System_%s",name);
12430 /*-----------------------------------------------------------------*/
12431 /* genSystemPoll - */
12432 /*-----------------------------------------------------------------*/
12433 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12438 assert (nparms==1);
12439 /* save registers that need to be saved */
12440 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12441 ds390_rUmaskForOp (IC_RESULT(ic))));
12444 aopOp (fp,ic,FALSE,FALSE);
12445 if (AOP_TYPE (fp) == AOP_IMMD) {
12446 emitcode ("mov", "dptr,%s",
12447 aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12448 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12449 emitcode ("mov","dpl,%s",
12450 aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12451 emitcode ("mov","dph,%s",
12452 aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12453 emitcode ("mov","dpx,%s",
12454 aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12456 freeAsmop (fp, NULL, ic, FALSE);
12458 emitcode ("lcall","System_%sPoll",name);
12460 /* put result into place */
12462 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12463 if (rsym->liveFrom != rsym->liveTo) {
12464 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12465 aopPut(AOP(IC_RESULT(ic)),"a",0);
12466 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12469 unsavermask(rsave);
12472 /*-----------------------------------------------------------------*/
12473 /* genSystemGetCurrentID - */
12474 /*-----------------------------------------------------------------*/
12475 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12477 assert (nparms==0);
12479 emitcode ("lcall","System_GetCurrent%sId",name);
12480 /* put result into place */
12482 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12483 if (rsym->liveFrom != rsym->liveTo) {
12484 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12485 aopPut(AOP(IC_RESULT(ic)),"a",0);
12486 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12491 /*-----------------------------------------------------------------*/
12492 /* genBuiltIn - calls the appropriate function to generating code */
12493 /* for a built in function */
12494 /*-----------------------------------------------------------------*/
12495 static void genBuiltIn (iCode *ic)
12497 operand *bi_parms[MAX_BUILTIN_ARGS];
12502 /* get all the arguments for a built in function */
12503 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12505 /* which function is it */
12506 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12507 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12508 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12509 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12510 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12511 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12512 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12513 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12514 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12515 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12516 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12517 } else if (strcmp(bif->name,"__builtin_inp")==0) {
12518 genInp(bi_iCode,nbi_parms,bi_parms);
12519 } else if (strcmp(bif->name,"__builtin_outp")==0) {
12520 genOutp(bi_iCode,nbi_parms,bi_parms);
12521 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12522 genSwapW(bi_iCode,nbi_parms,bi_parms);
12523 /* JavaNative builtIns */
12524 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12525 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12526 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12527 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12528 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12529 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12530 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12531 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12532 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12533 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12534 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12535 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12536 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12537 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12538 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12539 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12540 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12541 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12542 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12543 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12544 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12545 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12546 } else if (strcmp(bif->name,"MM_Malloc")==0) {
12547 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12548 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12549 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12550 } else if (strcmp(bif->name,"MM_Free")==0) {
12551 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12552 } else if (strcmp(bif->name,"MM_Deref")==0) {
12553 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12554 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12555 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12556 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12557 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12558 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12559 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12560 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12561 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12562 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12563 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12564 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12565 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12566 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12567 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12568 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12569 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12570 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12571 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12572 } else if (strcmp(bif->name,"System_SaveThread")==0) {
12573 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12574 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12575 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12576 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12577 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12578 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12579 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12580 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12581 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12582 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12583 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12584 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12585 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12586 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12587 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12588 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12589 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12590 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12591 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12592 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12593 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12595 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12601 /*-----------------------------------------------------------------*/
12602 /* gen390Code - generate code for Dallas 390 based controllers */
12603 /*-----------------------------------------------------------------*/
12605 gen390Code (iCode * lic)
12610 lineHead = lineCurr = NULL;
12611 dptrn[1][0] = "dpl1";
12612 dptrn[1][1] = "dph1";
12613 dptrn[1][2] = "dpx1";
12615 if (options.model == MODEL_FLAT24) {
12616 fReturnSizeDS390 = 5;
12617 fReturn = fReturn24;
12619 fReturnSizeDS390 = 4;
12620 fReturn = fReturn16;
12621 options.stack10bit=0;
12624 /* print the allocation information */
12626 printAllocInfo (currFunc, codeOutFile);
12628 /* if debug information required */
12629 if (options.debug && currFunc)
12631 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
12633 if (IS_STATIC (currFunc->etype))
12634 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12636 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12639 /* stack pointer name */
12640 if (options.useXstack)
12646 for (ic = lic; ic; ic = ic->next)
12649 if (ic->lineno && cln != ic->lineno)
12654 emitcode ("", "C$%s$%d$%d$%d ==.",
12655 FileBaseName (ic->filename), ic->lineno,
12656 ic->level, ic->block);
12659 if (!options.noCcodeInAsm) {
12660 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
12661 printCLine(ic->filename, ic->lineno));
12665 if (options.iCodeInAsm) {
12666 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12668 /* if the result is marked as
12669 spilt and rematerializable or code for
12670 this has already been generated then
12672 if (resultRemat (ic) || ic->generated)
12675 /* depending on the operation */
12695 /* IPOP happens only when trying to restore a
12696 spilt live range, if there is an ifx statement
12697 following this pop then the if statement might
12698 be using some of the registers being popped which
12699 would destory the contents of the register so
12700 we need to check for this condition and handle it */
12702 ic->next->op == IFX &&
12703 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12704 genIfx (ic->next, ic);
12722 genEndFunction (ic);
12742 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12759 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12763 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12770 /* note these two are xlated by algebraic equivalence
12771 during parsing SDCC.y */
12772 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12773 "got '>=' or '<=' shouldn't have come here");
12777 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12789 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12793 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12797 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12821 genRightShift (ic);
12824 case GET_VALUE_AT_ADDRESS:
12825 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12829 if (POINTER_SET (ic))
12830 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
12856 if (ic->builtinSEND) genBuiltIn(ic);
12857 else addSet (&_G.sendSet, ic);
12870 /* now we are ready to call the
12871 peep hole optimizer */
12872 if (!options.nopeep)
12873 peepHole (&lineHead);
12875 /* now do the actual printing */
12876 printLine (lineHead, codeOutFile);