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 -------------------------------------------------------------------------*/
37 #include "SDCCglobl.h"
40 #define BETTER_LITERAL_SHIFT
42 char *aopLiteral (value * val, int offset);
45 /* this is the down and dirty file with all kinds of
46 kludgy & hacky stuff. This is what it is all about
47 CODE GENERATION for a specific MCU . some of the
48 routines may be reusable, will have to see */
50 static char *zero = "#0";
51 static char *one = "#1";
56 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
57 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
59 short fReturnSizeDS390 = 5;
60 static char *fReturn24[] =
61 {"dpl", "dph", "dpx", "b", "a"};
62 static char *fReturn16[] =
63 {"dpl", "dph", "b", "a"};
64 static char **fReturn = fReturn24;
65 static char *accUse[] =
67 static char *dptrn[2][3];
68 static char *javaRet[] = { "r0","r1","r2","r3"};
69 static short rbank = -1;
87 static char *rb1regs[] = {
88 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
91 static void saveRBank (int, iCode *, bool);
93 #define RESULTONSTACK(x) \
94 (IC_RESULT(x) && IC_RESULT(x)->aop && \
95 IC_RESULT(x)->aop->type == AOP_STK )
97 #define MOVA(x) _movA(x)
98 #define MOVB(x) _movB(x)
100 #define CLRC emitcode("clr","c")
101 #define SETC emitcode("setb","c")
103 // A scratch register which will be used to hold
104 // result bytes from operands in far space via DPTR2.
105 #define DP2_RESULT_REG "_ap"
107 static lineNode *lineHead = NULL;
108 static lineNode *lineCurr = NULL;
110 static unsigned char SLMask[] =
111 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
112 0xE0, 0xC0, 0x80, 0x00};
113 static unsigned char SRMask[] =
114 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
115 0x07, 0x03, 0x01, 0x00};
121 #define PROTECT_SP {if (options.protect_sp_update) { \
122 symbol *lbl = newiTempLabel(NULL); \
123 emitcode ("setb","F1"); \
124 emitcode ("jbc","EA,!tlabel",lbl->key+100); \
125 emitcode ("clr","F1"); \
126 emitcode ("","!tlabeldef",lbl->key+100); \
128 #define UNPROTECT_SP { if (options.protect_sp_update) { \
129 symbol *lbl = newiTempLabel(NULL); \
130 emitcode ("jnb","F1,!tlabel",lbl->key+100); \
131 emitcode ("setb","EA"); \
132 emitcode ("","!tlabeldef",lbl->key+100); \
135 static int _currentDPS; /* Current processor DPS. */
136 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
137 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
139 /*-----------------------------------------------------------------*/
140 /* emitcode - writes the code into a file : for now it is simple */
141 /*-----------------------------------------------------------------*/
143 emitcode (char *inst, const char *fmt,...)
146 char lb[INITIAL_INLINEASM];
155 SNPRINTF (lb, sizeof(lb), "%s\t", inst);
159 SNPRINTF (lb, sizeof(lb), "%s", inst);
162 tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), fmt, ap);
166 tvsprintf (lb, sizeof(lb), fmt, ap);
169 while (isspace (*lbp))
176 lineCurr = (lineCurr ?
177 connectLine (lineCurr, newLineNode (lb)) :
178 (lineHead = newLineNode (lb)));
181 lineCurr->isInline = _G.inLine;
182 lineCurr->isDebug = _G.debugLine;
183 lineCurr->ic = _G.current_iCode;
184 lineCurr->aln = ds390newAsmLineNode(_currentDPS);
188 /*-----------------------------------------------------------------*/
189 /* ds390_emitDebuggerSymbol - associate the current code location */
190 /* with a debugger symbol */
191 /*-----------------------------------------------------------------*/
193 ds390_emitDebuggerSymbol (char * debugSym)
196 emitcode ("", "%s ==.", debugSym);
201 // Move the passed value into A unless it is already there.
206 if (strcmp(s,"a") && strcmp(s,"acc"))
208 emitcode("mov","a,%s",s);
213 // Move the passed value into B unless it is already there.
220 emitcode("mov","b,%s",s);
224 /*-----------------------------------------------------------------*/
225 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
226 /*-----------------------------------------------------------------*/
228 getFreePtr (iCode * ic, asmop ** aopp, bool result)
233 /* the logic: if r0 & r1 used in the instruction
234 then we are in trouble otherwise */
236 /* first check if r0 & r1 are used by this
237 instruction, in which case we are in trouble */
238 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
239 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
244 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
245 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
247 /* if no usage of r0 then return it */
250 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
251 (*aopp)->type = AOP_R0;
253 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
256 /* if no usage of r1 then return it */
259 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
260 (*aopp)->type = AOP_R1;
262 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
265 /* now we know they both have usage */
266 /* if r0 not used in this instruction */
269 /* push it if not already pushed */
272 emitcode ("push", "%s",
273 ds390_regWithIdx (R0_IDX)->dname);
277 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
278 (*aopp)->type = AOP_R0;
280 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
283 /* if r1 not used then */
287 /* push it if not already pushed */
290 emitcode ("push", "%s",
291 ds390_regWithIdx (R1_IDX)->dname);
295 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
296 (*aopp)->type = AOP_R1;
297 return ds390_regWithIdx (R1_IDX);
301 /* I said end of world but not quite end of world yet */
302 /* if this is a result then we can push it on the stack */
305 (*aopp)->type = AOP_STK;
309 /* other wise this is true end of the world */
310 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
311 "getFreePtr should never reach here");
314 return NULL; // notreached, but makes compiler happy.
317 /*-----------------------------------------------------------------*/
318 /* newAsmop - creates a new asmOp */
319 /*-----------------------------------------------------------------*/
321 newAsmop (short type)
325 aop = Safe_calloc (1, sizeof (asmop));
331 /*-----------------------------------------------------------------*/
332 /* genSetDPTR: generate code to select which DPTR is in use (zero */
333 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
334 /* alternate DPTR (DPL1/DPH1/DPX1). */
335 /*-----------------------------------------------------------------*/
340 /* If we are doing lazy evaluation, simply note the desired
341 * change, but don't emit any code yet.
351 emitcode ("mov", "dps,#0");
356 emitcode ("mov", "dps,#1");
360 /*-----------------------------------------------------------------*/
361 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
363 /* Any code that operates on DPTR (NB: not on the individual */
364 /* components, like DPH) *must* call _flushLazyDPS() before using */
365 /* DPTR within a lazy DPS evaluation block. */
367 /* Note that aopPut and aopGet already contain the proper calls to */
368 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
369 /* DPS evaluation block. */
371 /* Also, _flushLazyDPS must be called before any flow control */
372 /* operations that could potentially branch out of the block. */
374 /* Lazy DPS evaluation is simply an optimization (though an */
375 /* important one), so if in doubt, leave it out. */
376 /*-----------------------------------------------------------------*/
378 _startLazyDPSEvaluation (void)
382 #ifdef BETTER_LITERAL_SHIFT
389 /*-----------------------------------------------------------------*/
390 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
391 /* desired one. Call before using DPTR within a lazy DPS evaluation */
393 /*-----------------------------------------------------------------*/
403 if (_desiredDPS != _currentDPS)
407 emitcode ("inc", "dps");
411 emitcode ("dec", "dps");
413 _currentDPS = _desiredDPS;
417 /*-----------------------------------------------------------------*/
418 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
420 /* Forces us back to the safe state (standard DPTR selected). */
421 /*-----------------------------------------------------------------*/
423 _endLazyDPSEvaluation (void)
425 #ifdef BETTER_LITERAL_SHIFT
444 /*-----------------------------------------------------------------*/
445 /* pointerCode - returns the code for a pointer type */
446 /*-----------------------------------------------------------------*/
448 pointerCode (sym_link * etype)
451 return PTR_TYPE (SPEC_OCLS (etype));
455 /*-----------------------------------------------------------------*/
456 /* leftRightUseAcc - returns size of accumulator use by operands */
457 /*-----------------------------------------------------------------*/
459 leftRightUseAcc(iCode *ic)
468 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
469 "null iCode pointer");
476 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
479 size = getSize (OP_SYMBOL (op)->type);
484 else if (ic->op == JUMPTABLE)
487 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
490 size = getSize (OP_SYMBOL (op)->type);
498 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
501 size = getSize (OP_SYMBOL (op)->type);
506 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
509 size = getSize (OP_SYMBOL (op)->type);
521 /*-----------------------------------------------------------------*/
522 /* aopForSym - for a true symbol */
523 /*-----------------------------------------------------------------*/
525 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
528 memmap *space = SPEC_OCLS (sym->etype);
529 int accuse = leftRightUseAcc (ic);
531 /* if already has one */
534 if ((sym->aop->type == AOP_DPTR && useDP2)
535 || (sym->aop->type == AOP_DPTR2 && !useDP2))
541 /* assign depending on the storage class */
542 /* if it is on the stack or indirectly addressable */
543 /* space we need to assign either r0 or r1 to it */
544 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
546 sym->aop = aop = newAsmop (0);
547 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
548 aop->size = getSize (sym->type);
550 /* now assign the address of the variable to
551 the pointer register */
552 if (aop->type != AOP_STK)
557 if (_G.accInUse || accuse)
558 emitcode ("push", "acc");
560 if (_G.bInUse || (accuse>1))
561 emitcode ("push", "b");
563 emitcode ("mov", "a,_bp");
564 emitcode ("add", "a,#!constbyte",
566 ((char) (sym->stack - _G.nRegsSaved)) :
567 ((char) sym->stack)) & 0xff);
568 emitcode ("mov", "%s,a",
569 aop->aopu.aop_ptr->name);
571 if (_G.bInUse || (accuse>1))
572 emitcode ("pop", "b");
574 if (_G.accInUse || accuse)
575 emitcode ("pop", "acc");
578 emitcode ("mov", "%s,#%s",
579 aop->aopu.aop_ptr->name,
581 aop->paged = space->paged;
584 aop->aopu.aop_stk = sym->stack;
588 if (sym->onStack && options.stack10bit)
590 short stack_val = -((sym->stack < 0) ?
591 ((short) (sym->stack - _G.nRegsSaved)) :
592 ((short) sym->stack)) ;
593 if (useDP2 && _G.dptr1InUse) {
594 emitcode ("push","dpl1");
595 emitcode ("push","dph1");
596 emitcode ("push","dpx1");
597 } else if (_G.dptrInUse ) {
598 emitcode ("push","dpl");
599 emitcode ("push","dph");
600 emitcode ("push","dpx");
602 /* It's on the 10 bit stack, which is located in
605 if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
607 if (options.model == MODEL_FLAT24)
609 emitcode ("mov", "dpx1,#!constbyte",
610 (options.stack_loc >> 16) & 0xff);
612 emitcode ("mov", "dph1,_bpx+1");
614 emitcode ("mov", "dpl1,_bpx");
615 emitcode ("mov","dps,#1");
617 if (options.model == MODEL_FLAT24)
619 emitcode ("mov", "dpx,#!constbyte",
620 (options.stack_loc >> 16) & 0xff);
622 emitcode ("mov", "dph,_bpx+1");
623 emitcode ("mov", "dpl,_bpx");
625 stack_val = -stack_val;
626 while (stack_val--) {
627 emitcode ("inc","dptr");
630 emitcode("mov","dps,#0");
633 if (_G.accInUse || accuse)
634 emitcode ("push", "acc");
636 if (_G.bInUse || (accuse>1))
637 emitcode ("push", "b");
639 emitcode ("mov", "a,_bpx");
640 emitcode ("clr","c");
641 emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
642 emitcode ("mov","b,a");
643 emitcode ("mov","a,_bpx+1");
644 emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
646 if (options.model == MODEL_FLAT24)
648 emitcode ("mov", "dpx1,#!constbyte",
649 (options.stack_loc >> 16) & 0xff);
651 emitcode ("mov", "dph1,a");
652 emitcode ("mov", "dpl1,b");
654 if (options.model == MODEL_FLAT24)
656 emitcode ("mov", "dpx,#!constbyte",
657 (options.stack_loc >> 16) & 0xff);
659 emitcode ("mov", "dph,a");
660 emitcode ("mov", "dpl,b");
663 if (_G.bInUse || (accuse>1))
664 emitcode ("pop", "b");
666 if (_G.accInUse || accuse)
667 emitcode ("pop", "acc");
669 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
670 aop->size = getSize (sym->type);
674 /* if in bit space */
675 if (IN_BITSPACE (space))
677 sym->aop = aop = newAsmop (AOP_CRY);
678 aop->aopu.aop_dir = sym->rname;
679 aop->size = getSize (sym->type);
682 /* if it is in direct space */
683 if (IN_DIRSPACE (space))
685 sym->aop = aop = newAsmop (AOP_DIR);
686 aop->aopu.aop_dir = sym->rname;
687 aop->size = getSize (sym->type);
691 /* special case for a function */
692 if (IS_FUNC (sym->type) && !(sym->isitmp))
694 sym->aop = aop = newAsmop (AOP_IMMD);
695 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
696 aop->size = FPTRSIZE;
700 /* only remaining is far space */
701 /* in which case DPTR gets the address */
702 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
707 emitcode ("mov", "dptr,#%s", sym->rname);
712 emitcode ("mov", "dptr,#%s", sym->rname);
714 aop->size = getSize (sym->type);
716 /* if it is in code space */
717 if (IN_CODESPACE (space))
723 /*-----------------------------------------------------------------*/
724 /* aopForRemat - rematerialzes an object */
725 /*-----------------------------------------------------------------*/
727 aopForRemat (symbol * sym)
729 iCode *ic = sym->rematiCode;
730 asmop *aop = newAsmop (AOP_IMMD);
737 val += (int) operandLitValue (IC_RIGHT (ic));
738 else if (ic->op == '-')
739 val -= (int) operandLitValue (IC_RIGHT (ic));
740 else if (IS_CAST_ICODE(ic)) {
741 sym_link *from_type = operandType(IC_RIGHT(ic));
742 aop->aopu.aop_immd.from_cast_remat = 1;
743 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
744 ptr_type = DCL_TYPE(from_type);
745 if (ptr_type == IPOINTER) {
752 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
757 SNPRINTF (buffer, sizeof(buffer),
759 OP_SYMBOL (IC_LEFT (ic))->rname,
760 val >= 0 ? '+' : '-',
761 abs (val) & 0xffffff);
765 if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
767 SNPRINTF(buffer, sizeof(buffer),
768 "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
772 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
776 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
777 /* set immd2 field if required */
778 if (aop->aopu.aop_immd.from_cast_remat)
780 tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
781 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
787 /*-----------------------------------------------------------------*/
788 /* aopHasRegs - returns true if aop has regs between from-to */
789 /*-----------------------------------------------------------------*/
790 static int aopHasRegs(asmop *aop, int from, int to)
794 if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
796 for (; size < aop->size ; size++) {
798 for (reg = from ; reg <= to ; reg++)
799 if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
804 /*-----------------------------------------------------------------*/
805 /* regsInCommon - two operands have some registers in common */
806 /*-----------------------------------------------------------------*/
808 regsInCommon (operand * op1, operand * op2)
813 /* if they have registers in common */
814 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
817 sym1 = OP_SYMBOL (op1);
818 sym2 = OP_SYMBOL (op2);
820 if (sym1->nRegs == 0 || sym2->nRegs == 0)
823 for (i = 0; i < sym1->nRegs; i++)
829 for (j = 0; j < sym2->nRegs; j++)
834 if (sym2->regs[j] == sym1->regs[i])
842 /*-----------------------------------------------------------------*/
843 /* operandsEqu - equivalent */
844 /*-----------------------------------------------------------------*/
846 operandsEqu (operand * op1, operand * op2)
850 /* if they not symbols */
851 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
854 sym1 = OP_SYMBOL (op1);
855 sym2 = OP_SYMBOL (op2);
857 /* if both are itemps & one is spilt
858 and the other is not then false */
859 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
860 sym1->isspilt != sym2->isspilt)
863 /* if they are the same */
867 if (sym1->rname[0] && sym2->rname[0]
868 && strcmp (sym1->rname, sym2->rname) == 0)
871 /* if left is a tmp & right is not */
872 if (IS_ITEMP (op1) &&
875 (sym1->usl.spillLoc == sym2))
878 if (IS_ITEMP (op2) &&
882 (sym2->usl.spillLoc == sym1))
885 /* are they spilt to the same location */
886 if (IS_ITEMP (op2) &&
890 (sym1->usl.spillLoc == sym2->usl.spillLoc))
896 /*-----------------------------------------------------------------*/
897 /* sameRegs - two asmops have the same registers */
898 /*-----------------------------------------------------------------*/
900 sameRegs (asmop * aop1, asmop * aop2)
906 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
913 if (aop1->type != AOP_REG ||
914 aop2->type != AOP_REG)
917 if (aop1->size != aop2->size)
920 for (i = 0; i < aop1->size; i++)
921 if (aop1->aopu.aop_reg[i] !=
922 aop2->aopu.aop_reg[i])
928 /*-----------------------------------------------------------------*/
929 /* aopOp - allocates an asmop for an operand : */
930 /*-----------------------------------------------------------------*/
932 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
941 /* if this a literal */
942 if (IS_OP_LITERAL (op))
944 op->aop = aop = newAsmop (AOP_LIT);
945 aop->aopu.aop_lit = op->operand.valOperand;
946 aop->size = getSize (operandType (op));
950 /* if already has a asmop then continue */
953 if ((op->aop->type == AOP_DPTR && useDP2)
954 || (op->aop->type == AOP_DPTR2 && !useDP2))
960 /* if the underlying symbol has a aop */
961 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
963 op->aop = OP_SYMBOL (op)->aop;
964 if ((op->aop->type == AOP_DPTR && useDP2)
965 || (op->aop->type == AOP_DPTR2 && !useDP2))
971 /* if this is a true symbol */
972 if (IS_TRUE_SYMOP (op))
974 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
978 /* this is a temporary : this has
984 e) can be a return use only */
986 sym = OP_SYMBOL (op);
988 /* if the type is a conditional */
989 if (sym->regType == REG_CND)
991 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
996 /* if it is spilt then two situations
998 b) has a spill location */
999 if (sym->isspilt || sym->nRegs == 0)
1002 /* rematerialize it NOW */
1005 sym->aop = op->aop = aop =
1007 aop->size = getSize (sym->type);
1014 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
1015 aop->size = getSize (sym->type);
1016 for (i = 0; i < 2; i++)
1017 aop->aopu.aop_str[i] = accUse[i];
1027 /* a AOP_STR uses DPTR, but DPTR is already in use;
1030 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
1033 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1034 aop->size = getSize (sym->type);
1035 for (i = 0; i < fReturnSizeDS390; i++)
1036 aop->aopu.aop_str[i] = fReturn[i];
1040 if (sym->dptr) { /* has been allocated to a DPTRn */
1041 aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
1042 aop->size = getSize (sym->type);
1043 aop->aopu.dptr = sym->dptr;
1047 if (sym->usl.spillLoc)
1049 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1051 /* force a new aop if sizes differ */
1052 sym->usl.spillLoc->aop = NULL;
1054 sym->aop = op->aop = aop =
1055 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
1056 aop->size = getSize (sym->type);
1060 /* else must be a dummy iTemp */
1061 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1062 aop->size = getSize (sym->type);
1066 /* must be in a register */
1067 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1068 aop->size = sym->nRegs;
1069 for (i = 0; i < sym->nRegs; i++)
1070 aop->aopu.aop_reg[i] = sym->regs[i];
1073 /*-----------------------------------------------------------------*/
1074 /* freeAsmop - free up the asmop given to an operand */
1075 /*----------------------------------------------------------------*/
1077 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1094 /* depending on the asmop type only three cases need work AOP_RO
1095 , AOP_R1 && AOP_STK */
1103 emitcode ("pop", "ar0");
1107 bitVectUnSetBit (ic->rUsed, R0_IDX);
1115 emitcode ("pop", "ar1");
1119 bitVectUnSetBit (ic->rUsed, R1_IDX);
1125 int stk = aop->aopu.aop_stk + aop->size;
1126 bitVectUnSetBit (ic->rUsed, R0_IDX);
1127 bitVectUnSetBit (ic->rUsed, R1_IDX);
1129 getFreePtr (ic, &aop, FALSE);
1131 if (options.stack10bit)
1133 /* I'm not sure what to do here yet... */
1136 "*** Warning: probably generating bad code for "
1137 "10 bit stack mode.\n");
1142 emitcode ("mov", "a,_bp");
1143 emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1144 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1148 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1153 emitcode ("pop", "acc");
1154 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1157 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1160 freeAsmop (op, NULL, ic, TRUE);
1163 emitcode ("pop", "ar0");
1169 emitcode ("pop", "ar1");
1174 if (_G.dptr1InUse) {
1175 emitcode ("pop","dpx1");
1176 emitcode ("pop","dph1");
1177 emitcode ("pop","dpl1");
1182 emitcode ("pop","dpx");
1183 emitcode ("pop","dph");
1184 emitcode ("pop","dpl");
1189 /* all other cases just dealloc */
1195 OP_SYMBOL (op)->aop = NULL;
1196 /* if the symbol has a spill */
1198 SPIL_LOC (op)->aop = NULL;
1203 #define DEFAULT_ACC_WARNING 0
1204 static int saveAccWarn = DEFAULT_ACC_WARNING;
1206 /*-------------------------------------------------------------------*/
1207 /* aopGet - for fetching value of the aop */
1209 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1210 /* in the accumulator. Set it to the name of a free register */
1211 /* if acc must be preserved; the register will be used to preserve */
1212 /* acc temporarily and to return the result byte. */
1213 /*-------------------------------------------------------------------*/
1222 /* offset is greater than
1224 if (offset > (aop->size - 1) &&
1225 aop->type != AOP_LIT)
1228 /* depending on type */
1236 /* if we need to increment it */
1237 while (offset > aop->coff)
1239 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1243 while (offset < aop->coff)
1245 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1252 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1253 return (dname ? "acc" : "a");
1255 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1256 return Safe_strdup(buffer);
1259 assert(offset <= 3);
1260 return dptrn[aop->aopu.dptr][offset];
1265 if (aop->type == AOP_DPTR2)
1273 // if (aop->type != AOP_DPTR2)
1275 // if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1276 // emitcode(";", "spanky: saveAcc for DPTR");
1279 emitcode ("xch", "a, %s", saveAcc);
1284 while (offset > aop->coff)
1286 emitcode ("inc", "dptr");
1290 while (offset < aop->coff)
1292 emitcode ("lcall", "__decdptr");
1299 emitcode ("clr", "a");
1300 emitcode ("movc", "a,@a+dptr");
1304 emitcode ("movx", "a,@dptr");
1307 if (aop->type == AOP_DPTR2)
1315 emitcode ("xch", "a, %s", saveAcc);
1316 // if (strcmp(saveAcc, "_ap"))
1318 // emitcode(";", "spiffy: non _ap return from aopGet.");
1323 return (dname ? "acc" : "a");
1326 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1328 SNPRINTF(buffer, sizeof(buffer),
1329 "%s",aop->aopu.aop_immd.aop_immd2);
1333 SNPRINTF(buffer, sizeof(buffer),
1334 "#%s", aop->aopu.aop_immd.aop_immd1);
1340 tsprintf(buffer, sizeof(buffer),
1341 "#!his",aop->aopu.aop_immd.aop_immd1);
1344 tsprintf(buffer, sizeof(buffer),
1345 "#!hihis",aop->aopu.aop_immd.aop_immd1);
1348 tsprintf(buffer, sizeof(buffer),
1349 "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1351 default: /* should not need this (just in case) */
1352 SNPRINTF (buffer, sizeof(buffer),
1354 aop->aopu.aop_immd.aop_immd1,
1360 SNPRINTF (buffer, sizeof(buffer),
1361 "#%s", aop->aopu.aop_immd.aop_immd1);
1363 return Safe_strdup(buffer);
1368 SNPRINTF (buffer, sizeof(buffer),
1375 SNPRINTF(buffer, sizeof(buffer),
1376 "%s", aop->aopu.aop_dir);
1379 return Safe_strdup(buffer);
1383 return aop->aopu.aop_reg[offset]->dname;
1385 return aop->aopu.aop_reg[offset]->name;
1388 emitcode ("clr", "a");
1389 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1390 emitcode ("rlc", "a");
1391 return (dname ? "acc" : "a");
1394 if (!offset && dname)
1396 return aop->aopu.aop_str[offset];
1399 return aopLiteral (aop->aopu.aop_lit, offset);
1403 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1407 return aop->aopu.aop_str[offset];
1411 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1412 "aopget got unsupported aop->type");
1415 return NULL; // not reached, but makes compiler happy.
1417 /*-----------------------------------------------------------------*/
1418 /* aopPut - puts a string for a aop */
1419 /*-----------------------------------------------------------------*/
1421 aopPut (asmop * aop, char *s, int offset)
1423 if (aop->size && offset > (aop->size - 1))
1425 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1426 "aopPut got offset > aop->size");
1430 /* will assign value to value */
1431 /* depending on where it is ofcourse */
1435 MOVA (s); /* read s in case it was volatile */
1441 SNPRINTF (buffer, sizeof(buffer),
1443 aop->aopu.aop_dir, offset);
1447 SNPRINTF (buffer, sizeof(buffer),
1448 "%s", aop->aopu.aop_dir);
1452 if (strcmp (buffer, s))
1454 emitcode ("mov", "%s,%s", buffer, s);
1459 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1460 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1463 strcmp (s, "r0") == 0 ||
1464 strcmp (s, "r1") == 0 ||
1465 strcmp (s, "r2") == 0 ||
1466 strcmp (s, "r3") == 0 ||
1467 strcmp (s, "r4") == 0 ||
1468 strcmp (s, "r5") == 0 ||
1469 strcmp (s, "r6") == 0 ||
1470 strcmp (s, "r7") == 0)
1472 emitcode ("mov", "%s,%s",
1473 aop->aopu.aop_reg[offset]->dname, s);
1477 emitcode ("mov", "%s,%s",
1478 aop->aopu.aop_reg[offset]->name, s);
1484 emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1490 if (aop->type == AOP_DPTR2)
1498 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1499 "aopPut writting to code space");
1503 while (offset > aop->coff)
1506 emitcode ("inc", "dptr");
1509 while (offset < aop->coff)
1512 emitcode ("lcall", "__decdptr");
1517 /* if not in accumulater */
1520 emitcode ("movx", "@dptr,a");
1522 if (aop->type == AOP_DPTR2)
1530 while (offset > aop->coff)
1533 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1535 while (offset < aop->coff)
1538 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1545 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1551 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1553 else if (strcmp (s, "r0") == 0 ||
1554 strcmp (s, "r1") == 0 ||
1555 strcmp (s, "r2") == 0 ||
1556 strcmp (s, "r3") == 0 ||
1557 strcmp (s, "r4") == 0 ||
1558 strcmp (s, "r5") == 0 ||
1559 strcmp (s, "r6") == 0 ||
1560 strcmp (s, "r7") == 0)
1563 SNPRINTF(buff, sizeof(buff),
1565 emitcode ("mov", "@%s,%s",
1566 aop->aopu.aop_ptr->name, buff);
1570 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1575 if (strcmp (s, "a") == 0)
1576 emitcode ("push", "acc");
1580 emitcode ("push", "acc");
1582 emitcode ("push", s);
1588 /* if bit variable */
1589 if (!aop->aopu.aop_dir)
1591 emitcode ("clr", "a");
1592 emitcode ("rlc", "a");
1597 emitcode ("clr", "%s", aop->aopu.aop_dir);
1599 emitcode ("setb", "%s", aop->aopu.aop_dir);
1600 else if (!strcmp (s, "c"))
1601 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1604 if (strcmp (s, "a"))
1609 /* set C, if a >= 1 */
1610 emitcode ("add", "a,#!constbyte",0xff);
1611 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1619 if (strcmp (aop->aopu.aop_str[offset], s))
1620 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1625 if (!offset && (strcmp (s, "acc") == 0))
1628 if (strcmp (aop->aopu.aop_str[offset], s))
1629 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1633 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1634 "aopPut got unsupported aop->type");
1641 /*--------------------------------------------------------------------*/
1642 /* reAdjustPreg - points a register back to where it should (coff==0) */
1643 /*--------------------------------------------------------------------*/
1645 reAdjustPreg (asmop * aop)
1647 if ((aop->coff==0) || (aop->size <= 1)) {
1656 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1660 if (aop->type == AOP_DPTR2)
1667 emitcode ("lcall", "__decdptr");
1670 if (aop->type == AOP_DPTR2)
1680 #define AOP(op) op->aop
1681 #define AOP_TYPE(op) AOP(op)->type
1682 #define AOP_SIZE(op) AOP(op)->size
1683 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1684 AOP_TYPE(x) == AOP_R0))
1686 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1687 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1690 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1691 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1692 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1693 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1694 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1695 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1697 // The following two macros can be used even if the aop has not yet been aopOp'd.
1698 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1699 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1701 /* Workaround for DS80C390 bug: div ab may return bogus results
1702 * if A is accessed in instruction immediately before the div.
1704 * Will be fixed in B4 rev of processor, Dallas claims.
1707 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1708 if (!AOP_NEEDSACC(RIGHT)) \
1710 /* We can load A first, then B, since \
1711 * B (the RIGHT operand) won't clobber A, \
1712 * thus avoiding touching A right before the div. \
1714 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1715 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1717 L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1722 /* Just stuff in a nop after loading A. */ \
1723 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1724 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1726 emitcode("nop", "; workaround for DS80C390 div bug."); \
1730 /*-----------------------------------------------------------------*/
1731 /* opIsGptr: returns non-zero if the passed operand is */
1732 /* a generic pointer type. */
1733 /*-----------------------------------------------------------------*/
1735 opIsGptr (operand * op)
1737 sym_link *type = operandType (op);
1739 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1746 /*-----------------------------------------------------------------*/
1747 /* getDataSize - get the operand data size */
1748 /*-----------------------------------------------------------------*/
1750 getDataSize (operand * op)
1753 size = AOP_SIZE (op);
1754 if (size == GPTRSIZE)
1756 sym_link *type = operandType (op);
1757 if (IS_GENPTR (type))
1759 /* generic pointer; arithmetic operations
1760 * should ignore the high byte (pointer type).
1768 /*-----------------------------------------------------------------*/
1769 /* outAcc - output Acc */
1770 /*-----------------------------------------------------------------*/
1772 outAcc (operand * result)
1775 size = getDataSize (result);
1778 aopPut (AOP (result), "a", 0);
1781 /* unsigned or positive */
1784 aopPut (AOP (result), zero, offset++);
1789 /*-----------------------------------------------------------------*/
1790 /* outBitC - output a bit C */
1791 /*-----------------------------------------------------------------*/
1793 outBitC (operand * result)
1795 /* if the result is bit */
1796 if (AOP_TYPE (result) == AOP_CRY)
1798 aopPut (AOP (result), "c", 0);
1802 emitcode ("clr", "a");
1803 emitcode ("rlc", "a");
1808 /*-----------------------------------------------------------------*/
1809 /* toBoolean - emit code for orl a,operator(sizeop) */
1810 /*-----------------------------------------------------------------*/
1812 toBoolean (operand * oper)
1814 int size = AOP_SIZE (oper) - 1;
1818 /* The generic part of a generic pointer should
1819 * not participate in it's truth value.
1821 * i.e. 0x10000000 is zero.
1823 if (opIsGptr (oper))
1825 D (emitcode (";", "toBoolean: generic ptr special case."););
1829 _startLazyDPSEvaluation ();
1830 if (AOP_NEEDSACC (oper) && size)
1835 emitcode ("push", "b");
1837 MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1841 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1848 emitcode ("orl", "b,%s",
1849 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1853 emitcode ("orl", "a,%s",
1854 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1857 _endLazyDPSEvaluation ();
1861 emitcode ("mov", "a,b");
1864 emitcode ("pop", "b");
1871 /*-----------------------------------------------------------------*/
1872 /* genNot - generate code for ! operation */
1873 /*-----------------------------------------------------------------*/
1879 D (emitcode (";", "genNot "););
1881 /* assign asmOps to operand & result */
1882 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1883 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1885 /* if in bit space then a special case */
1886 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1888 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1889 emitcode ("cpl", "c");
1890 outBitC (IC_RESULT (ic));
1894 toBoolean (IC_LEFT (ic));
1896 tlbl = newiTempLabel (NULL);
1897 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1898 emitcode ("", "!tlabeldef", tlbl->key + 100);
1899 outBitC (IC_RESULT (ic));
1902 /* release the aops */
1903 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1904 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1908 /*-----------------------------------------------------------------*/
1909 /* genCpl - generate code for complement */
1910 /*-----------------------------------------------------------------*/
1917 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1919 D(emitcode (";", "genCpl"));
1921 /* assign asmOps to operand & result */
1922 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1923 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1925 /* special case if in bit space */
1926 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1930 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1931 (SPEC_USIGN (letype) && IS_CHAR (letype)))
1933 /* promotion rules are responsible for this strange result:
1934 bit -> int -> ~int -> bit
1935 uchar -> int -> ~int -> bit
1937 werror(W_COMPLEMENT);
1938 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1941 tlbl=newiTempLabel(NULL);
1942 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, FALSE,NULL);
1943 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC ||
1944 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1945 IS_AOP_PREG (IC_LEFT (ic)))
1947 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1952 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1954 emitcode ("", "%05d$:", tlbl->key+100);
1955 outBitC (IC_RESULT(ic));
1959 size = AOP_SIZE (IC_RESULT (ic));
1960 _startLazyDPSEvaluation ();
1963 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1964 emitcode ("cpl", "a");
1965 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1967 _endLazyDPSEvaluation ();
1971 /* release the aops */
1972 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1973 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1976 /*-----------------------------------------------------------------*/
1977 /* genUminusFloat - unary minus for floating points */
1978 /*-----------------------------------------------------------------*/
1980 genUminusFloat (operand * op, operand * result)
1982 int size, offset = 0;
1984 D(emitcode (";", "genUminusFloat"););
1986 /* for this we just copy and then flip the bit */
1988 _startLazyDPSEvaluation ();
1989 size = AOP_SIZE (op) - 1;
1993 aopPut (AOP (result),
1994 aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1999 MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
2001 emitcode ("cpl", "acc.7");
2002 aopPut (AOP (result), "a", offset);
2003 _endLazyDPSEvaluation ();
2006 /*-----------------------------------------------------------------*/
2007 /* genUminus - unary minus code generation */
2008 /*-----------------------------------------------------------------*/
2010 genUminus (iCode * ic)
2015 D (emitcode (";", "genUminus "););
2018 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2019 aopOp (IC_RESULT (ic), ic, TRUE, (AOP_TYPE(IC_LEFT (ic)) == AOP_DPTR));
2021 /* if both in bit space then special
2023 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2024 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2027 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2028 emitcode ("cpl", "c");
2029 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2033 optype = operandType (IC_LEFT (ic));
2035 /* if float then do float stuff */
2036 if (IS_FLOAT (optype))
2038 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2042 /* otherwise subtract from zero */
2043 size = AOP_SIZE (IC_LEFT (ic));
2045 _startLazyDPSEvaluation ();
2048 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
2049 if (!strcmp (l, "a"))
2053 emitcode ("cpl", "a");
2054 emitcode ("addc", "a,#0");
2060 emitcode ("clr", "a");
2061 emitcode ("subb", "a,%s", l);
2063 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2065 _endLazyDPSEvaluation ();
2067 /* if any remaining bytes in the result */
2068 /* we just need to propagate the sign */
2069 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
2071 emitcode ("rlc", "a");
2072 emitcode ("subb", "a,acc");
2074 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2078 /* release the aops */
2079 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2080 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2083 /*-----------------------------------------------------------------*/
2084 /* savermask - saves registers in the mask */
2085 /*-----------------------------------------------------------------*/
2086 static void savermask(bitVect *rs_mask)
2089 if (options.useXstack) {
2090 if (bitVectBitValue (rs_mask, R0_IDX))
2091 emitcode ("mov", "b,r0");
2092 emitcode ("mov", "r0,%s", spname);
2093 for (i = 0; i < ds390_nRegs; i++) {
2094 if (bitVectBitValue (rs_mask, i)) {
2096 emitcode ("mov", "a,b");
2098 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2099 emitcode ("movx", "@r0,a");
2100 emitcode ("inc", "r0");
2103 emitcode ("mov", "%s,r0", spname);
2104 if (bitVectBitValue (rs_mask, R0_IDX))
2105 emitcode ("mov", "r0,b");
2107 for (i = 0; i < ds390_nRegs; i++) {
2108 if (bitVectBitValue (rs_mask, i))
2109 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2114 /*-----------------------------------------------------------------*/
2115 /* saveRegisters - will look for a call and save the registers */
2116 /*-----------------------------------------------------------------*/
2118 saveRegisters (iCode * lic)
2124 for (ic = lic; ic; ic = ic->next)
2125 if (ic->op == CALL || ic->op == PCALL)
2130 fprintf (stderr, "found parameter push with no function call\n");
2134 /* if the registers have been saved already then
2137 || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2140 /* special case if DPTR alive across a function call then must save it
2141 even though callee saves */
2142 if (IS_SYMOP(IC_LEFT(ic)) &&
2143 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2145 rsave = newBitVect(ic->rMask->size);
2146 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2147 if (bitVectBitValue(ic->rMask,i))
2148 rsave = bitVectSetBit(rsave,i);
2150 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2152 /* safe the registers in use at this time but skip the
2153 ones for the result */
2154 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2155 ds390_rUmaskForOp (IC_RESULT(ic)));
2161 /*-----------------------------------------------------------------*/
2162 /* usavermask - restore registers with mask */
2163 /*-----------------------------------------------------------------*/
2164 static void unsavermask(bitVect *rs_mask)
2167 if (options.useXstack) {
2168 emitcode ("mov", "r0,%s", spname);
2169 for (i = ds390_nRegs; i >= 0; i--) {
2170 if (bitVectBitValue (rs_mask, i)) {
2171 emitcode ("dec", "r0");
2172 emitcode ("movx", "a,@r0");
2174 emitcode ("mov", "b,a");
2176 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2179 emitcode ("mov", "%s,r0", spname);
2180 if (bitVectBitValue (rs_mask, R0_IDX))
2181 emitcode ("mov", "r0,b");
2183 for (i = ds390_nRegs; i >= 0; i--) {
2184 if (bitVectBitValue (rs_mask, i))
2185 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2190 /*-----------------------------------------------------------------*/
2191 /* unsaveRegisters - pop the pushed registers */
2192 /*-----------------------------------------------------------------*/
2194 unsaveRegisters (iCode * ic)
2198 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2200 rsave = newBitVect(ic->rMask->size);
2201 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2202 if (bitVectBitValue(ic->rMask,i))
2203 rsave = bitVectSetBit(rsave,i);
2205 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2207 /* restore the registers in use at this time but skip the
2208 ones for the result */
2209 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2210 ds390_rUmaskForOp (IC_RESULT(ic)));
2216 /*-----------------------------------------------------------------*/
2218 /*-----------------------------------------------------------------*/
2220 pushSide (operand * oper, int size)
2223 _startLazyDPSEvaluation ();
2226 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2227 if (AOP_TYPE (oper) != AOP_REG &&
2228 AOP_TYPE (oper) != AOP_DIR &&
2231 emitcode ("mov", "a,%s", l);
2232 emitcode ("push", "acc");
2235 emitcode ("push", "%s", l);
2237 _endLazyDPSEvaluation ();
2240 /*-----------------------------------------------------------------*/
2241 /* assignResultValue - */
2242 /*-----------------------------------------------------------------*/
2244 assignResultValue (operand * oper)
2247 int size = AOP_SIZE (oper);
2248 bool pushedAcc = FALSE;
2250 if (size == fReturnSizeDS390)
2252 /* I don't think this case can ever happen... */
2253 /* ACC is the last part of this. If writing the result
2254 * uses AC, we must preserve it.
2256 if (AOP_NEEDSACC(oper))
2258 emitcode(";", "assignResultValue special case for ACC.");
2259 emitcode("push", "acc");
2266 _startLazyDPSEvaluation ();
2269 aopPut (AOP (oper), fReturn[offset], offset);
2272 _endLazyDPSEvaluation ();
2276 emitcode("pop", "acc");
2277 aopPut(AOP(oper), "a", offset);
2282 /*-----------------------------------------------------------------*/
2283 /* genXpush - pushes onto the external stack */
2284 /*-----------------------------------------------------------------*/
2286 genXpush (iCode * ic)
2288 asmop *aop = newAsmop (0);
2290 int size, offset = 0;
2292 D (emitcode (";", "genXpush ");
2295 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2296 r = getFreePtr (ic, &aop, FALSE);
2299 emitcode ("mov", "%s,_spx", r->name);
2301 size = AOP_SIZE (IC_LEFT (ic));
2302 _startLazyDPSEvaluation ();
2306 MOVA (aopGet (AOP (IC_LEFT (ic)),
2307 offset++, FALSE, FALSE, NULL));
2308 emitcode ("movx", "@%s,a", r->name);
2309 emitcode ("inc", "%s", r->name);
2312 _endLazyDPSEvaluation ();
2315 emitcode ("mov", "_spx,%s", r->name);
2317 freeAsmop (NULL, aop, ic, TRUE);
2318 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2321 /*-----------------------------------------------------------------*/
2322 /* genIpush - generate code for pushing this gets a little complex */
2323 /*-----------------------------------------------------------------*/
2325 genIpush (iCode * ic)
2327 int size, offset = 0;
2330 D (emitcode (";", "genIpush ");
2333 /* if this is not a parm push : ie. it is spill push
2334 and spill push is always done on the local stack */
2338 /* and the item is spilt then do nothing */
2339 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2342 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2343 size = AOP_SIZE (IC_LEFT (ic));
2344 /* push it on the stack */
2345 _startLazyDPSEvaluation ();
2348 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2354 emitcode ("push", "%s", l);
2356 _endLazyDPSEvaluation ();
2360 /* this is a paramter push: in this case we call
2361 the routine to find the call and save those
2362 registers that need to be saved */
2365 /* if use external stack then call the external
2366 stack pushing routine */
2367 if (options.useXstack)
2373 /* then do the push */
2374 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2376 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2377 size = AOP_SIZE (IC_LEFT (ic));
2379 _startLazyDPSEvaluation ();
2382 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2383 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2384 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2387 emitcode ("mov", "a,%s", l);
2388 emitcode ("push", "acc");
2392 emitcode ("push", "%s", l);
2395 _endLazyDPSEvaluation ();
2397 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2400 /*-----------------------------------------------------------------*/
2401 /* genIpop - recover the registers: can happen only for spilling */
2402 /*-----------------------------------------------------------------*/
2404 genIpop (iCode * ic)
2408 D (emitcode (";", "genIpop ");
2412 /* if the temp was not pushed then */
2413 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2416 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2417 size = AOP_SIZE (IC_LEFT (ic));
2418 offset = (size - 1);
2419 _startLazyDPSEvaluation ();
2422 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2423 FALSE, TRUE, NULL));
2425 _endLazyDPSEvaluation ();
2427 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2430 /*-----------------------------------------------------------------*/
2431 /* unsaveRBank - restores the resgister bank from stack */
2432 /*-----------------------------------------------------------------*/
2434 unsaveRBank (int bank, iCode * ic, bool popPsw)
2440 if (options.useXstack)
2444 /* Assume r0 is available for use. */
2445 r = ds390_regWithIdx (R0_IDX);;
2450 r = getFreePtr (ic, &aop, FALSE);
2452 emitcode ("mov", "%s,_spx", r->name);
2457 if (options.useXstack)
2459 emitcode ("movx", "a,@%s", r->name);
2460 emitcode ("mov", "psw,a");
2461 emitcode ("dec", "%s", r->name);
2465 emitcode ("pop", "psw");
2469 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2471 if (options.useXstack)
2473 emitcode ("movx", "a,@%s", r->name);
2474 emitcode ("mov", "(%s+%d),a",
2475 regs390[i].base, 8 * bank + regs390[i].offset);
2476 emitcode ("dec", "%s", r->name);
2480 emitcode ("pop", "(%s+%d)",
2481 regs390[i].base, 8 * bank + regs390[i].offset);
2484 if (options.useXstack)
2486 emitcode ("mov", "_spx,%s", r->name);
2491 freeAsmop (NULL, aop, ic, TRUE);
2495 /*-----------------------------------------------------------------*/
2496 /* saveRBank - saves an entire register bank on the stack */
2497 /*-----------------------------------------------------------------*/
2499 saveRBank (int bank, iCode * ic, bool pushPsw)
2505 if (options.useXstack)
2509 /* Assume r0 is available for use. */
2510 r = ds390_regWithIdx (R0_IDX);;
2515 r = getFreePtr (ic, &aop, FALSE);
2517 emitcode ("mov", "%s,_spx", r->name);
2520 for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2522 if (options.useXstack)
2524 emitcode ("inc", "%s", r->name);
2525 emitcode ("mov", "a,(%s+%d)",
2526 regs390[i].base, 8 * bank + regs390[i].offset);
2527 emitcode ("movx", "@%s,a", r->name);
2530 emitcode ("push", "(%s+%d)",
2531 regs390[i].base, 8 * bank + regs390[i].offset);
2536 if (options.useXstack)
2538 emitcode ("mov", "a,psw");
2539 emitcode ("movx", "@%s,a", r->name);
2540 emitcode ("inc", "%s", r->name);
2541 emitcode ("mov", "_spx,%s", r->name);
2545 emitcode ("push", "psw");
2548 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2553 freeAsmop (NULL, aop, ic, TRUE);
2562 /*-----------------------------------------------------------------*/
2563 /* genSend - gen code for SEND */
2564 /*-----------------------------------------------------------------*/
2565 static void genSend(set *sendSet)
2569 static int rb1_count = 0;
2571 for (sic = setFirstItem (sendSet); sic;
2572 sic = setNextItem (sendSet)) {
2573 int size, offset = 0;
2575 size=getSize(operandType(IC_LEFT(sic)));
2576 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2577 if (sendCount == 0) { /* first parameter */
2578 // we know that dpl(hxb) is the result, so
2580 _startLazyDPSEvaluation ();
2582 aopOp (IC_LEFT (sic), sic, FALSE,
2583 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2585 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2588 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2589 FALSE, FALSE, NULL);
2590 if (strcmp (l, fReturn[offset])) {
2591 emitcode ("mov", "%s,%s",
2597 _endLazyDPSEvaluation ();
2598 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2600 } else { /* if more parameter in registers */
2601 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2603 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2604 FALSE, FALSE, NULL));
2606 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2613 adjustEsp(const char *reg)
2615 emitcode ("anl","%s,#3", reg);
2616 if (TARGET_IS_DS400)
2618 emitcode ("orl","%s,#!constbyte",
2620 (options.stack_loc >> 8) & 0xff);
2624 /*-----------------------------------------------------------------*/
2625 /* genCall - generates a call statement */
2626 /*-----------------------------------------------------------------*/
2628 genCall (iCode * ic)
2631 bool restoreBank = FALSE;
2632 bool swapBanks = FALSE;
2634 D (emitcode (";", "genCall "););
2636 /* if we are calling a not _naked function that is not using
2637 the same register bank then we need to save the
2638 destination registers on the stack */
2639 dtype = operandType (IC_LEFT (ic));
2640 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2641 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2642 IFFUNC_ISISR (currFunc->type))
2646 /* This is unexpected; the bank should have been saved in
2649 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2655 /* if caller saves & we have not saved then */
2659 /* if send set is not empty then assign */
2660 /* We've saved all the registers we care about;
2661 * therefore, we may clobber any register not used
2662 * in the calling convention (i.e. anything not in
2667 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2668 genSend(reverseSet(_G.sendSet));
2670 genSend(_G.sendSet);
2677 emitcode ("mov", "psw,#!constbyte",
2678 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2682 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2683 OP_SYMBOL (IC_LEFT (ic))->rname :
2684 OP_SYMBOL (IC_LEFT (ic))->name));
2688 emitcode ("mov", "psw,#!constbyte",
2689 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2692 /* if we need assign a result value */
2693 if ((IS_ITEMP (IC_RESULT (ic)) &&
2694 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2695 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2696 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2697 IS_TRUE_SYMOP (IC_RESULT (ic)))
2699 if (isOperandInFarSpace (IC_RESULT (ic))
2700 && getSize (operandType (IC_RESULT (ic))) <= 2)
2702 int size = getSize (operandType (IC_RESULT (ic)));
2704 /* Special case for 1 or 2 byte return in far space. */
2708 emitcode ("mov", "b,%s", fReturn[1]);
2713 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2719 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2723 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2725 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2730 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2733 assignResultValue (IC_RESULT (ic));
2735 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2739 /* adjust the stack for parameters if
2741 if (ic->parmBytes) {
2743 if (options.stack10bit) {
2744 if (ic->parmBytes <= 10) {
2745 emitcode(";","stack adjustment for parms");
2746 for (i=0; i < ic->parmBytes ; i++) {
2747 emitcode("pop","acc");
2751 emitcode ("clr","c");
2752 emitcode ("mov","a,sp");
2753 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2754 emitcode ("mov","sp,a");
2755 emitcode ("mov","a,esp");
2757 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2758 emitcode ("mov","esp,a");
2762 if (ic->parmBytes > 3) {
2763 emitcode ("mov", "a,%s", spname);
2764 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2765 emitcode ("mov", "%s,a", spname);
2767 for (i = 0; i < ic->parmBytes; i++)
2768 emitcode ("dec", "%s", spname);
2772 /* if we hade saved some registers then unsave them */
2774 unsaveRegisters (ic);
2776 /* if register bank was saved then pop them */
2778 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2781 /*-----------------------------------------------------------------*/
2782 /* genPcall - generates a call by pointer statement */
2783 /*-----------------------------------------------------------------*/
2785 genPcall (iCode * ic)
2788 symbol *rlbl = newiTempLabel (NULL);
2789 bool restoreBank=FALSE;
2791 D (emitcode (";", "genPcall ");
2795 /* if caller saves & we have not saved then */
2799 /* if we are calling a function that is not using
2800 the same register bank then we need to save the
2801 destination registers on the stack */
2802 dtype = operandType (IC_LEFT (ic));
2803 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2804 IFFUNC_ISISR (currFunc->type) &&
2805 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2806 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2810 /* push the return address on to the stack */
2811 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2812 emitcode ("push", "acc");
2813 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2814 emitcode ("push", "acc");
2816 if (options.model == MODEL_FLAT24)
2818 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2819 emitcode ("push", "acc");
2822 /* now push the calling address */
2823 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2825 pushSide (IC_LEFT (ic), FPTRSIZE);
2827 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2829 /* if send set is not empty the assign */
2832 genSend(reverseSet(_G.sendSet));
2836 emitcode ("ret", "");
2837 emitcode ("", "!tlabeldef", (rlbl->key + 100));
2840 /* if we need assign a result value */
2841 if ((IS_ITEMP (IC_RESULT (ic)) &&
2842 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2843 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2844 IS_TRUE_SYMOP (IC_RESULT (ic)))
2848 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2851 assignResultValue (IC_RESULT (ic));
2853 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2856 /* adjust the stack for parameters if
2861 if (options.stack10bit) {
2862 if (ic->parmBytes <= 10) {
2863 emitcode(";","stack adjustment for parms");
2864 for (i=0; i < ic->parmBytes ; i++) {
2865 emitcode("pop","acc");
2869 emitcode ("clr","c");
2870 emitcode ("mov","a,sp");
2871 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2872 emitcode ("mov","sp,a");
2873 emitcode ("mov","a,esp");
2875 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2876 emitcode ("mov","esp,a");
2880 if (ic->parmBytes > 3) {
2881 emitcode ("mov", "a,%s", spname);
2882 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2883 emitcode ("mov", "%s,a", spname);
2886 for (i = 0; i < ic->parmBytes; i++)
2887 emitcode ("dec", "%s", spname);
2891 /* if register bank was saved then unsave them */
2893 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2895 /* if we hade saved some registers then
2898 unsaveRegisters (ic);
2902 /*-----------------------------------------------------------------*/
2903 /* resultRemat - result is rematerializable */
2904 /*-----------------------------------------------------------------*/
2906 resultRemat (iCode * ic)
2908 if (SKIP_IC (ic) || ic->op == IFX)
2911 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2913 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2914 if (sym->remat && !POINTER_SET (ic))
2921 #if defined(__BORLANDC__) || defined(_MSC_VER)
2922 #define STRCASECMP stricmp
2924 #define STRCASECMP strcasecmp
2927 /*-----------------------------------------------------------------*/
2928 /* inExcludeList - return 1 if the string is in exclude Reg list */
2929 /*-----------------------------------------------------------------*/
2931 regsCmp(void *p1, void *p2)
2933 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2937 inExcludeList (char *s)
2939 const char *p = setFirstItem(options.excludeRegsSet);
2941 if (p == NULL || STRCASECMP(p, "none") == 0)
2945 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2948 /*-----------------------------------------------------------------*/
2949 /* genFunction - generated code for function entry */
2950 /*-----------------------------------------------------------------*/
2952 genFunction (iCode * ic)
2956 bool switchedPSW = FALSE;
2958 D (emitcode (";", "genFunction "););
2961 /* create the function header */
2962 emitcode (";", "-----------------------------------------");
2963 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2964 emitcode (";", "-----------------------------------------");
2966 emitcode ("", "%s:", sym->rname);
2967 ftype = operandType (IC_LEFT (ic));
2969 if (IFFUNC_ISNAKED(ftype))
2971 emitcode(";", "naked function: no prologue.");
2975 if (options.stack_probe)
2976 emitcode ("lcall","__stack_probe");
2978 /* here we need to generate the equates for the
2979 register bank if required */
2980 if (FUNC_REGBANK (ftype) != rbank)
2984 rbank = FUNC_REGBANK (ftype);
2985 for (i = 0; i < ds390_nRegs; i++)
2987 if (regs390[i].print) {
2988 if (strcmp (regs390[i].base, "0") == 0)
2989 emitcode ("", "%s !equ !constbyte",
2991 8 * rbank + regs390[i].offset);
2993 emitcode ("", "%s !equ %s + !constbyte",
2996 8 * rbank + regs390[i].offset);
3001 /* if this is an interrupt service routine then
3002 save acc, b, dpl, dph */
3003 if (IFFUNC_ISISR (sym->type))
3005 if (!inExcludeList ("acc"))
3006 emitcode ("push", "acc");
3007 if (!inExcludeList ("b"))
3008 emitcode ("push", "b");
3009 if (!inExcludeList ("dpl"))
3010 emitcode ("push", "dpl");
3011 if (!inExcludeList ("dph"))
3012 emitcode ("push", "dph");
3013 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3015 emitcode ("push", "dpx");
3016 /* Make sure we're using standard DPTR */
3017 emitcode ("push", "dps");
3018 emitcode ("mov", "dps,#0");
3019 if (options.stack10bit)
3021 /* This ISR could conceivably use DPTR2. Better save it. */
3022 emitcode ("push", "dpl1");
3023 emitcode ("push", "dph1");
3024 emitcode ("push", "dpx1");
3025 emitcode ("push", DP2_RESULT_REG);
3028 /* if this isr has no bank i.e. is going to
3029 run with bank 0 , then we need to save more
3031 if (!FUNC_REGBANK (sym->type))
3035 /* if this function does not call any other
3036 function then we can be economical and
3037 save only those registers that are used */
3038 if (!IFFUNC_HASFCALL(sym->type))
3041 /* if any registers used */
3044 /* save the registers used */
3045 for (i = 0; i < sym->regsUsed->size; i++)
3047 if (bitVectBitValue (sym->regsUsed, i))
3048 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3054 /* this function has a function call cannot
3055 determines register usage so we will have to push the
3057 saveRBank (0, ic, FALSE);
3058 if (options.parms_in_bank1) {
3059 for (i=0; i < 8 ; i++ ) {
3060 emitcode ("push","%s",rb1regs[i]);
3067 /* This ISR uses a non-zero bank.
3069 * We assume that the bank is available for our
3072 * However, if this ISR calls a function which uses some
3073 * other bank, we must save that bank entirely.
3075 unsigned long banksToSave = 0;
3077 if (IFFUNC_HASFCALL(sym->type))
3080 #define MAX_REGISTER_BANKS 4
3085 for (i = ic; i; i = i->next)
3087 if (i->op == ENDFUNCTION)
3089 /* we got to the end OK. */
3097 dtype = operandType (IC_LEFT(i));
3099 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3101 /* Mark this bank for saving. */
3102 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3104 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3108 banksToSave |= (1 << FUNC_REGBANK(dtype));
3111 /* And note that we don't need to do it in
3119 /* This is a mess; we have no idea what
3120 * register bank the called function might
3123 * The only thing I can think of to do is
3124 * throw a warning and hope.
3126 werror(W_FUNCPTR_IN_USING_ISR);
3130 if (banksToSave && options.useXstack)
3132 /* Since we aren't passing it an ic,
3133 * saveRBank will assume r0 is available to abuse.
3135 * So switch to our (trashable) bank now, so
3136 * the caller's R0 isn't trashed.
3138 emitcode ("push", "psw");
3139 emitcode ("mov", "psw,#!constbyte",
3140 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3144 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3146 if (banksToSave & (1 << ix))
3148 saveRBank(ix, NULL, FALSE);
3152 // TODO: this needs a closer look
3153 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3158 /* if callee-save to be used for this function
3159 then save the registers being used in this function */
3160 if (IFFUNC_CALLEESAVES(sym->type))
3164 /* if any registers used */
3167 /* save the registers used */
3168 for (i = 0; i < sym->regsUsed->size; i++)
3170 if (bitVectBitValue (sym->regsUsed, i))
3172 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3180 /* set the register bank to the desired value */
3181 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3184 emitcode ("push", "psw");
3185 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3188 if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3189 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3190 if (options.stack10bit) {
3191 emitcode ("push","_bpx");
3192 emitcode ("push","_bpx+1");
3193 emitcode ("mov","_bpx,%s",spname);
3194 emitcode ("mov","_bpx+1,esp");
3195 adjustEsp("_bpx+1");
3197 if (options.useXstack) {
3198 emitcode ("mov", "r0,%s", spname);
3199 emitcode ("mov", "a,_bp");
3200 emitcode ("movx", "@r0,a");
3201 emitcode ("inc", "%s", spname);
3203 /* set up the stack */
3204 emitcode ("push", "_bp"); /* save the callers stack */
3206 emitcode ("mov", "_bp,%s", spname);
3210 /* adjust the stack for the function */
3213 if (options.stack10bit) {
3214 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3215 assert (sym->recvSize <= 4);
3216 if (sym->stack <= 8) {
3217 while (i--) emitcode ("push","acc");
3220 emitcode ("mov","a,sp");
3221 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3222 emitcode ("mov","sp,a");
3223 emitcode ("mov","a,esp");
3225 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3226 emitcode ("mov","esp,a");
3231 werror (W_STACK_OVERFLOW, sym->name);
3233 if (i > 3 && sym->recvSize < 4) {
3235 emitcode ("mov", "a,sp");
3236 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3237 emitcode ("mov", "sp,a");
3241 emitcode ("inc", "sp");
3248 emitcode ("mov", "a,_spx");
3249 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3250 emitcode ("mov", "_spx,a");
3253 /* if critical function then turn interrupts off */
3254 if (IFFUNC_ISCRITICAL (ftype))
3256 symbol *tlbl = newiTempLabel (NULL);
3257 emitcode ("setb", "c");
3258 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3259 emitcode ("clr", "c");
3260 emitcode ("", "%05d$:", (tlbl->key + 100));
3261 emitcode ("push", "psw"); /* save old ea via c in psw */
3266 /*-----------------------------------------------------------------*/
3267 /* genEndFunction - generates epilogue for functions */
3268 /*-----------------------------------------------------------------*/
3270 genEndFunction (iCode * ic)
3272 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3273 lineNode *lnp = lineCurr;
3275 bitVect *regsUsedPrologue;
3276 bitVect *regsUnneeded;
3279 D (emitcode (";", "genEndFunction "););
3281 if (IFFUNC_ISNAKED(sym->type))
3283 emitcode(";", "naked function: no epilogue.");
3284 if (options.debug && currFunc)
3285 debugFile->writeEndFunction (currFunc, ic, 0);
3289 if (IFFUNC_ISCRITICAL (sym->type))
3291 emitcode ("pop", "psw"); /* restore ea via c in psw */
3292 emitcode ("mov", "ea,c");
3295 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3296 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3298 if (options.stack10bit) {
3300 emitcode ("mov", "sp,_bpx", spname);
3301 emitcode ("mov", "esp,_bpx+1", spname);
3304 emitcode ("mov", "%s,_bp", spname);
3308 /* if use external stack but some variables were
3309 added to the local stack then decrement the
3311 if (options.useXstack && sym->stack) {
3312 emitcode ("mov", "a,sp");
3313 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3314 emitcode ("mov", "sp,a");
3318 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3319 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3321 if (options.useXstack) {
3322 emitcode ("mov", "r0,%s", spname);
3323 emitcode ("movx", "a,@r0");
3324 emitcode ("mov", "_bp,a");
3325 emitcode ("dec", "%s", spname);
3327 if (options.stack10bit) {
3328 emitcode ("pop", "_bpx+1");
3329 emitcode ("pop", "_bpx");
3331 emitcode ("pop", "_bp");
3336 /* restore the register bank */
3337 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3339 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3340 || !options.useXstack)
3342 /* Special case of ISR using non-zero bank with useXstack
3345 emitcode ("pop", "psw");
3349 if (IFFUNC_ISISR (sym->type))
3352 /* now we need to restore the registers */
3353 /* if this isr has no bank i.e. is going to
3354 run with bank 0 , then we need to save more
3356 if (!FUNC_REGBANK (sym->type))
3359 /* if this function does not call any other
3360 function then we can be economical and
3361 save only those registers that are used */
3362 if (!IFFUNC_HASFCALL(sym->type))
3365 /* if any registers used */
3368 /* save the registers used */
3369 for (i = sym->regsUsed->size; i >= 0; i--)
3371 if (bitVectBitValue (sym->regsUsed, i))
3372 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3378 /* this function has a function call cannot
3379 determines register usage so we will have to pop the
3381 if (options.parms_in_bank1) {
3382 for (i = 7 ; i >= 0 ; i-- ) {
3383 emitcode ("pop","%s",rb1regs[i]);
3386 unsaveRBank (0, ic, FALSE);
3391 /* This ISR uses a non-zero bank.
3393 * Restore any register banks saved by genFunction
3396 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3399 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3401 if (savedBanks & (1 << ix))
3403 unsaveRBank(ix, NULL, FALSE);
3407 if (options.useXstack)
3409 /* Restore bank AFTER calling unsaveRBank,
3410 * since it can trash r0.
3412 emitcode ("pop", "psw");
3416 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3418 if (options.stack10bit)
3420 emitcode ("pop", DP2_RESULT_REG);
3421 emitcode ("pop", "dpx1");
3422 emitcode ("pop", "dph1");
3423 emitcode ("pop", "dpl1");
3425 emitcode ("pop", "dps");
3426 emitcode ("pop", "dpx");
3428 if (!inExcludeList ("dph"))
3429 emitcode ("pop", "dph");
3430 if (!inExcludeList ("dpl"))
3431 emitcode ("pop", "dpl");
3432 if (!inExcludeList ("b"))
3433 emitcode ("pop", "b");
3434 if (!inExcludeList ("acc"))
3435 emitcode ("pop", "acc");
3437 /* if debug then send end of function */
3438 if (options.debug && currFunc) {
3439 debugFile->writeEndFunction (currFunc, ic, 1);
3442 emitcode ("reti", "");
3446 if (IFFUNC_CALLEESAVES(sym->type))
3450 /* if any registers used */
3453 /* save the registers used */
3454 for (i = sym->regsUsed->size; i >= 0; i--)
3456 if (bitVectBitValue (sym->regsUsed, i))
3457 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3462 /* if debug then send end of function */
3463 if (options.debug && currFunc)
3465 debugFile->writeEndFunction (currFunc, ic, 1);
3468 emitcode ("ret", "");
3471 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3474 /* If this was an interrupt handler using bank 0 that called another */
3475 /* function, then all registers must be saved; nothing to optimized. */
3476 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3477 && !FUNC_REGBANK(sym->type))
3480 /* There are no push/pops to optimize if not callee-saves or ISR */
3481 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3484 /* If there were stack parameters, we cannot optimize without also */
3485 /* fixing all of the stack offsets; this is too dificult to consider. */
3486 if (FUNC_HASSTACKPARM(sym->type))
3489 /* Compute the registers actually used */
3490 regsUsed = newBitVect (ds390_nRegs);
3491 regsUsedPrologue = newBitVect (ds390_nRegs);
3494 if (lnp->ic && lnp->ic->op == FUNCTION)
3495 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3497 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3499 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3500 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3507 if (bitVectBitValue (regsUsedPrologue, DPS_IDX)
3508 && !bitVectBitValue (regsUsed, DPS_IDX))
3510 bitVectUnSetBit (regsUsedPrologue, DPS_IDX);
3513 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3514 && !bitVectBitValue (regsUsed, CND_IDX))
3516 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3517 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3518 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3519 bitVectUnSetBit (regsUsed, CND_IDX);
3522 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3524 /* If this was an interrupt handler that called another function */
3525 /* function, then assume working registers may be modified by it. */
3526 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3528 regsUsed = bitVectSetBit (regsUsed, AP_IDX);
3529 regsUsed = bitVectSetBit (regsUsed, DPX1_IDX);
3530 regsUsed = bitVectSetBit (regsUsed, DPL1_IDX);
3531 regsUsed = bitVectSetBit (regsUsed, DPH1_IDX);
3532 regsUsed = bitVectSetBit (regsUsed, DPX_IDX);
3533 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3534 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3535 regsUsed = bitVectSetBit (regsUsed, DPS_IDX);
3536 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3537 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3538 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3541 /* Remove the unneeded push/pops */
3542 regsUnneeded = newBitVect (ds390_nRegs);
3545 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3547 if (!strncmp(lnp->line, "push", 4))
3549 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3550 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3552 connectLine (lnp->prev, lnp->next);
3553 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3556 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3558 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3559 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3561 connectLine (lnp->prev, lnp->next);
3562 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3569 for (idx = 0; idx < regsUnneeded->size; idx++)
3570 if (bitVectBitValue (regsUnneeded, idx))
3571 emitcode ("", ";\teliminated unneeded push/pop %s", ds390_regWithIdx (idx)->dname);
3573 freeBitVect (regsUnneeded);
3574 freeBitVect (regsUsed);
3575 freeBitVect (regsUsedPrologue);
3578 /*-----------------------------------------------------------------*/
3579 /* genJavaNativeRet - generate code for return JavaNative */
3580 /*-----------------------------------------------------------------*/
3581 static void genJavaNativeRet(iCode *ic)
3585 aopOp (IC_LEFT (ic), ic, FALSE,
3586 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3587 size = AOP_SIZE (IC_LEFT (ic));
3591 /* it is assigned to GPR0-R3 then push them */
3592 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3593 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3594 for (i = 0 ; i < size ; i++ ) {
3595 emitcode ("push","%s",
3596 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3598 for (i = (size-1) ; i >= 0 ; i--) {
3599 emitcode ("pop","a%s",javaRet[i]);
3602 for (i = 0 ; i < size ; i++)
3603 emitcode ("mov","%s,%s",javaRet[i],
3604 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3606 for (i = size ; i < 4 ; i++ )
3607 emitcode ("mov","%s,#0",javaRet[i]);
3611 /*-----------------------------------------------------------------*/
3612 /* genRet - generate code for return statement */
3613 /*-----------------------------------------------------------------*/
3617 int size, offset = 0, pushed = 0;
3619 D (emitcode (";", "genRet "););
3621 /* if we have no return value then
3622 just generate the "ret" */
3626 /* if this is a JavaNative function then return
3627 value in different register */
3628 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3629 genJavaNativeRet(ic);
3632 /* we have something to return then
3633 move the return value into place */
3634 aopOp (IC_LEFT (ic), ic, FALSE,
3635 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3636 size = AOP_SIZE (IC_LEFT (ic));
3638 _startLazyDPSEvaluation ();
3642 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3644 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3646 emitcode ("push", "%s", l);
3651 /* Since A is the last element of fReturn,
3652 * is is OK to clobber it in the aopGet.
3654 l = aopGet (AOP (IC_LEFT (ic)), offset,
3655 FALSE, FALSE, NULL);
3656 if (strcmp (fReturn[offset], l))
3657 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3660 _endLazyDPSEvaluation ();
3667 if (strcmp (fReturn[pushed], "a"))
3668 emitcode ("pop", fReturn[pushed]);
3670 emitcode ("pop", "acc");
3673 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3676 /* generate a jump to the return label
3677 if the next is not the return statement */
3678 if (!(ic->next && ic->next->op == LABEL &&
3679 IC_LABEL (ic->next) == returnLabel))
3681 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3685 /*-----------------------------------------------------------------*/
3686 /* genLabel - generates a label */
3687 /*-----------------------------------------------------------------*/
3689 genLabel (iCode * ic)
3691 /* special case never generate */
3692 if (IC_LABEL (ic) == entryLabel)
3695 D (emitcode (";", "genLabel ");
3698 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3701 /*-----------------------------------------------------------------*/
3702 /* genGoto - generates a ljmp */
3703 /*-----------------------------------------------------------------*/
3705 genGoto (iCode * ic)
3707 D (emitcode (";", "genGoto ");
3709 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3712 /*-----------------------------------------------------------------*/
3713 /* findLabelBackwards: walks back through the iCode chain looking */
3714 /* for the given label. Returns number of iCode instructions */
3715 /* between that label and given ic. */
3716 /* Returns zero if label not found. */
3717 /*-----------------------------------------------------------------*/
3719 findLabelBackwards (iCode * ic, int key)
3728 /* If we have any pushes or pops, we cannot predict the distance.
3729 I don't like this at all, this should be dealt with in the
3731 if (ic->op == IPUSH || ic->op == IPOP) {
3735 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3737 /* printf("findLabelBackwards = %d\n", count); */
3745 /*-----------------------------------------------------------------*/
3746 /* genPlusIncr :- does addition with increment if possible */
3747 /*-----------------------------------------------------------------*/
3749 genPlusIncr (iCode * ic)
3751 unsigned int icount;
3752 unsigned int size = getDataSize (IC_RESULT (ic));
3754 /* will try to generate an increment */
3755 /* if the right side is not a literal
3757 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3760 /* if the literal value of the right hand side
3761 is greater than 4 then it is not worth it */
3762 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3765 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3766 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3768 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3772 /* if increment 16 bits in register */
3774 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3775 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3776 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3785 /* If the next instruction is a goto and the goto target
3786 * is <= 5 instructions previous to this, we can generate
3787 * jumps straight to that target.
3789 if (ic->next && ic->next->op == GOTO
3790 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3793 D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3794 tlbl = IC_LABEL (ic->next);
3799 tlbl = newiTempLabel (NULL);
3803 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3804 emitcode ("inc", "%s", l);
3806 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3807 IS_AOP_PREG (IC_RESULT (ic)))
3809 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3813 emitcode ("clr", "a");
3814 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3817 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
3818 emitcode ("inc", "%s", l);
3821 if (!strcmp(l, "acc"))
3823 emitcode("jnz", "!tlabel", tlbl->key + 100);
3825 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3826 IS_AOP_PREG (IC_RESULT (ic)))
3828 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3832 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3835 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3836 emitcode ("inc", "%s", l);
3840 if (!strcmp(l, "acc"))
3842 emitcode("jnz", "!tlabel", tlbl->key + 100);
3844 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3845 IS_AOP_PREG (IC_RESULT (ic)))
3847 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3851 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3854 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3855 emitcode ("inc", "%s", l);
3860 emitcode ("", "!tlabeldef", tlbl->key + 100);
3865 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3866 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
3867 options.model == MODEL_FLAT24 )
3869 if (IC_RESULT(ic)->isGptr)
3871 emitcode ("mov","b,%s",aopGet(AOP (IC_LEFT (ic)), 3, FALSE, FALSE, NULL));
3875 emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3877 emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3879 emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3882 while (icount--) emitcode ("inc","dptr");
3886 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3887 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3889 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3890 while (icount--) emitcode ("inc","dptr");
3891 emitcode ("mov","dps,#0");
3895 /* if the sizes are greater than 1 then we cannot */
3896 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3897 AOP_SIZE (IC_LEFT (ic)) > 1)
3900 /* we can if the aops of the left & result match or
3901 if they are in registers and the registers are the
3904 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3905 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3906 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3911 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3912 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3913 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3918 _startLazyDPSEvaluation ();
3921 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3923 _endLazyDPSEvaluation ();
3932 /*-----------------------------------------------------------------*/
3933 /* outBitAcc - output a bit in acc */
3934 /*-----------------------------------------------------------------*/
3936 outBitAcc (operand * result)
3938 symbol *tlbl = newiTempLabel (NULL);
3939 /* if the result is a bit */
3940 if (AOP_TYPE (result) == AOP_CRY)
3942 aopPut (AOP (result), "a", 0);
3946 emitcode ("jz", "!tlabel", tlbl->key + 100);
3947 emitcode ("mov", "a,%s", one);
3948 emitcode ("", "!tlabeldef", tlbl->key + 100);
3953 /*-----------------------------------------------------------------*/
3954 /* genPlusBits - generates code for addition of two bits */
3955 /*-----------------------------------------------------------------*/
3957 genPlusBits (iCode * ic)
3959 D (emitcode (";", "genPlusBits "););
3961 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3963 symbol *lbl = newiTempLabel (NULL);
3964 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3965 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3966 emitcode ("cpl", "c");
3967 emitcode ("", "!tlabeldef", (lbl->key + 100));
3968 outBitC (IC_RESULT (ic));
3972 emitcode ("clr", "a");
3973 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3974 emitcode ("rlc", "a");
3975 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3976 emitcode ("addc", "a,#0");
3977 outAcc (IC_RESULT (ic));
3982 adjustArithmeticResult (iCode * ic)
3984 if (opIsGptr (IC_RESULT (ic)) &&
3985 opIsGptr (IC_LEFT (ic)) &&
3986 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3988 aopPut (AOP (IC_RESULT (ic)),
3989 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3993 if (opIsGptr (IC_RESULT (ic)) &&
3994 opIsGptr (IC_RIGHT (ic)) &&
3995 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3997 aopPut (AOP (IC_RESULT (ic)),
3998 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
4002 if (opIsGptr (IC_RESULT (ic)) &&
4003 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4004 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4005 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4006 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4009 SNPRINTF (buff, sizeof(buff),
4010 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
4011 aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
4015 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
4016 // generates the result if possible. If result is generated, returns TRUE; otherwise
4017 // returns false and caller must deal with fact that result isn't aopOp'd.
4018 bool aopOp3(iCode * ic)
4020 bool dp1InUse, dp2InUse;
4023 // First, generate the right opcode. DPTR may be used if neither left nor result are
4026 // D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
4027 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
4028 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
4029 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
4031 // D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
4032 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
4033 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
4034 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
4037 // Right uses DPTR unless left or result is an AOP_STR; however,
4038 // if right is an AOP_STR, it must use DPTR regardless.
4039 if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
4040 && !AOP_IS_STR(IC_RIGHT(ic)))
4049 aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
4051 // if the right used DPTR, left MUST use DPTR2.
4052 // if the right used DPTR2, left MUST use DPTR.
4053 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
4054 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
4055 // enabling us to assign DPTR to result.
4057 if (AOP_USESDPTR(IC_RIGHT(ic)))
4061 else if (AOP_USESDPTR2(IC_RIGHT(ic)))
4067 if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
4077 aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
4080 // We've op'd the left & right. So, if left or right are the same operand as result,
4081 // we know aopOp will succeed, and we can just do it & bail.
4082 if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))
4084 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4087 if (isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
4089 // D(emitcode(";", "aopOp3: (left | right) & result equal"););
4090 aopOp(IC_RESULT(ic),ic,TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4094 // Operands may be equivalent (but not equal) if they share a spill location. If
4095 // so, use the same DPTR or DPTR2.
4096 if (operandsEqu (IC_LEFT(ic), IC_RESULT(ic)))
4098 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4101 if (operandsEqu (IC_RIGHT(ic), IC_RESULT(ic)))
4103 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4107 // Note which dptrs are currently in use.
4108 dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
4109 dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
4111 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
4113 if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
4118 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
4119 if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
4124 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
4125 if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
4130 aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
4132 // Some sanity checking...
4133 if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
4136 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
4137 __FILE__, __LINE__, ic->filename, ic->lineno);
4138 emitcode(";", ">>> unexpected DPTR here.");
4141 if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
4144 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
4145 __FILE__, __LINE__, ic->filename, ic->lineno);
4146 emitcode(";", ">>> unexpected DPTR2 here.");
4152 // Macro to aopOp all three operands of an ic. If this cannot be done,
4153 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
4154 // will be set TRUE. The caller must then handle the case specially, noting
4155 // that the IC_RESULT operand is not aopOp'd.
4157 #define AOP_OP_3_NOFATAL(ic, rc) \
4158 do { rc = !aopOp3(ic); } while (0)
4160 // aopOp the left & right operands of an ic.
4161 #define AOP_OP_2(ic) \
4162 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
4163 aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
4165 // convienience macro.
4166 #define AOP_SET_LOCALS(ic) \
4167 left = IC_LEFT(ic); \
4168 right = IC_RIGHT(ic); \
4169 result = IC_RESULT(ic);
4172 // Given an integer value of pushedSize bytes on the stack,
4173 // adjust it to be resultSize bytes, either by discarding
4174 // the most significant bytes or by zero-padding.
4176 // On exit from this macro, pushedSize will have been adjusted to
4177 // equal resultSize, and ACC may be trashed.
4178 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
4179 /* If the pushed data is bigger than the result, \
4180 * simply discard unused bytes. Icky, but works. \
4182 while (pushedSize > resultSize) \
4184 D (emitcode (";", "discarding unused result byte."););\
4185 emitcode ("pop", "acc"); \
4188 if (pushedSize < resultSize) \
4190 emitcode ("clr", "a"); \
4191 /* Conversly, we haven't pushed enough here. \
4192 * just zero-pad, and all is well. \
4194 while (pushedSize < resultSize) \
4196 emitcode("push", "acc"); \
4200 assert(pushedSize == resultSize);
4202 /*-----------------------------------------------------------------*/
4203 /* genPlus - generates code for addition */
4204 /*-----------------------------------------------------------------*/
4206 genPlus (iCode * ic)
4208 int size, offset = 0;
4212 D (emitcode (";", "genPlus "););
4214 /* special cases :- */
4215 if ( AOP_IS_STR(IC_LEFT(ic)) &&
4216 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4217 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4218 size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4220 while (size--) emitcode ("inc","dptr");
4222 emitcode ("mov","a,dpl");
4223 emitcode ("add","a,#!constbyte",size & 0xff);
4224 emitcode ("mov","dpl,a");
4225 emitcode ("mov","a,dph");
4226 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4227 emitcode ("mov","dph,a");
4228 emitcode ("mov","a,dpx");
4229 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4230 emitcode ("mov","dpx,a");
4232 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4235 if ( IS_SYMOP(IC_LEFT(ic)) &&
4236 OP_SYMBOL(IC_LEFT(ic))->remat &&
4237 isOperandInFarSpace(IC_RIGHT(ic))) {
4238 operand *op = IC_RIGHT(ic);
4239 IC_RIGHT(ic) = IC_LEFT(ic);
4243 AOP_OP_3_NOFATAL (ic, pushResult);
4247 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4252 /* if literal, literal on the right or
4253 if left requires ACC or right is already
4255 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4256 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4257 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4259 operand *t = IC_RIGHT (ic);
4260 IC_RIGHT (ic) = IC_LEFT (ic);
4262 emitcode (";", "Swapped plus args.");
4265 /* if both left & right are in bit
4267 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4268 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4274 /* if left in bit space & right literal */
4275 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4276 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4278 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4279 /* if result in bit space */
4280 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4282 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4283 emitcode ("cpl", "c");
4284 outBitC (IC_RESULT (ic));
4288 size = getDataSize (IC_RESULT (ic));
4289 _startLazyDPSEvaluation ();
4292 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4293 emitcode ("addc", "a,#0");
4294 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4296 _endLazyDPSEvaluation ();
4301 /* if I can do an increment instead
4302 of add then GOOD for ME */
4303 if (genPlusIncr (ic) == TRUE)
4305 emitcode (";", "did genPlusIncr");
4310 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4312 _startLazyDPSEvaluation ();
4315 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4317 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4319 emitcode ("add", "a,%s",
4320 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4322 emitcode ("addc", "a,%s",
4323 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4327 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4329 /* right is going to use ACC or we would have taken the
4332 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4334 D(emitcode(";", "+ AOP_ACC special case."););
4335 emitcode("xch", "a, %s", DP2_RESULT_REG);
4337 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4340 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4343 emitcode("add", "a, %s", DP2_RESULT_REG);
4347 emitcode ("add", "a,%s",
4348 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4354 emitcode ("addc", "a,%s",
4355 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4361 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4365 emitcode ("push", "acc");
4369 _endLazyDPSEvaluation ();
4373 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4375 size = getDataSize (IC_LEFT (ic));
4376 rSize = getDataSize (IC_RESULT (ic));
4378 ADJUST_PUSHED_RESULT(size, rSize);
4380 _startLazyDPSEvaluation ();
4383 emitcode ("pop", "acc");
4384 aopPut (AOP (IC_RESULT (ic)), "a", size);
4386 _endLazyDPSEvaluation ();
4389 adjustArithmeticResult (ic);
4392 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4393 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4394 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4397 /*-----------------------------------------------------------------*/
4398 /* genMinusDec :- does subtraction with deccrement if possible */
4399 /*-----------------------------------------------------------------*/
4401 genMinusDec (iCode * ic)
4403 unsigned int icount;
4404 unsigned int size = getDataSize (IC_RESULT (ic));
4406 /* will try to generate an increment */
4407 /* if the right side is not a literal
4409 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4412 /* if the literal value of the right hand side
4413 is greater than 4 then it is not worth it */
4414 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4417 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4418 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4420 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4424 /* if decrement 16 bits in register */
4425 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4426 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4427 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4436 /* If the next instruction is a goto and the goto target
4437 * is <= 5 instructions previous to this, we can generate
4438 * jumps straight to that target.
4440 if (ic->next && ic->next->op == GOTO
4441 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4444 emitcode (";", "tail decrement optimized (range %d)", labelRange);
4445 tlbl = IC_LABEL (ic->next);
4450 tlbl = newiTempLabel (NULL);
4454 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4455 emitcode ("dec", "%s", l);
4457 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4458 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4459 IS_AOP_PREG (IC_RESULT (ic)))
4461 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4465 emitcode ("mov", "a,#!constbyte",0xff);
4466 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4468 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4469 emitcode ("dec", "%s", l);
4472 if (!strcmp(l, "acc"))
4474 emitcode("jnz", "!tlabel", tlbl->key + 100);
4476 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4477 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4478 IS_AOP_PREG (IC_RESULT (ic)))
4480 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4484 emitcode ("mov", "a,#!constbyte",0xff);
4485 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4487 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4488 emitcode ("dec", "%s", l);
4492 if (!strcmp(l, "acc"))
4494 emitcode("jnz", "!tlabel", tlbl->key + 100);
4496 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4497 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4498 IS_AOP_PREG (IC_RESULT (ic)))
4500 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4504 emitcode ("mov", "a,#!constbyte",0xff);
4505 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4507 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4508 emitcode ("dec", "%s", l);
4512 emitcode ("", "!tlabeldef", tlbl->key + 100);
4517 /* if the sizes are greater than 1 then we cannot */
4518 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4519 AOP_SIZE (IC_LEFT (ic)) > 1)
4522 /* we can if the aops of the left & result match or
4523 if they are in registers and the registers are the
4526 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4527 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4528 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4531 _startLazyDPSEvaluation ();
4534 emitcode ("dec", "%s",
4535 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4537 _endLazyDPSEvaluation ();
4545 /*-----------------------------------------------------------------*/
4546 /* addSign - complete with sign */
4547 /*-----------------------------------------------------------------*/
4549 addSign (operand * result, int offset, int sign)
4551 int size = (getDataSize (result) - offset);
4554 _startLazyDPSEvaluation();
4557 emitcode ("rlc", "a");
4558 emitcode ("subb", "a,acc");
4561 aopPut (AOP (result), "a", offset++);
4568 aopPut (AOP (result), zero, offset++);
4571 _endLazyDPSEvaluation();
4575 /*-----------------------------------------------------------------*/
4576 /* genMinusBits - generates code for subtraction of two bits */
4577 /*-----------------------------------------------------------------*/
4579 genMinusBits (iCode * ic)
4581 symbol *lbl = newiTempLabel (NULL);
4583 D (emitcode (";", "genMinusBits "););
4585 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4587 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4588 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4589 emitcode ("cpl", "c");
4590 emitcode ("", "!tlabeldef", (lbl->key + 100));
4591 outBitC (IC_RESULT (ic));
4595 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4596 emitcode ("subb", "a,acc");
4597 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4598 emitcode ("inc", "a");
4599 emitcode ("", "!tlabeldef", (lbl->key + 100));
4600 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4601 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4605 /*-----------------------------------------------------------------*/
4606 /* genMinus - generates code for subtraction */
4607 /*-----------------------------------------------------------------*/
4609 genMinus (iCode * ic)
4611 int size, offset = 0;
4616 D (emitcode (";", "genMinus "););
4618 AOP_OP_3_NOFATAL(ic, pushResult);
4622 /* special cases :- */
4623 /* if both left & right are in bit space */
4624 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4625 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4631 /* if I can do an decrement instead
4632 of subtract then GOOD for ME */
4633 if (genMinusDec (ic) == TRUE)
4638 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4640 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4646 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4651 /* if literal, add a,#-lit, else normal subb */
4652 _startLazyDPSEvaluation ();
4654 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4655 if (AOP_USESDPTR(IC_RIGHT(ic))) {
4656 emitcode ("mov","b,%s",
4657 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4658 MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4659 emitcode ("subb","a,b");
4661 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4662 emitcode ("subb", "a,%s",
4663 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE,
4667 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4668 /* first add without previous c */
4670 if (!size && lit==-1) {
4671 emitcode ("dec", "a");
4673 emitcode ("add", "a,#!constbyte",
4674 (unsigned int) (lit & 0x0FFL));
4677 emitcode ("addc", "a,#!constbyte",
4678 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4683 emitcode ("push", "acc");
4685 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4689 _endLazyDPSEvaluation ();
4693 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4695 size = getDataSize (IC_LEFT (ic));
4696 rSize = getDataSize (IC_RESULT (ic));
4698 ADJUST_PUSHED_RESULT(size, rSize);
4700 _startLazyDPSEvaluation ();
4703 emitcode ("pop", "acc");
4704 aopPut (AOP (IC_RESULT (ic)), "a", size);
4706 _endLazyDPSEvaluation ();
4709 adjustArithmeticResult (ic);
4712 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4713 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4714 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4718 /*-----------------------------------------------------------------*/
4719 /* genMultbits :- multiplication of bits */
4720 /*-----------------------------------------------------------------*/
4722 genMultbits (operand * left,
4727 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4728 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4729 aopOp(result, ic, TRUE, FALSE);
4734 /*-----------------------------------------------------------------*/
4735 /* genMultOneByte : 8*8=8/16 bit multiplication */
4736 /*-----------------------------------------------------------------*/
4738 genMultOneByte (operand * left,
4745 bool runtimeSign, compiletimeSign;
4746 bool lUnsigned, rUnsigned;
4749 /* (if two literals: the value is computed before) */
4750 /* if one literal, literal on the right */
4751 if (AOP_TYPE (left) == AOP_LIT)
4756 emitcode (";", "swapped left and right");
4759 /* (if two literals: the value is computed before) */
4760 /* if one literal, literal on the right */
4761 if (AOP_TYPE (left) == AOP_LIT)
4766 /* emitcode (";", "swapped left and right"); */
4768 /* if no literal, unsigned on the right: shorter code */
4769 if ( AOP_TYPE (right) != AOP_LIT
4770 && SPEC_USIGN (getSpec (operandType (left))))
4777 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4778 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4780 if ((lUnsigned && rUnsigned)
4781 /* sorry, I don't know how to get size
4782 without calling aopOp (result,...);
4783 see Feature Request */
4784 /* || size == 1 */ ) /* no, this is not a bug; with a 1 byte result there's
4785 no need to take care about the signedness! */
4787 /* just an unsigned 8 * 8 = 8 multiply
4789 /* emitcode (";","unsigned"); */
4790 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4791 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4792 emitcode ("mul", "ab");
4794 _G.accInUse++; _G.bInUse++;
4795 aopOp (result, ic, TRUE, FALSE);
4796 size = AOP_SIZE (result);
4798 if (size < 1 || size > 2)
4800 /* this should never happen */
4801 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4802 size, __FILE__, lineno);
4806 aopPut (AOP (result), "a", 0);
4807 _G.accInUse--; _G.bInUse--;
4809 aopPut (AOP (result), "b", 1);
4813 /* we have to do a signed multiply */
4814 /* emitcode (";", "signed"); */
4816 /* now sign adjust for both left & right */
4818 /* let's see what's needed: */
4819 /* apply negative sign during runtime */
4820 runtimeSign = FALSE;
4821 /* negative sign from literals */
4822 compiletimeSign = FALSE;
4826 if (AOP_TYPE(left) == AOP_LIT)
4828 /* signed literal */
4829 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4831 compiletimeSign = TRUE;
4834 /* signed but not literal */
4840 if (AOP_TYPE(right) == AOP_LIT)
4842 /* signed literal */
4843 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4845 compiletimeSign ^= TRUE;
4848 /* signed but not literal */
4852 /* initialize F0, which stores the runtime sign */
4855 if (compiletimeSign)
4856 emitcode ("setb", "F0"); /* set sign flag */
4858 emitcode ("clr", "F0"); /* reset sign flag */
4861 /* save the signs of the operands */
4862 if (AOP_TYPE(right) == AOP_LIT)
4864 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4866 if (!rUnsigned && val < 0)
4867 emitcode ("mov", "b,#!constbyte", -val);
4869 emitcode ("mov", "b,#!constbyte", (unsigned char) val);
4871 else /* ! literal */
4873 if (rUnsigned) /* emitcode (";", "signed"); */
4874 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4877 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4878 lbl = newiTempLabel (NULL);
4879 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
4880 emitcode ("cpl", "F0"); /* complement sign flag */
4881 emitcode ("cpl", "a"); /* 2's complement */
4882 emitcode ("inc", "a");
4883 emitcode ("", "!tlabeldef", lbl->key + 100);
4884 emitcode ("mov", "b,a");
4888 if (AOP_TYPE(left) == AOP_LIT)
4890 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4892 if (!lUnsigned && val < 0)
4893 emitcode ("mov", "a,#!constbyte", -val);
4895 emitcode ("mov", "a,#!constbyte", (unsigned char) val);
4897 else /* ! literal */
4899 if (lUnsigned) /* emitcode (";", "signed"); */
4901 emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4904 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4905 lbl = newiTempLabel (NULL);
4906 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
4907 emitcode ("cpl", "F0"); /* complement sign flag */
4908 emitcode ("cpl", "a"); /* 2's complement */
4909 emitcode ("inc", "a");
4910 emitcode ("", "!tlabeldef", lbl->key + 100);
4914 /* now the multiplication */
4915 emitcode ("mul", "ab");
4916 _G.accInUse++;_G.bInUse++;
4917 aopOp(result, ic, TRUE, FALSE);
4918 size = AOP_SIZE (result);
4920 if (size < 1 || size > 2)
4922 /* this should never happen */
4923 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4924 size, __FILE__, lineno);
4928 if (runtimeSign || compiletimeSign)
4930 lbl = newiTempLabel (NULL);
4932 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
4933 emitcode ("cpl", "a"); /* lsb 2's complement */
4935 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4938 emitcode ("add", "a,#1"); /* this sets carry flag */
4939 emitcode ("xch", "a,b");
4940 emitcode ("cpl", "a"); /* msb 2's complement */
4941 emitcode ("addc", "a,#0");
4942 emitcode ("xch", "a,b");
4944 emitcode ("", "!tlabeldef", lbl->key + 100);
4946 aopPut (AOP (result), "a", 0);
4947 _G.accInUse--;_G.bInUse--;
4949 aopPut (AOP (result), "b", 1);
4952 /*-----------------------------------------------------------------*/
4953 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4954 /*-----------------------------------------------------------------*/
4955 static void genMultTwoByte (operand *left, operand *right,
4956 operand *result, iCode *ic)
4958 sym_link *retype = getSpec(operandType(right));
4959 sym_link *letype = getSpec(operandType(left));
4960 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4963 if (AOP_TYPE (left) == AOP_LIT) {
4968 /* save EA bit in F1 */
4969 lbl = newiTempLabel(NULL);
4970 emitcode ("setb","F1");
4971 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4972 emitcode ("clr","F1");
4973 emitcode("","!tlabeldef",lbl->key+100);
4975 /* load up MB with right */
4977 emitcode("clr","F0");
4978 if (AOP_TYPE(right) == AOP_LIT) {
4979 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4981 emitcode("setb","F0");
4984 emitcode ("mov","mb,#!constbyte",val & 0xff);
4985 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4987 lbl = newiTempLabel(NULL);
4988 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4989 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4990 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4991 emitcode ("xch", "a,b");
4992 emitcode ("cpl","a");
4993 emitcode ("add", "a,#1");
4994 emitcode ("xch", "a,b");
4995 emitcode ("cpl", "a"); // msb
4996 emitcode ("addc", "a,#0");
4997 emitcode ("setb","F0");
4998 emitcode ("","!tlabeldef",lbl->key+100);
4999 emitcode ("mov","mb,b");
5000 emitcode ("mov","mb,a");
5003 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5004 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5006 /* load up MA with left */
5008 lbl = newiTempLabel(NULL);
5009 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5010 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5011 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5012 emitcode ("xch", "a,b");
5013 emitcode ("cpl","a");
5014 emitcode ("add", "a,#1");
5015 emitcode ("xch", "a,b");
5016 emitcode ("cpl", "a"); // msb
5017 emitcode ("addc","a,#0");
5018 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5019 emitcode ("setb","F0");
5020 emitcode ("","!tlabeldef",lbl->key+100);
5021 emitcode ("mov","ma,b");
5022 emitcode ("mov","ma,a");
5024 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5025 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5027 /* wait for multiplication to finish */
5028 lbl = newiTempLabel(NULL);
5029 emitcode("","!tlabeldef", lbl->key+100);
5030 emitcode("mov","a,mcnt1");
5031 emitcode("anl","a,#!constbyte",0x80);
5032 emitcode("jnz","!tlabel",lbl->key+100);
5034 freeAsmop (left, NULL, ic, TRUE);
5035 freeAsmop (right, NULL, ic,TRUE);
5036 aopOp(result, ic, TRUE, FALSE);
5038 /* if unsigned then simple */
5040 emitcode ("mov","a,ma");
5041 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
5042 emitcode ("mov","a,ma");
5043 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
5044 aopPut(AOP(result),"ma",1);
5045 aopPut(AOP(result),"ma",0);
5047 emitcode("push","ma");
5048 emitcode("push","ma");
5049 emitcode("push","ma");
5051 /* negate result if needed */
5052 lbl = newiTempLabel(NULL);
5053 emitcode("jnb","F0,!tlabel",lbl->key+100);
5054 emitcode("cpl","a");
5055 emitcode("add","a,#1");
5056 emitcode("","!tlabeldef", lbl->key+100);
5057 if (AOP_TYPE(result) == AOP_ACC)
5059 D(emitcode(";", "ACC special case."););
5060 /* We know result is the only live aop, and
5061 * it's obviously not a DPTR2, so AP is available.
5063 emitcode("mov", "%s,acc", DP2_RESULT_REG);
5067 aopPut(AOP(result),"a",0);
5070 emitcode("pop","acc");
5071 lbl = newiTempLabel(NULL);
5072 emitcode("jnb","F0,!tlabel",lbl->key+100);
5073 emitcode("cpl","a");
5074 emitcode("addc","a,#0");
5075 emitcode("","!tlabeldef", lbl->key+100);
5076 aopPut(AOP(result),"a",1);
5077 emitcode("pop","acc");
5078 if (AOP_SIZE(result) >= 3) {
5079 lbl = newiTempLabel(NULL);
5080 emitcode("jnb","F0,!tlabel",lbl->key+100);
5081 emitcode("cpl","a");
5082 emitcode("addc","a,#0");
5083 emitcode("","!tlabeldef", lbl->key+100);
5084 aopPut(AOP(result),"a",2);
5086 emitcode("pop","acc");
5087 if (AOP_SIZE(result) >= 4) {
5088 lbl = newiTempLabel(NULL);
5089 emitcode("jnb","F0,!tlabel",lbl->key+100);
5090 emitcode("cpl","a");
5091 emitcode("addc","a,#0");
5092 emitcode("","!tlabeldef", lbl->key+100);
5093 aopPut(AOP(result),"a",3);
5095 if (AOP_TYPE(result) == AOP_ACC)
5097 /* We stashed the result away above. */
5098 emitcode("mov", "acc,%s", DP2_RESULT_REG);
5102 freeAsmop (result, NULL, ic, TRUE);
5104 /* restore EA bit in F1 */
5105 lbl = newiTempLabel(NULL);
5106 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5107 emitcode ("setb","EA");
5108 emitcode("","!tlabeldef",lbl->key+100);
5112 /*-----------------------------------------------------------------*/
5113 /* genMult - generates code for multiplication */
5114 /*-----------------------------------------------------------------*/
5116 genMult (iCode * ic)
5118 operand *left = IC_LEFT (ic);
5119 operand *right = IC_RIGHT (ic);
5120 operand *result = IC_RESULT (ic);
5122 D (emitcode (";", "genMult "););
5124 /* assign the amsops */
5127 /* special cases first */
5129 if (AOP_TYPE (left) == AOP_CRY &&
5130 AOP_TYPE (right) == AOP_CRY)
5132 genMultbits (left, right, result, ic);
5136 /* if both are of size == 1 */
5137 if (AOP_SIZE (left) == 1 &&
5138 AOP_SIZE (right) == 1)
5140 genMultOneByte (left, right, result, ic);
5144 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5145 /* use the ds390 ARITHMETIC accel UNIT */
5146 genMultTwoByte (left, right, result, ic);
5149 /* should have been converted to function call */
5153 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5154 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5155 freeAsmop (result, NULL, ic, TRUE);
5158 /*-----------------------------------------------------------------*/
5159 /* genDivbits :- division of bits */
5160 /*-----------------------------------------------------------------*/
5162 genDivbits (operand * left,
5170 /* the result must be bit */
5171 LOAD_AB_FOR_DIV (left, right, l);
5172 emitcode ("div", "ab");
5173 emitcode ("rrc", "a");
5174 aopOp(result, ic, TRUE, FALSE);
5176 aopPut (AOP (result), "c", 0);
5179 /*-----------------------------------------------------------------*/
5180 /* genDivOneByte : 8 bit division */
5181 /*-----------------------------------------------------------------*/
5183 genDivOneByte (operand * left,
5188 bool lUnsigned, rUnsigned;
5189 bool runtimeSign, compiletimeSign;
5195 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5196 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5198 /* signed or unsigned */
5199 if (lUnsigned && rUnsigned)
5201 /* unsigned is easy */
5202 LOAD_AB_FOR_DIV (left, right, l);
5203 emitcode ("div", "ab");
5206 aopOp (result, ic, TRUE, FALSE);
5207 aopPut (AOP (result), "a", 0);
5210 size = AOP_SIZE (result) - 1;
5213 aopPut (AOP (result), zero, offset++);
5217 /* signed is a little bit more difficult */
5219 /* now sign adjust for both left & right */
5221 /* let's see what's needed: */
5222 /* apply negative sign during runtime */
5223 runtimeSign = FALSE;
5224 /* negative sign from literals */
5225 compiletimeSign = FALSE;
5229 if (AOP_TYPE(left) == AOP_LIT)
5231 /* signed literal */
5232 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5234 compiletimeSign = TRUE;
5237 /* signed but not literal */
5243 if (AOP_TYPE(right) == AOP_LIT)
5245 /* signed literal */
5246 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5248 compiletimeSign ^= TRUE;
5251 /* signed but not literal */
5255 /* initialize F0, which stores the runtime sign */
5258 if (compiletimeSign)
5259 emitcode ("setb", "F0"); /* set sign flag */
5261 emitcode ("clr", "F0"); /* reset sign flag */
5264 /* save the signs of the operands */
5265 if (AOP_TYPE(right) == AOP_LIT)
5267 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5269 if (!rUnsigned && val < 0)
5270 emitcode ("mov", "b,#0x%02x", -val);
5272 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5274 else /* ! literal */
5277 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5280 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5281 lbl = newiTempLabel (NULL);
5282 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5283 emitcode ("cpl", "F0"); /* complement sign flag */
5284 emitcode ("cpl", "a"); /* 2's complement */
5285 emitcode ("inc", "a");
5286 emitcode ("", "!tlabeldef", lbl->key + 100);
5287 emitcode ("mov", "b,a");
5291 if (AOP_TYPE(left) == AOP_LIT)
5293 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5295 if (!lUnsigned && val < 0)
5296 emitcode ("mov", "a,#0x%02x", -val);
5298 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5300 else /* ! literal */
5303 emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5306 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5307 lbl = newiTempLabel (NULL);
5308 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5309 emitcode ("cpl", "F0"); /* complement sign flag */
5310 emitcode ("cpl", "a"); /* 2's complement */
5311 emitcode ("inc", "a");
5312 emitcode ("", "!tlabeldef", lbl->key + 100);
5316 /* now the division */
5317 emitcode ("nop", "; workaround for DS80C390 div bug.");
5318 emitcode ("div", "ab");
5320 if (runtimeSign || compiletimeSign)
5322 lbl = newiTempLabel (NULL);
5324 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5325 emitcode ("cpl", "a"); /* lsb 2's complement */
5326 emitcode ("inc", "a");
5327 emitcode ("", "!tlabeldef", lbl->key + 100);
5329 _G.accInUse++; _G.bInUse++;
5330 aopOp (result, ic, TRUE, FALSE);
5331 size = AOP_SIZE (result) - 1;
5335 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5336 then the result will be in b, a */
5337 emitcode ("mov", "b,a"); /* 1 */
5338 /* msb is 0x00 or 0xff depending on the sign */
5341 emitcode ("mov", "c,F0");
5342 emitcode ("subb", "a,acc");
5343 emitcode ("xch", "a,b"); /* 2 */
5345 aopPut (AOP (result), "b", offset++); /* write msb's */
5347 else /* compiletimeSign */
5349 aopPut (AOP (result), "#0xff", offset++); /* write msb's */
5351 aopPut (AOP (result), "a", 0); /* 3: write lsb */
5355 _G.accInUse++; _G.bInUse++;
5356 aopOp(result, ic, TRUE, FALSE);
5357 size = AOP_SIZE (result) - 1;
5359 aopPut (AOP (result), "a", 0);
5361 aopPut (AOP (result), zero, offset++);
5363 _G.accInUse--; _G.bInUse--;
5367 /*-----------------------------------------------------------------*/
5368 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
5369 /*-----------------------------------------------------------------*/
5370 static void genDivTwoByte (operand *left, operand *right,
5371 operand *result, iCode *ic)
5373 sym_link *retype = getSpec(operandType(right));
5374 sym_link *letype = getSpec(operandType(left));
5375 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5378 /* save EA bit in F1 */
5379 lbl = newiTempLabel(NULL);
5380 emitcode ("setb","F1");
5381 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5382 emitcode ("clr","F1");
5383 emitcode("","!tlabeldef",lbl->key+100);
5385 /* load up MA with left */
5387 emitcode("clr","F0");
5388 lbl = newiTempLabel(NULL);
5389 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5390 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5391 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5392 emitcode ("xch", "a,b");
5393 emitcode ("cpl","a");
5394 emitcode ("add", "a,#1");
5395 emitcode ("xch", "a,b");
5396 emitcode ("cpl", "a"); // msb
5397 emitcode ("addc","a,#0");
5398 emitcode ("setb","F0");
5399 emitcode ("","!tlabeldef",lbl->key+100);
5400 emitcode ("mov","ma,b");
5401 emitcode ("mov","ma,a");
5403 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5404 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5407 /* load up MB with right */
5409 if (AOP_TYPE(right) == AOP_LIT) {
5410 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5412 lbl = newiTempLabel(NULL);
5413 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5414 emitcode("setb","F0");
5415 emitcode ("","!tlabeldef",lbl->key+100);
5418 emitcode ("mov","mb,#!constbyte",val & 0xff);
5419 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5421 lbl = newiTempLabel(NULL);
5422 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5423 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5424 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5425 emitcode ("xch", "a,b");
5426 emitcode ("cpl","a");
5427 emitcode ("add", "a,#1");
5428 emitcode ("xch", "a,b");
5429 emitcode ("cpl", "a"); // msb
5430 emitcode ("addc", "a,#0");
5431 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5432 emitcode ("setb","F0");
5433 emitcode ("","!tlabeldef",lbl->key+100);
5434 emitcode ("mov","mb,b");
5435 emitcode ("mov","mb,a");
5438 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5439 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5442 /* wait for multiplication to finish */
5443 lbl = newiTempLabel(NULL);
5444 emitcode("","!tlabeldef", lbl->key+100);
5445 emitcode("mov","a,mcnt1");
5446 emitcode("anl","a,#!constbyte",0x80);
5447 emitcode("jnz","!tlabel",lbl->key+100);
5449 freeAsmop (left, NULL, ic, TRUE);
5450 freeAsmop (right, NULL, ic,TRUE);
5451 aopOp(result, ic, TRUE, FALSE);
5453 /* if unsigned then simple */
5455 aopPut(AOP(result),"ma",1);
5456 aopPut(AOP(result),"ma",0);
5458 emitcode("push","ma");
5460 /* negate result if needed */
5461 lbl = newiTempLabel(NULL);
5462 emitcode("jnb","F0,!tlabel",lbl->key+100);
5463 emitcode("cpl","a");
5464 emitcode("add","a,#1");
5465 emitcode("","!tlabeldef", lbl->key+100);
5466 aopPut(AOP(result),"a",0);
5467 emitcode("pop","acc");
5468 lbl = newiTempLabel(NULL);
5469 emitcode("jnb","F0,!tlabel",lbl->key+100);
5470 emitcode("cpl","a");
5471 emitcode("addc","a,#0");
5472 emitcode("","!tlabeldef", lbl->key+100);
5473 aopPut(AOP(result),"a",1);
5475 freeAsmop (result, NULL, ic, TRUE);
5476 /* restore EA bit in F1 */
5477 lbl = newiTempLabel(NULL);
5478 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5479 emitcode ("setb","EA");
5480 emitcode("","!tlabeldef",lbl->key+100);
5484 /*-----------------------------------------------------------------*/
5485 /* genDiv - generates code for division */
5486 /*-----------------------------------------------------------------*/
5490 operand *left = IC_LEFT (ic);
5491 operand *right = IC_RIGHT (ic);
5492 operand *result = IC_RESULT (ic);
5494 D (emitcode (";", "genDiv "););
5496 /* assign the amsops */
5499 /* special cases first */
5501 if (AOP_TYPE (left) == AOP_CRY &&
5502 AOP_TYPE (right) == AOP_CRY)
5504 genDivbits (left, right, result, ic);
5508 /* if both are of size == 1 */
5509 if (AOP_SIZE (left) == 1 &&
5510 AOP_SIZE (right) == 1)
5512 genDivOneByte (left, right, result, ic);
5516 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5517 /* use the ds390 ARITHMETIC accel UNIT */
5518 genDivTwoByte (left, right, result, ic);
5521 /* should have been converted to function call */
5524 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5525 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5526 freeAsmop (result, NULL, ic, TRUE);
5529 /*-----------------------------------------------------------------*/
5530 /* genModbits :- modulus of bits */
5531 /*-----------------------------------------------------------------*/
5533 genModbits (operand * left,
5541 /* the result must be bit */
5542 LOAD_AB_FOR_DIV (left, right, l);
5543 emitcode ("div", "ab");
5544 emitcode ("mov", "a,b");
5545 emitcode ("rrc", "a");
5546 aopOp(result, ic, TRUE, FALSE);
5547 aopPut (AOP (result), "c", 0);
5550 /*-----------------------------------------------------------------*/
5551 /* genModOneByte : 8 bit modulus */
5552 /*-----------------------------------------------------------------*/
5554 genModOneByte (operand * left,
5559 bool lUnsigned, rUnsigned;
5560 bool runtimeSign, compiletimeSign;
5566 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5567 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5569 /* signed or unsigned */
5570 if (lUnsigned && rUnsigned)
5572 /* unsigned is easy */
5573 LOAD_AB_FOR_DIV (left, right, l);
5574 emitcode ("div", "ab");
5575 aopOp (result, ic, TRUE, FALSE);
5576 aopPut (AOP (result), "b", 0);
5578 for (size = AOP_SIZE (result) - 1; size--;)
5579 aopPut (AOP (result), zero, offset++);
5583 /* signed is a little bit more difficult */
5585 /* now sign adjust for both left & right */
5587 /* modulus: sign of the right operand has no influence on the result! */
5588 if (AOP_TYPE(right) == AOP_LIT)
5590 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5592 if (!rUnsigned && val < 0)
5593 emitcode ("mov", "b,#0x%02x", -val);
5595 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5597 else /* ! literal */
5600 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5603 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5604 lbl = newiTempLabel (NULL);
5605 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5606 emitcode ("cpl", "a"); /* 2's complement */
5607 emitcode ("inc", "a");
5608 emitcode ("", "!tlabeldef", lbl->key + 100);
5609 emitcode ("mov", "b,a");
5613 /* let's see what's needed: */
5614 /* apply negative sign during runtime */
5615 runtimeSign = FALSE;
5616 /* negative sign from literals */
5617 compiletimeSign = FALSE;
5619 /* sign adjust left side */
5620 if (AOP_TYPE(left) == AOP_LIT)
5622 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5624 if (!lUnsigned && val < 0)
5626 compiletimeSign = TRUE; /* set sign flag */
5627 emitcode ("mov", "a,#0x%02x", -val);
5630 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5632 else /* ! literal */
5634 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5639 emitcode ("clr", "F0"); /* clear sign flag */
5641 lbl = newiTempLabel (NULL);
5642 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5643 emitcode ("setb", "F0"); /* set sign flag */
5644 emitcode ("cpl", "a"); /* 2's complement */
5645 emitcode ("inc", "a");
5646 emitcode ("", "!tlabeldef", lbl->key + 100);
5650 /* now the modulus */
5651 emitcode ("nop", "; workaround for DS80C390 div bug.");
5652 emitcode ("div", "ab");
5654 if (runtimeSign || compiletimeSign)
5656 emitcode ("mov", "a,b");
5657 lbl = newiTempLabel (NULL);
5659 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5660 emitcode ("cpl", "a"); /* lsb 2's complement */
5661 emitcode ("inc", "a");
5662 emitcode ("", "!tlabeldef", lbl->key + 100);
5664 _G.accInUse++; _G.bInUse++;
5665 aopOp (result, ic, TRUE, FALSE);
5666 size = AOP_SIZE (result) - 1;
5670 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5671 then the result will be in b, a */
5672 emitcode ("mov", "b,a"); /* 1 */
5673 /* msb is 0x00 or 0xff depending on the sign */
5676 emitcode ("mov", "c,F0");
5677 emitcode ("subb", "a,acc");
5678 emitcode ("xch", "a,b"); /* 2 */
5680 aopPut (AOP (result), "b", offset++); /* write msb's */
5682 else /* compiletimeSign */
5684 aopPut (AOP (result), "#0xff", offset++); /* write msb's */
5686 aopPut (AOP (result), "a", 0); /* 3: write lsb */
5690 _G.accInUse++; _G.bInUse++;
5691 aopOp(result, ic, TRUE, FALSE);
5692 size = AOP_SIZE (result) - 1;
5694 aopPut (AOP (result), "b", 0);
5696 aopPut (AOP (result), zero, offset++);
5698 _G.accInUse--; _G.bInUse--;
5702 /*-----------------------------------------------------------------*/
5703 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
5704 /*-----------------------------------------------------------------*/
5705 static void genModTwoByte (operand *left, operand *right,
5706 operand *result, iCode *ic)
5708 sym_link *retype = getSpec(operandType(right));
5709 sym_link *letype = getSpec(operandType(left));
5710 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5713 /* load up MA with left */
5714 /* save EA bit in F1 */
5715 lbl = newiTempLabel(NULL);
5716 emitcode ("setb","F1");
5717 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5718 emitcode ("clr","F1");
5719 emitcode("","!tlabeldef",lbl->key+100);
5722 lbl = newiTempLabel(NULL);
5723 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5724 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5725 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5726 emitcode ("xch", "a,b");
5727 emitcode ("cpl","a");
5728 emitcode ("add", "a,#1");
5729 emitcode ("xch", "a,b");
5730 emitcode ("cpl", "a"); // msb
5731 emitcode ("addc","a,#0");
5732 emitcode ("","!tlabeldef",lbl->key+100);
5733 emitcode ("mov","ma,b");
5734 emitcode ("mov","ma,a");
5736 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5737 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5740 /* load up MB with right */
5742 if (AOP_TYPE(right) == AOP_LIT) {
5743 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5747 emitcode ("mov","mb,#!constbyte",val & 0xff);
5748 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5750 lbl = newiTempLabel(NULL);
5751 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5752 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5753 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5754 emitcode ("xch", "a,b");
5755 emitcode ("cpl","a");
5756 emitcode ("add", "a,#1");
5757 emitcode ("xch", "a,b");
5758 emitcode ("cpl", "a"); // msb
5759 emitcode ("addc", "a,#0");
5760 emitcode ("","!tlabeldef",lbl->key+100);
5761 emitcode ("mov","mb,b");
5762 emitcode ("mov","mb,a");
5765 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5766 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5769 /* wait for multiplication to finish */
5770 lbl = newiTempLabel(NULL);
5771 emitcode("","!tlabeldef", lbl->key+100);
5772 emitcode("mov","a,mcnt1");
5773 emitcode("anl","a,#!constbyte",0x80);
5774 emitcode("jnz","!tlabel",lbl->key+100);
5776 freeAsmop (left, NULL, ic, TRUE);
5777 freeAsmop (right, NULL, ic,TRUE);
5778 aopOp(result, ic, TRUE, FALSE);
5780 aopPut(AOP(result),"mb",1);
5781 aopPut(AOP(result),"mb",0);
5782 freeAsmop (result, NULL, ic, TRUE);
5784 /* restore EA bit in F1 */
5785 lbl = newiTempLabel(NULL);
5786 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5787 emitcode ("setb","EA");
5788 emitcode("","!tlabeldef",lbl->key+100);
5792 /*-----------------------------------------------------------------*/
5793 /* genMod - generates code for division */
5794 /*-----------------------------------------------------------------*/
5798 operand *left = IC_LEFT (ic);
5799 operand *right = IC_RIGHT (ic);
5800 operand *result = IC_RESULT (ic);
5802 D (emitcode (";", "genMod "); );
5804 /* assign the amsops */
5807 /* special cases first */
5809 if (AOP_TYPE (left) == AOP_CRY &&
5810 AOP_TYPE (right) == AOP_CRY)
5812 genModbits (left, right, result, ic);
5816 /* if both are of size == 1 */
5817 if (AOP_SIZE (left) == 1 &&
5818 AOP_SIZE (right) == 1)
5820 genModOneByte (left, right, result, ic);
5824 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5825 /* use the ds390 ARITHMETIC accel UNIT */
5826 genModTwoByte (left, right, result, ic);
5830 /* should have been converted to function call */
5834 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5835 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5836 freeAsmop (result, NULL, ic, TRUE);
5839 /*-----------------------------------------------------------------*/
5840 /* genIfxJump :- will create a jump depending on the ifx */
5841 /*-----------------------------------------------------------------*/
5843 genIfxJump (iCode * ic, char *jval)
5846 symbol *tlbl = newiTempLabel (NULL);
5849 D (emitcode (";", "genIfxJump"););
5851 /* if true label then we jump if condition
5855 jlbl = IC_TRUE (ic);
5856 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5857 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5861 /* false label is present */
5862 jlbl = IC_FALSE (ic);
5863 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5864 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5866 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5867 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5869 emitcode (inst, "!tlabel", tlbl->key + 100);
5870 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5871 emitcode ("", "!tlabeldef", tlbl->key + 100);
5873 /* mark the icode as generated */
5877 /*-----------------------------------------------------------------*/
5878 /* genCmp :- greater or less than comparison */
5879 /*-----------------------------------------------------------------*/
5881 genCmp (operand * left, operand * right,
5882 iCode * ic, iCode * ifx, int sign)
5884 int size, offset = 0;
5885 unsigned long lit = 0L;
5888 D (emitcode (";", "genCmp"););
5890 result = IC_RESULT (ic);
5892 /* if left & right are bit variables */
5893 if (AOP_TYPE (left) == AOP_CRY &&
5894 AOP_TYPE (right) == AOP_CRY)
5896 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5897 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5901 /* subtract right from left if at the
5902 end the carry flag is set then we know that
5903 left is greater than right */
5904 size = max (AOP_SIZE (left), AOP_SIZE (right));
5906 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5907 if ((size == 1) && !sign
5908 && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5910 symbol *lbl = newiTempLabel (NULL);
5911 emitcode ("cjne", "%s,%s,!tlabel",
5912 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5913 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5915 emitcode ("", "!tlabeldef", lbl->key + 100);
5919 if (AOP_TYPE (right) == AOP_LIT)
5921 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5922 /* optimize if(x < 0) or if(x >= 0) */
5931 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5933 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5934 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5936 aopOp (result, ic, FALSE, FALSE);
5938 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5940 freeAsmop (result, NULL, ic, TRUE);
5941 genIfxJump (ifx, "acc.7");
5946 emitcode ("rlc", "a");
5948 goto release_freedLR;
5956 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5957 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5958 // emitcode (";", "genCmp #2");
5959 if (sign && (size == 0))
5961 // emitcode (";", "genCmp #3");
5962 emitcode ("xrl", "a,#!constbyte",0x80);
5963 if (AOP_TYPE (right) == AOP_LIT)
5965 unsigned long lit = (unsigned long)
5966 floatFromVal (AOP (right)->aopu.aop_lit);
5967 // emitcode (";", "genCmp #3.1");
5968 emitcode ("subb", "a,#!constbyte",
5969 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5973 // emitcode (";", "genCmp #3.2");
5975 MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5976 saveAccWarn = DEFAULT_ACC_WARNING;
5977 emitcode ("xrl", "b,#!constbyte",0x80);
5978 emitcode ("subb", "a,b");
5985 // emitcode (";", "genCmp #4");
5987 s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5988 saveAccWarn = DEFAULT_ACC_WARNING;
5990 emitcode ("subb", "a,%s", s);
5997 /* Don't need the left & right operands any more; do need the result. */
5998 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5999 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6001 aopOp (result, ic, FALSE, FALSE);
6005 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6011 /* if the result is used in the next
6012 ifx conditional branch then generate
6013 code a little differently */
6016 genIfxJump (ifx, "c");
6022 /* leave the result in acc */
6024 freeAsmop (result, NULL, ic, TRUE);
6027 /*-----------------------------------------------------------------*/
6028 /* genCmpGt :- greater than comparison */
6029 /*-----------------------------------------------------------------*/
6031 genCmpGt (iCode * ic, iCode * ifx)
6033 operand *left, *right;
6034 sym_link *letype, *retype;
6037 D (emitcode (";", "genCmpGt ");
6040 left = IC_LEFT (ic);
6041 right = IC_RIGHT (ic);
6043 letype = getSpec (operandType (left));
6044 retype = getSpec (operandType (right));
6045 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6047 /* assign the left & right amsops */
6050 genCmp (right, left, ic, ifx, sign);
6053 /*-----------------------------------------------------------------*/
6054 /* genCmpLt - less than comparisons */
6055 /*-----------------------------------------------------------------*/
6057 genCmpLt (iCode * ic, iCode * ifx)
6059 operand *left, *right;
6060 sym_link *letype, *retype;
6063 D (emitcode (";", "genCmpLt "););
6065 left = IC_LEFT (ic);
6066 right = IC_RIGHT (ic);
6068 letype = getSpec (operandType (left));
6069 retype = getSpec (operandType (right));
6070 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6072 /* assign the left & right amsops */
6075 genCmp (left, right, ic, ifx, sign);
6078 /*-----------------------------------------------------------------*/
6079 /* gencjneshort - compare and jump if not equal */
6080 /*-----------------------------------------------------------------*/
6082 gencjneshort (operand * left, operand * right, symbol * lbl)
6084 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6086 unsigned long lit = 0L;
6088 D (emitcode (";", "gencjneshort");
6091 /* if the left side is a literal or
6092 if the right is in a pointer register and left
6094 if ((AOP_TYPE (left) == AOP_LIT) ||
6095 (AOP_TYPE (left) == AOP_IMMD) ||
6096 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6103 if (AOP_TYPE (right) == AOP_LIT)
6104 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6106 if (opIsGptr (left) || opIsGptr (right))
6108 /* We are comparing a generic pointer to something.
6109 * Exclude the generic type byte from the comparison.
6112 D (emitcode (";", "cjneshort: generic ptr special case."););
6116 /* if the right side is a literal then anything goes */
6117 if (AOP_TYPE (right) == AOP_LIT &&
6118 AOP_TYPE (left) != AOP_DIR)
6122 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6123 emitcode ("cjne", "a,%s,!tlabel",
6124 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
6130 /* if the right side is in a register or in direct space or
6131 if the left is a pointer register & right is not */
6132 else if (AOP_TYPE (right) == AOP_REG ||
6133 AOP_TYPE (right) == AOP_DIR ||
6134 AOP_TYPE (right) == AOP_LIT ||
6135 AOP_TYPE (right) == AOP_IMMD ||
6136 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6137 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6141 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6142 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6143 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6144 emitcode ("jnz", "!tlabel", lbl->key + 100);
6146 emitcode ("cjne", "a,%s,!tlabel",
6147 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
6154 /* right is a pointer reg need both a & b */
6157 MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6158 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6159 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
6165 /*-----------------------------------------------------------------*/
6166 /* gencjne - compare and jump if not equal */
6167 /*-----------------------------------------------------------------*/
6169 gencjne (operand * left, operand * right, symbol * lbl)
6171 symbol *tlbl = newiTempLabel (NULL);
6173 D (emitcode (";", "gencjne");
6176 gencjneshort (left, right, lbl);
6178 emitcode ("mov", "a,%s", one);
6179 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
6180 emitcode ("", "!tlabeldef", lbl->key + 100);
6181 emitcode ("clr", "a");
6182 emitcode ("", "!tlabeldef", tlbl->key + 100);
6185 /*-----------------------------------------------------------------*/
6186 /* genCmpEq - generates code for equal to */
6187 /*-----------------------------------------------------------------*/
6189 genCmpEq (iCode * ic, iCode * ifx)
6191 operand *left, *right, *result;
6193 D (emitcode (";", "genCmpEq ");
6197 AOP_SET_LOCALS (ic);
6199 /* if literal, literal on the right or
6200 if the right is in a pointer register and left
6202 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6203 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6205 operand *t = IC_RIGHT (ic);
6206 IC_RIGHT (ic) = IC_LEFT (ic);
6210 if (ifx && /* !AOP_SIZE(result) */
6211 OP_SYMBOL (result) &&
6212 OP_SYMBOL (result)->regType == REG_CND)
6215 /* if they are both bit variables */
6216 if (AOP_TYPE (left) == AOP_CRY &&
6217 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6219 if (AOP_TYPE (right) == AOP_LIT)
6221 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6224 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6225 emitcode ("cpl", "c");
6229 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6233 emitcode ("clr", "c");
6235 /* AOP_TYPE(right) == AOP_CRY */
6239 symbol *lbl = newiTempLabel (NULL);
6240 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6241 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6242 emitcode ("cpl", "c");
6243 emitcode ("", "!tlabeldef", (lbl->key + 100));
6245 /* if true label then we jump if condition
6247 tlbl = newiTempLabel (NULL);
6250 emitcode ("jnc", "!tlabel", tlbl->key + 100);
6251 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6255 emitcode ("jc", "!tlabel", tlbl->key + 100);
6256 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6258 emitcode ("", "!tlabeldef", tlbl->key + 100);
6262 tlbl = newiTempLabel (NULL);
6263 gencjneshort (left, right, tlbl);
6266 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6267 emitcode ("", "!tlabeldef", tlbl->key + 100);
6271 symbol *lbl = newiTempLabel (NULL);
6272 emitcode ("sjmp", "!tlabel", lbl->key + 100);
6273 emitcode ("", "!tlabeldef", tlbl->key + 100);
6274 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6275 emitcode ("", "!tlabeldef", lbl->key + 100);
6278 /* mark the icode as generated */
6281 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6282 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6286 /* if they are both bit variables */
6287 if (AOP_TYPE (left) == AOP_CRY &&
6288 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6290 if (AOP_TYPE (right) == AOP_LIT)
6292 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6295 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6296 emitcode ("cpl", "c");
6300 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6304 emitcode ("clr", "c");
6306 /* AOP_TYPE(right) == AOP_CRY */
6310 symbol *lbl = newiTempLabel (NULL);
6311 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6312 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6313 emitcode ("cpl", "c");
6314 emitcode ("", "!tlabeldef", (lbl->key + 100));
6317 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6318 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6320 aopOp (result, ic, TRUE, FALSE);
6323 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6330 genIfxJump (ifx, "c");
6333 /* if the result is used in an arithmetic operation
6334 then put the result in place */
6339 gencjne (left, right, newiTempLabel (NULL));
6341 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6342 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6344 aopOp (result, ic, TRUE, FALSE);
6346 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6348 aopPut (AOP (result), "a", 0);
6353 genIfxJump (ifx, "a");
6356 /* if the result is used in an arithmetic operation
6357 then put the result in place */
6358 if (AOP_TYPE (result) != AOP_CRY)
6360 /* leave the result in acc */
6364 freeAsmop (result, NULL, ic, TRUE);
6367 /*-----------------------------------------------------------------*/
6368 /* ifxForOp - returns the icode containing the ifx for operand */
6369 /*-----------------------------------------------------------------*/
6371 ifxForOp (operand * op, iCode * ic)
6373 /* if true symbol then needs to be assigned */
6374 if (IS_TRUE_SYMOP (op))
6377 /* if this has register type condition and
6378 the next instruction is ifx with the same operand
6379 and live to of the operand is upto the ifx only then */
6381 ic->next->op == IFX &&
6382 IC_COND (ic->next)->key == op->key &&
6383 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6388 /*-----------------------------------------------------------------*/
6389 /* hasInc - operand is incremented before any other use */
6390 /*-----------------------------------------------------------------*/
6392 hasInc (operand *op, iCode *ic, int osize)
6394 sym_link *type = operandType(op);
6395 sym_link *retype = getSpec (type);
6396 iCode *lic = ic->next;
6399 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6400 if (!IS_SYMOP(op)) return NULL;
6402 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6403 if (IS_AGGREGATE(type->next)) return NULL;
6404 if (osize != (isize = getSize(type->next))) return NULL;
6407 /* if operand of the form op = op + <sizeof *op> */
6408 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6409 isOperandEqual(IC_RESULT(lic),op) &&
6410 isOperandLiteral(IC_RIGHT(lic)) &&
6411 operandLitValue(IC_RIGHT(lic)) == isize) {
6414 /* if the operand used or deffed */
6415 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6418 /* if GOTO or IFX */
6419 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6425 /*-----------------------------------------------------------------*/
6426 /* genAndOp - for && operation */
6427 /*-----------------------------------------------------------------*/
6429 genAndOp (iCode * ic)
6431 operand *left, *right, *result;
6434 D (emitcode (";", "genAndOp "););
6436 /* note here that && operations that are in an
6437 if statement are taken away by backPatchLabels
6438 only those used in arthmetic operations remain */
6440 AOP_SET_LOCALS (ic);
6442 /* if both are bit variables */
6443 if (AOP_TYPE (left) == AOP_CRY &&
6444 AOP_TYPE (right) == AOP_CRY)
6446 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6447 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6448 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6449 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6451 aopOp (result,ic,FALSE, FALSE);
6456 tlbl = newiTempLabel (NULL);
6458 emitcode ("jz", "!tlabel", tlbl->key + 100);
6460 emitcode ("", "!tlabeldef", tlbl->key + 100);
6461 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6462 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6464 aopOp (result,ic,FALSE, FALSE);
6467 freeAsmop (result, NULL, ic, TRUE);
6471 /*-----------------------------------------------------------------*/
6472 /* genOrOp - for || operation */
6473 /*-----------------------------------------------------------------*/
6475 genOrOp (iCode * ic)
6477 operand *left, *right, *result;
6480 D (emitcode (";", "genOrOp "););
6482 /* note here that || operations that are in an
6483 if statement are taken away by backPatchLabels
6484 only those used in arthmetic operations remain */
6486 AOP_SET_LOCALS (ic);
6488 /* if both are bit variables */
6489 if (AOP_TYPE (left) == AOP_CRY &&
6490 AOP_TYPE (right) == AOP_CRY)
6492 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6493 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6494 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6495 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6497 aopOp (result,ic,FALSE, FALSE);
6503 tlbl = newiTempLabel (NULL);
6505 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6507 emitcode ("", "!tlabeldef", tlbl->key + 100);
6508 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6509 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6511 aopOp (result,ic,FALSE, FALSE);
6516 freeAsmop (result, NULL, ic, TRUE);
6519 /*-----------------------------------------------------------------*/
6520 /* isLiteralBit - test if lit == 2^n */
6521 /*-----------------------------------------------------------------*/
6523 isLiteralBit (unsigned long lit)
6525 unsigned long pw[32] =
6526 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6527 0x100L, 0x200L, 0x400L, 0x800L,
6528 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6529 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6530 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6531 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6532 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6535 for (idx = 0; idx < 32; idx++)
6541 /*-----------------------------------------------------------------*/
6542 /* continueIfTrue - */
6543 /*-----------------------------------------------------------------*/
6545 continueIfTrue (iCode * ic)
6548 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6552 /*-----------------------------------------------------------------*/
6554 /*-----------------------------------------------------------------*/
6556 jumpIfTrue (iCode * ic)
6559 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6563 /*-----------------------------------------------------------------*/
6564 /* jmpTrueOrFalse - */
6565 /*-----------------------------------------------------------------*/
6567 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6569 // ugly but optimized by peephole
6572 symbol *nlbl = newiTempLabel (NULL);
6573 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6574 emitcode ("", "!tlabeldef", tlbl->key + 100);
6575 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6576 emitcode ("", "!tlabeldef", nlbl->key + 100);
6580 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6581 emitcode ("", "!tlabeldef", tlbl->key + 100);
6586 // Generate code to perform a bit-wise logic operation
6587 // on two operands in far space (assumed to already have been
6588 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6589 // in far space. This requires pushing the result on the stack
6590 // then popping it into the result.
6592 genFarFarLogicOp(iCode *ic, char *logicOp)
6594 int size, resultSize, compSize;
6598 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6599 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
6600 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6602 _startLazyDPSEvaluation();
6603 for (size = compSize; (size--); offset++)
6605 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6606 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6607 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6609 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6610 emitcode ("push", "acc");
6612 _endLazyDPSEvaluation();
6614 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6615 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6616 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6618 resultSize = AOP_SIZE(IC_RESULT(ic));
6620 ADJUST_PUSHED_RESULT(compSize, resultSize);
6622 _startLazyDPSEvaluation();
6625 emitcode ("pop", "acc");
6626 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6628 _endLazyDPSEvaluation();
6629 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6633 /*-----------------------------------------------------------------*/
6634 /* genAnd - code for and */
6635 /*-----------------------------------------------------------------*/
6637 genAnd (iCode * ic, iCode * ifx)
6639 operand *left, *right, *result;
6640 int size, offset = 0;
6641 unsigned long lit = 0L;
6646 D (emitcode (";", "genAnd "););
6648 AOP_OP_3_NOFATAL (ic, pushResult);
6649 AOP_SET_LOCALS (ic);
6653 genFarFarLogicOp(ic, "anl");
6658 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6660 AOP_TYPE (left), AOP_TYPE (right));
6661 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6663 AOP_SIZE (left), AOP_SIZE (right));
6666 /* if left is a literal & right is not then exchange them */
6667 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6668 #ifdef LOGIC_OPS_BROKEN
6669 || AOP_NEEDSACC (left)
6673 operand *tmp = right;
6678 /* if result = right then exchange left and right */
6679 if (sameRegs (AOP (result), AOP (right)))
6681 operand *tmp = right;
6686 /* if right is bit then exchange them */
6687 if (AOP_TYPE (right) == AOP_CRY &&
6688 AOP_TYPE (left) != AOP_CRY)
6690 operand *tmp = right;
6694 if (AOP_TYPE (right) == AOP_LIT)
6695 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6697 size = AOP_SIZE (result);
6700 // result = bit & yy;
6701 if (AOP_TYPE (left) == AOP_CRY)
6703 // c = bit & literal;
6704 if (AOP_TYPE (right) == AOP_LIT)
6708 if (size && sameRegs (AOP (result), AOP (left)))
6711 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6716 if (size && (AOP_TYPE (result) == AOP_CRY))
6718 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6721 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6726 emitcode ("clr", "c");
6731 if (AOP_TYPE (right) == AOP_CRY)
6734 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6735 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6740 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6742 emitcode ("rrc", "a");
6743 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6751 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6752 genIfxJump (ifx, "c");
6756 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6757 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6758 if ((AOP_TYPE (right) == AOP_LIT) &&
6759 (AOP_TYPE (result) == AOP_CRY) &&
6760 (AOP_TYPE (left) != AOP_CRY))
6762 int posbit = isLiteralBit (lit);
6767 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6770 emitcode ("mov", "c,acc.%d", posbit & 0x07);
6776 SNPRINTF (buff, sizeof(buff),
6777 "acc.%d", posbit & 0x07);
6778 genIfxJump (ifx, buff);
6782 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6789 symbol *tlbl = newiTempLabel (NULL);
6790 int sizel = AOP_SIZE (left);
6792 emitcode ("setb", "c");
6795 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6797 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6799 if ((posbit = isLiteralBit (bytelit)) != 0)
6800 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6803 if (bytelit != 0x0FFL)
6804 emitcode ("anl", "a,%s",
6805 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6806 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6811 // bit = left & literal
6814 emitcode ("clr", "c");
6815 emitcode ("", "!tlabeldef", tlbl->key + 100);
6817 // if(left & literal)
6821 jmpTrueOrFalse (ifx, tlbl);
6823 emitcode ("", "!tlabeldef", tlbl->key + 100);
6831 /* if left is same as result */
6832 if (sameRegs (AOP (result), AOP (left)))
6834 for (; size--; offset++)
6836 if (AOP_TYPE (right) == AOP_LIT)
6838 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6839 if (bytelit == 0x0FF)
6841 /* dummy read of volatile operand */
6842 if (isOperandVolatile (left, FALSE))
6843 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6847 else if (bytelit == 0)
6849 aopPut (AOP (result), zero, offset);
6851 else if (IS_AOP_PREG (result))
6853 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6854 emitcode ("anl", "a,%s",
6855 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6856 aopPut (AOP (result), "a", offset);
6859 emitcode ("anl", "%s,%s",
6860 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6861 aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6865 if (AOP_TYPE (left) == AOP_ACC)
6866 emitcode ("anl", "a,%s",
6867 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6870 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6871 if (IS_AOP_PREG (result))
6873 emitcode ("anl", "a,%s",
6874 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6875 aopPut (AOP (result), "a", offset);
6878 emitcode ("anl", "%s,a",
6879 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6886 // left & result in different registers
6887 if (AOP_TYPE (result) == AOP_CRY)
6890 // if(size), result in bit
6891 // if(!size && ifx), conditional oper: if(left & right)
6892 symbol *tlbl = newiTempLabel (NULL);
6893 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6895 emitcode ("setb", "c");
6898 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6899 emitcode ("anl", "a,%s",
6900 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6902 if (AOP_TYPE(left)==AOP_ACC) {
6903 emitcode("mov", "b,a");
6904 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6905 emitcode("anl", "a,b");
6907 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6908 emitcode ("anl", "a,%s",
6909 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6912 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6918 emitcode ("", "!tlabeldef", tlbl->key + 100);
6922 jmpTrueOrFalse (ifx, tlbl);
6924 emitcode ("", "!tlabeldef", tlbl->key + 100);
6928 for (; (size--); offset++)
6931 // result = left & right
6932 if (AOP_TYPE (right) == AOP_LIT)
6934 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6935 if (bytelit == 0x0FF)
6937 aopPut (AOP (result),
6938 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6942 else if (bytelit == 0)
6944 /* dummy read of volatile operand */
6945 if (isOperandVolatile (left, FALSE))
6946 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6947 aopPut (AOP (result), zero, offset);
6950 D (emitcode (";", "better literal AND."););
6951 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6952 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6953 FALSE, FALSE, DP2_RESULT_REG));
6958 // faster than result <- left, anl result,right
6959 // and better if result is SFR
6960 if (AOP_TYPE (left) == AOP_ACC)
6962 emitcode ("anl", "a,%s",
6963 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6967 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6968 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6970 emitcode("mov", "b,a");
6974 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6975 emitcode ("anl", "a,%s", rOp);
6978 aopPut (AOP (result), "a", offset);
6984 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6985 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6986 freeAsmop (result, NULL, ic, TRUE);
6990 /*-----------------------------------------------------------------*/
6991 /* genOr - code for or */
6992 /*-----------------------------------------------------------------*/
6994 genOr (iCode * ic, iCode * ifx)
6996 operand *left, *right, *result;
6997 int size, offset = 0;
6998 unsigned long lit = 0L;
7002 D (emitcode (";", "genOr "););
7004 AOP_OP_3_NOFATAL (ic, pushResult);
7005 AOP_SET_LOCALS (ic);
7009 genFarFarLogicOp(ic, "orl");
7015 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7017 AOP_TYPE (left), AOP_TYPE (right));
7018 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7020 AOP_SIZE (left), AOP_SIZE (right));
7023 /* if left is a literal & right is not then exchange them */
7024 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7025 #ifdef LOGIC_OPS_BROKEN
7026 || AOP_NEEDSACC (left) // I think this is a net loss now.
7030 operand *tmp = right;
7035 /* if result = right then exchange them */
7036 if (sameRegs (AOP (result), AOP (right)))
7038 operand *tmp = right;
7043 /* if right is bit then exchange them */
7044 if (AOP_TYPE (right) == AOP_CRY &&
7045 AOP_TYPE (left) != AOP_CRY)
7047 operand *tmp = right;
7051 if (AOP_TYPE (right) == AOP_LIT)
7052 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7054 size = AOP_SIZE (result);
7058 if (AOP_TYPE (left) == AOP_CRY)
7060 if (AOP_TYPE (right) == AOP_LIT)
7062 // c = bit & literal;
7065 // lit != 0 => result = 1
7066 if (AOP_TYPE (result) == AOP_CRY)
7069 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7071 continueIfTrue (ifx);
7074 emitcode ("setb", "c");
7078 // lit == 0 => result = left
7079 if (size && sameRegs (AOP (result), AOP (left)))
7081 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7086 if (AOP_TYPE (right) == AOP_CRY)
7089 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7090 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7095 symbol *tlbl = newiTempLabel (NULL);
7096 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7097 emitcode ("setb", "c");
7098 emitcode ("jb", "%s,!tlabel",
7099 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7101 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7102 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7104 jmpTrueOrFalse (ifx, tlbl);
7110 emitcode ("", "!tlabeldef", tlbl->key + 100);
7119 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7120 genIfxJump (ifx, "c");
7124 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7125 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7126 if ((AOP_TYPE (right) == AOP_LIT) &&
7127 (AOP_TYPE (result) == AOP_CRY) &&
7128 (AOP_TYPE (left) != AOP_CRY))
7134 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7136 continueIfTrue (ifx);
7141 // lit = 0, result = boolean(left)
7143 emitcode ("setb", "c");
7147 symbol *tlbl = newiTempLabel (NULL);
7148 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7150 emitcode ("", "!tlabeldef", tlbl->key + 100);
7154 genIfxJump (ifx, "a");
7162 /* if left is same as result */
7163 if (sameRegs (AOP (result), AOP (left)))
7165 for (; size--; offset++)
7167 if (AOP_TYPE (right) == AOP_LIT)
7169 bytelit = (int)((lit >> (offset * 8)) & 0x0FFL);
7170 if (bytelit == 0x00L)
7172 /* dummy read of volatile operand */
7173 if (isOperandVolatile (left, FALSE))
7174 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7178 else if (bytelit == 0x0FF)
7180 aopPut (AOP (result), "#0xFF", offset);
7182 else if (IS_AOP_PREG (left))
7184 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7185 emitcode ("orl", "a,%s",
7186 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7187 aopPut (AOP (result), "a", offset);
7191 emitcode ("orl", "%s,%s",
7192 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7193 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7198 if (AOP_TYPE (left) == AOP_ACC)
7200 emitcode ("orl", "a,%s",
7201 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7205 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7206 if (IS_AOP_PREG (left))
7208 emitcode ("orl", "a,%s",
7209 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7210 aopPut (AOP (result), "a", offset);
7214 emitcode ("orl", "%s,a",
7215 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7223 // left & result in different registers
7224 if (AOP_TYPE (result) == AOP_CRY)
7227 // if(size), result in bit
7228 // if(!size && ifx), conditional oper: if(left | right)
7229 symbol *tlbl = newiTempLabel (NULL);
7230 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7232 emitcode ("setb", "c");
7235 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7236 emitcode ("orl", "a,%s",
7237 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7239 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7240 emitcode ("orl", "a,%s",
7241 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
7243 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7249 emitcode ("", "!tlabeldef", tlbl->key + 100);
7253 jmpTrueOrFalse (ifx, tlbl);
7255 emitcode ("", "!tlabeldef", tlbl->key + 100);
7259 _startLazyDPSEvaluation();
7260 for (; (size--); offset++)
7263 // result = left & right
7264 if (AOP_TYPE (right) == AOP_LIT)
7266 bytelit = (int)((lit >> (offset * 8)) & 0x0FFL);
7267 if (bytelit == 0x00L)
7269 aopPut (AOP (result),
7270 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7274 else if (bytelit == 0x0FF)
7276 /* dummy read of volatile operand */
7277 if (isOperandVolatile (left, FALSE))
7278 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7279 aopPut (AOP (result), "#0xFF", offset);
7282 D (emitcode (";", "better literal OR."););
7283 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7284 emitcode ("orl", "a, %s",
7285 aopGet (AOP (right), offset,
7286 FALSE, FALSE, DP2_RESULT_REG));
7291 // faster than result <- left, anl result,right
7292 // and better if result is SFR
7293 if (AOP_TYPE (left) == AOP_ACC)
7295 emitcode ("orl", "a,%s",
7296 aopGet (AOP (right), offset,
7297 FALSE, FALSE, DP2_RESULT_REG));
7301 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7303 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7305 emitcode("mov", "b,a");
7309 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7310 emitcode ("orl", "a,%s", rOp);
7313 aopPut (AOP (result), "a", offset);
7315 _endLazyDPSEvaluation();
7320 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7321 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7322 freeAsmop (result, NULL, ic, TRUE);
7325 /*-----------------------------------------------------------------*/
7326 /* genXor - code for xclusive or */
7327 /*-----------------------------------------------------------------*/
7329 genXor (iCode * ic, iCode * ifx)
7331 operand *left, *right, *result;
7332 int size, offset = 0;
7333 unsigned long lit = 0L;
7337 D (emitcode (";", "genXor "););
7339 AOP_OP_3_NOFATAL (ic, pushResult);
7340 AOP_SET_LOCALS (ic);
7344 genFarFarLogicOp(ic, "xrl");
7349 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7351 AOP_TYPE (left), AOP_TYPE (right));
7352 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7354 AOP_SIZE (left), AOP_SIZE (right));
7357 /* if left is a literal & right is not ||
7358 if left needs acc & right does not */
7359 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7360 #ifdef LOGIC_OPS_BROKEN
7361 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
7365 operand *tmp = right;
7370 /* if result = right then exchange them */
7371 if (sameRegs (AOP (result), AOP (right)))
7373 operand *tmp = right;
7378 /* if right is bit then exchange them */
7379 if (AOP_TYPE (right) == AOP_CRY &&
7380 AOP_TYPE (left) != AOP_CRY)
7382 operand *tmp = right;
7386 if (AOP_TYPE (right) == AOP_LIT)
7387 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7389 size = AOP_SIZE (result);
7393 if (AOP_TYPE (left) == AOP_CRY)
7395 if (AOP_TYPE (right) == AOP_LIT)
7397 // c = bit & literal;
7400 // lit>>1 != 0 => result = 1
7401 if (AOP_TYPE (result) == AOP_CRY)
7404 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7406 continueIfTrue (ifx);
7409 emitcode ("setb", "c");
7416 // lit == 0, result = left
7417 if (size && sameRegs (AOP (result), AOP (left)))
7419 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7423 // lit == 1, result = not(left)
7424 if (size && sameRegs (AOP (result), AOP (left)))
7426 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7431 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7432 emitcode ("cpl", "c");
7441 symbol *tlbl = newiTempLabel (NULL);
7442 if (AOP_TYPE (right) == AOP_CRY)
7445 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7449 int sizer = AOP_SIZE (right);
7451 // if val>>1 != 0, result = 1
7452 emitcode ("setb", "c");
7455 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
7457 // test the msb of the lsb
7458 emitcode ("anl", "a,#!constbyte",0xfe);
7459 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7463 emitcode ("rrc", "a");
7465 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7466 emitcode ("cpl", "c");
7467 emitcode ("", "!tlabeldef", (tlbl->key + 100));
7474 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7475 genIfxJump (ifx, "c");
7479 /* if left is same as result */
7480 if (sameRegs (AOP (result), AOP (left)))
7482 for (; size--; offset++)
7484 if (AOP_TYPE (right) == AOP_LIT)
7486 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7487 if (bytelit == 0x00L)
7489 /* dummy read of volatile operand */
7490 if (isOperandVolatile (left, FALSE))
7491 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7495 else if (IS_AOP_PREG (left))
7497 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7498 emitcode ("xrl", "a,%s",
7499 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7500 aopPut (AOP (result), "a", offset);
7504 emitcode ("xrl", "%s,%s",
7505 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7506 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7511 if (AOP_TYPE (left) == AOP_ACC)
7512 emitcode ("xrl", "a,%s",
7513 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7516 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7517 if (IS_AOP_PREG (left))
7519 emitcode ("xrl", "a,%s",
7520 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7521 aopPut (AOP (result), "a", offset);
7524 emitcode ("xrl", "%s,a",
7525 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7532 // left & result in different registers
7533 if (AOP_TYPE (result) == AOP_CRY)
7536 // if(size), result in bit
7537 // if(!size && ifx), conditional oper: if(left ^ right)
7538 symbol *tlbl = newiTempLabel (NULL);
7539 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7542 emitcode ("setb", "c");
7545 if ((AOP_TYPE (right) == AOP_LIT) &&
7546 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7548 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7552 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7553 emitcode ("xrl", "a,%s",
7554 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7556 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7557 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7559 emitcode("mov", "b,a");
7563 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7564 emitcode ("xrl", "a,%s", rOp);
7567 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7573 emitcode ("", "!tlabeldef", tlbl->key + 100);
7577 jmpTrueOrFalse (ifx, tlbl);
7581 for (; (size--); offset++)
7584 // result = left & right
7585 if (AOP_TYPE (right) == AOP_LIT)
7587 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7589 aopPut (AOP (result),
7590 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7594 D (emitcode (";", "better literal XOR."););
7595 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7596 emitcode ("xrl", "a, %s",
7597 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7601 // faster than result <- left, anl result,right
7602 // and better if result is SFR
7603 if (AOP_TYPE (left) == AOP_ACC)
7605 emitcode ("xrl", "a,%s",
7606 aopGet (AOP (right), offset,
7607 FALSE, FALSE, DP2_RESULT_REG));
7611 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7612 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7614 emitcode("mov", "b,a");
7618 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7619 emitcode ("xrl", "a,%s", rOp);
7622 aopPut (AOP (result), "a", offset);
7629 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7630 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7631 freeAsmop (result, NULL, ic, TRUE);
7634 /*-----------------------------------------------------------------*/
7635 /* genInline - write the inline code out */
7636 /*-----------------------------------------------------------------*/
7638 genInline (iCode * ic)
7640 char *buffer, *bp, *bp1;
7642 D (emitcode (";", "genInline "); );
7644 _G.inLine += (!options.asmpeep);
7646 buffer = Safe_strdup(IC_INLINE(ic));
7650 /* emit each line as a code */
7675 /* emitcode("",buffer); */
7676 _G.inLine -= (!options.asmpeep);
7679 /*-----------------------------------------------------------------*/
7680 /* genRRC - rotate right with carry */
7681 /*-----------------------------------------------------------------*/
7685 operand *left, *result;
7688 D (emitcode (";", "genRRC "););
7690 /* rotate right with carry */
7691 left = IC_LEFT (ic);
7692 result = IC_RESULT (ic);
7693 aopOp (left, ic, FALSE, FALSE);
7694 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7696 /* move it to the result */
7697 size = AOP_SIZE (result);
7701 _startLazyDPSEvaluation ();
7704 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7705 emitcode ("rrc", "a");
7706 if (AOP_SIZE (result) > 1)
7707 aopPut (AOP (result), "a", offset--);
7709 _endLazyDPSEvaluation ();
7711 /* now we need to put the carry into the
7712 highest order byte of the result */
7713 if (AOP_SIZE (result) > 1)
7715 MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7717 emitcode ("mov", "acc.7,c");
7718 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7719 freeAsmop (left, NULL, ic, TRUE);
7720 freeAsmop (result, NULL, ic, TRUE);
7723 /*-----------------------------------------------------------------*/
7724 /* genRLC - generate code for rotate left with carry */
7725 /*-----------------------------------------------------------------*/
7729 operand *left, *result;
7733 D (emitcode (";", "genRLC "););
7735 /* rotate right with carry */
7736 left = IC_LEFT (ic);
7737 result = IC_RESULT (ic);
7738 aopOp (left, ic, FALSE, FALSE);
7739 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7741 /* move it to the result */
7742 size = AOP_SIZE (result);
7746 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7748 emitcode ("add", "a,acc");
7749 if (AOP_SIZE (result) > 1)
7751 aopPut (AOP (result), "a", offset++);
7754 _startLazyDPSEvaluation ();
7757 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7759 emitcode ("rlc", "a");
7760 if (AOP_SIZE (result) > 1)
7761 aopPut (AOP (result), "a", offset++);
7763 _endLazyDPSEvaluation ();
7765 /* now we need to put the carry into the
7766 highest order byte of the result */
7767 if (AOP_SIZE (result) > 1)
7769 l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7772 emitcode ("mov", "acc.0,c");
7773 aopPut (AOP (result), "a", 0);
7774 freeAsmop (left, NULL, ic, TRUE);
7775 freeAsmop (result, NULL, ic, TRUE);
7778 /*-----------------------------------------------------------------*/
7779 /* genGetHbit - generates code get highest order bit */
7780 /*-----------------------------------------------------------------*/
7782 genGetHbit (iCode * ic)
7784 operand *left, *result;
7785 left = IC_LEFT (ic);
7786 result = IC_RESULT (ic);
7787 aopOp (left, ic, FALSE, FALSE);
7788 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7790 D (emitcode (";", "genGetHbit "););
7792 /* get the highest order byte into a */
7793 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7794 if (AOP_TYPE (result) == AOP_CRY)
7796 emitcode ("rlc", "a");
7801 emitcode ("rl", "a");
7802 emitcode ("anl", "a,#1");
7807 freeAsmop (left, NULL, ic, TRUE);
7808 freeAsmop (result, NULL, ic, TRUE);
7811 /*-----------------------------------------------------------------*/
7812 /* genSwap - generates code to swap nibbles or bytes */
7813 /*-----------------------------------------------------------------*/
7815 genSwap (iCode * ic)
7817 operand *left, *result;
7819 D(emitcode ("; genSwap",""));
7821 left = IC_LEFT (ic);
7822 result = IC_RESULT (ic);
7823 aopOp (left, ic, FALSE, FALSE);
7824 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7826 _startLazyDPSEvaluation ();
7827 switch (AOP_SIZE (left))
7829 case 1: /* swap nibbles in byte */
7830 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7831 emitcode ("swap", "a");
7832 aopPut (AOP (result), "a", 0);
7834 case 2: /* swap bytes in word */
7835 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7837 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7838 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7839 aopPut (AOP (result), "a", 1);
7841 else if (operandsEqu (left, result))
7844 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7845 if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
7847 emitcode ("mov", "b,a");
7851 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7852 aopPut (AOP (result), reg, 1);
7857 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7858 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE, NULL), 1);
7862 wassertl(FALSE, "unsupported SWAP operand size");
7864 _endLazyDPSEvaluation ();
7866 freeAsmop (left, NULL, ic, TRUE);
7867 freeAsmop (result, NULL, ic, TRUE);
7870 /*-----------------------------------------------------------------*/
7871 /* AccRol - rotate left accumulator by known count */
7872 /*-----------------------------------------------------------------*/
7874 AccRol (int shCount)
7876 shCount &= 0x0007; // shCount : 0..7
7883 emitcode ("rl", "a");
7886 emitcode ("rl", "a");
7887 emitcode ("rl", "a");
7890 emitcode ("swap", "a");
7891 emitcode ("rr", "a");
7894 emitcode ("swap", "a");
7897 emitcode ("swap", "a");
7898 emitcode ("rl", "a");
7901 emitcode ("rr", "a");
7902 emitcode ("rr", "a");
7905 emitcode ("rr", "a");
7910 /*-----------------------------------------------------------------*/
7911 /* AccLsh - left shift accumulator by known count */
7912 /*-----------------------------------------------------------------*/
7914 AccLsh (int shCount)
7919 emitcode ("add", "a,acc");
7920 else if (shCount == 2)
7922 emitcode ("add", "a,acc");
7923 emitcode ("add", "a,acc");
7927 /* rotate left accumulator */
7929 /* and kill the lower order bits */
7930 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7935 /*-----------------------------------------------------------------*/
7936 /* AccRsh - right shift accumulator by known count */
7937 /*-----------------------------------------------------------------*/
7939 AccRsh (int shCount)
7946 emitcode ("rrc", "a");
7950 /* rotate right accumulator */
7951 AccRol (8 - shCount);
7952 /* and kill the higher order bits */
7953 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7958 #ifdef BETTER_LITERAL_SHIFT
7959 /*-----------------------------------------------------------------*/
7960 /* AccSRsh - signed right shift accumulator by known count */
7961 /*-----------------------------------------------------------------*/
7963 AccSRsh (int shCount)
7970 emitcode ("mov", "c,acc.7");
7971 emitcode ("rrc", "a");
7973 else if (shCount == 2)
7975 emitcode ("mov", "c,acc.7");
7976 emitcode ("rrc", "a");
7977 emitcode ("mov", "c,acc.7");
7978 emitcode ("rrc", "a");
7982 tlbl = newiTempLabel (NULL);
7983 /* rotate right accumulator */
7984 AccRol (8 - shCount);
7985 /* and kill the higher order bits */
7986 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7987 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7988 emitcode ("orl", "a,#!constbyte",
7989 (unsigned char) ~SRMask[shCount]);
7990 emitcode ("", "!tlabeldef", tlbl->key + 100);
7996 #ifdef BETTER_LITERAL_SHIFT
7997 /*-----------------------------------------------------------------*/
7998 /* shiftR1Left2Result - shift right one byte from left to result */
7999 /*-----------------------------------------------------------------*/
8001 shiftR1Left2Result (operand * left, int offl,
8002 operand * result, int offr,
8003 int shCount, int sign)
8005 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8006 /* shift right accumulator */
8011 aopPut (AOP (result), "a", offr);
8015 #ifdef BETTER_LITERAL_SHIFT
8016 /*-----------------------------------------------------------------*/
8017 /* shiftL1Left2Result - shift left one byte from left to result */
8018 /*-----------------------------------------------------------------*/
8020 shiftL1Left2Result (operand * left, int offl,
8021 operand * result, int offr, int shCount)
8023 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8024 /* shift left accumulator */
8026 aopPut (AOP (result), "a", offr);
8030 #ifdef BETTER_LITERAL_SHIFT
8031 /*-----------------------------------------------------------------*/
8032 /* movLeft2Result - move byte from left to result */
8033 /*-----------------------------------------------------------------*/
8035 movLeft2Result (operand * left, int offl,
8036 operand * result, int offr, int sign)
8039 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8041 l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
8043 if (*l == '@' && (IS_AOP_PREG (result)))
8045 emitcode ("mov", "a,%s", l);
8046 aopPut (AOP (result), "a", offr);
8052 aopPut (AOP (result), l, offr);
8056 /* MSB sign in acc.7 ! */
8057 if (getDataSize (left) == offl + 1)
8059 emitcode ("mov", "a,%s", l);
8060 aopPut (AOP (result), "a", offr);
8068 #ifdef BETTER_LITERAL_SHIFT
8069 /*-----------------------------------------------------------------*/
8070 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8071 /*-----------------------------------------------------------------*/
8075 emitcode ("rrc", "a");
8076 emitcode ("xch", "a,%s", x);
8077 emitcode ("rrc", "a");
8078 emitcode ("xch", "a,%s", x);
8082 #ifdef BETTER_LITERAL_SHIFT
8084 /*-----------------------------------------------------------------*/
8085 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8086 /*-----------------------------------------------------------------*/
8090 emitcode ("xch", "a,%s", x);
8091 emitcode ("rlc", "a");
8092 emitcode ("xch", "a,%s", x);
8093 emitcode ("rlc", "a");
8097 #ifdef BETTER_LITERAL_SHIFT
8098 /*-----------------------------------------------------------------*/
8099 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8100 /*-----------------------------------------------------------------*/
8104 emitcode ("xch", "a,%s", x);
8105 emitcode ("add", "a,acc");
8106 emitcode ("xch", "a,%s", x);
8107 emitcode ("rlc", "a");
8111 #ifdef BETTER_LITERAL_SHIFT
8112 /*-----------------------------------------------------------------*/
8113 /* AccAXLsh - left shift a:x by known count (0..7) */
8114 /*-----------------------------------------------------------------*/
8116 AccAXLsh (char *x, int shCount)
8131 case 5: // AAAAABBB:CCCCCDDD
8133 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8135 emitcode ("anl", "a,#!constbyte",
8136 SLMask[shCount]); // BBB00000:CCCCCDDD
8138 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8140 AccRol (shCount); // DDDCCCCC:BBB00000
8142 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8144 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8146 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8148 emitcode ("anl", "a,#!constbyte",
8149 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8151 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8153 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8156 case 6: // AAAAAABB:CCCCCCDD
8157 emitcode ("anl", "a,#!constbyte",
8158 SRMask[shCount]); // 000000BB:CCCCCCDD
8159 emitcode ("mov", "c,acc.0"); // c = B
8160 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8162 AccAXRrl1 (x); // BCCCCCCD:D000000B
8163 AccAXRrl1 (x); // BBCCCCCC:DD000000
8165 emitcode("rrc","a");
8166 emitcode("xch","a,%s", x);
8167 emitcode("rrc","a");
8168 emitcode("mov","c,acc.0"); //<< get correct bit
8169 emitcode("xch","a,%s", x);
8171 emitcode("rrc","a");
8172 emitcode("xch","a,%s", x);
8173 emitcode("rrc","a");
8174 emitcode("xch","a,%s", x);
8177 case 7: // a:x <<= 7
8179 emitcode ("anl", "a,#!constbyte",
8180 SRMask[shCount]); // 0000000B:CCCCCCCD
8182 emitcode ("mov", "c,acc.0"); // c = B
8184 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8186 AccAXRrl1 (x); // BCCCCCCC:D0000000
8195 #ifdef BETTER_LITERAL_SHIFT
8197 /*-----------------------------------------------------------------*/
8198 /* AccAXRsh - right shift a:x known count (0..7) */
8199 /*-----------------------------------------------------------------*/
8201 AccAXRsh (char *x, int shCount)
8209 AccAXRrl1 (x); // 0->a:x
8214 AccAXRrl1 (x); // 0->a:x
8217 AccAXRrl1 (x); // 0->a:x
8222 case 5: // AAAAABBB:CCCCCDDD = a:x
8224 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8226 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8228 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8230 emitcode ("anl", "a,#!constbyte",
8231 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8233 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8235 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8237 emitcode ("anl", "a,#!constbyte",
8238 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8240 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8242 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8244 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8247 case 6: // AABBBBBB:CCDDDDDD
8249 emitcode ("mov", "c,acc.7");
8250 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8252 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8254 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8256 emitcode ("anl", "a,#!constbyte",
8257 SRMask[shCount]); // 000000AA:BBBBBBCC
8260 case 7: // ABBBBBBB:CDDDDDDD
8262 emitcode ("mov", "c,acc.7"); // c = A
8264 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8266 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8268 emitcode ("anl", "a,#!constbyte",
8269 SRMask[shCount]); // 0000000A:BBBBBBBC
8278 #ifdef BETTER_LITERAL_SHIFT
8279 /*-----------------------------------------------------------------*/
8280 /* AccAXRshS - right shift signed a:x known count (0..7) */
8281 /*-----------------------------------------------------------------*/
8283 AccAXRshS (char *x, int shCount)
8291 emitcode ("mov", "c,acc.7");
8292 AccAXRrl1 (x); // s->a:x
8296 emitcode ("mov", "c,acc.7");
8297 AccAXRrl1 (x); // s->a:x
8299 emitcode ("mov", "c,acc.7");
8300 AccAXRrl1 (x); // s->a:x
8305 case 5: // AAAAABBB:CCCCCDDD = a:x
8307 tlbl = newiTempLabel (NULL);
8308 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8310 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8312 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8314 emitcode ("anl", "a,#!constbyte",
8315 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8317 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8319 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8321 emitcode ("anl", "a,#!constbyte",
8322 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8324 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8326 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8328 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8330 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8331 emitcode ("orl", "a,#!constbyte",
8332 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8334 emitcode ("", "!tlabeldef", tlbl->key + 100);
8335 break; // SSSSAAAA:BBBCCCCC
8337 case 6: // AABBBBBB:CCDDDDDD
8339 tlbl = newiTempLabel (NULL);
8340 emitcode ("mov", "c,acc.7");
8341 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8343 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8345 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8347 emitcode ("anl", "a,#!constbyte",
8348 SRMask[shCount]); // 000000AA:BBBBBBCC
8350 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8351 emitcode ("orl", "a,#!constbyte",
8352 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8354 emitcode ("", "!tlabeldef", tlbl->key + 100);
8356 case 7: // ABBBBBBB:CDDDDDDD
8358 tlbl = newiTempLabel (NULL);
8359 emitcode ("mov", "c,acc.7"); // c = A
8361 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8363 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8365 emitcode ("anl", "a,#!constbyte",
8366 SRMask[shCount]); // 0000000A:BBBBBBBC
8368 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8369 emitcode ("orl", "a,#!constbyte",
8370 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8372 emitcode ("", "!tlabeldef", tlbl->key + 100);
8380 #ifdef BETTER_LITERAL_SHIFT
8382 _loadLeftIntoAx(char **lsb,
8388 // Get the initial value from left into a pair of registers.
8389 // MSB must be in A, LSB can be any register.
8391 // If the result is held in registers, it is an optimization
8392 // if the LSB can be held in the register which will hold the,
8393 // result LSB since this saves us from having to copy it into
8394 // the result following AccAXLsh.
8396 // If the result is addressed indirectly, this is not a gain.
8397 if (AOP_NEEDSACC(result))
8401 _startLazyDPSEvaluation();
8402 if (AOP_TYPE(left) == AOP_DPTR2)
8405 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
8406 // get LSB in DP2_RESULT_REG.
8407 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
8408 assert(!strcmp(leftByte, DP2_RESULT_REG));
8412 // get LSB into DP2_RESULT_REG
8413 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
8414 if (strcmp(leftByte, DP2_RESULT_REG))
8417 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
8420 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
8421 assert(strcmp(leftByte, DP2_RESULT_REG));
8424 _endLazyDPSEvaluation();
8425 *lsb = DP2_RESULT_REG;
8429 if (sameRegs (AOP (result), AOP (left)) &&
8430 ((offl + MSB16) == offr))
8432 /* don't crash result[offr] */
8433 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
8434 emitcode ("xch", "a,%s",
8435 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
8439 movLeft2Result (left, offl, result, offr, 0);
8440 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
8442 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
8443 assert(strcmp(*lsb,"a"));
8448 _storeAxResults(char *lsb,
8452 _startLazyDPSEvaluation();
8453 if (AOP_NEEDSACC(result))
8455 /* We have to explicitly update the result LSB.
8457 emitcode("xch","a,%s", lsb);
8458 aopPut(AOP(result), "a", offr);
8459 emitcode("mov","a,%s", lsb);
8461 if (getDataSize (result) > 1)
8463 aopPut (AOP (result), "a", offr + MSB16);
8465 _endLazyDPSEvaluation();
8468 /*-----------------------------------------------------------------*/
8469 /* shiftL2Left2Result - shift left two bytes from left to result */
8470 /*-----------------------------------------------------------------*/
8472 shiftL2Left2Result (operand * left, int offl,
8473 operand * result, int offr, int shCount)
8477 _loadLeftIntoAx(&lsb, left, result, offl, offr);
8479 AccAXLsh (lsb, shCount);
8481 _storeAxResults(lsb, result, offr);
8485 #ifdef BETTER_LITERAL_SHIFT
8486 /*-----------------------------------------------------------------*/
8487 /* shiftR2Left2Result - shift right two bytes from left to result */
8488 /*-----------------------------------------------------------------*/
8490 shiftR2Left2Result (operand * left, int offl,
8491 operand * result, int offr,
8492 int shCount, int sign)
8496 _loadLeftIntoAx(&lsb, left, result, offl, offr);
8498 /* a:x >> shCount (x = lsb(result)) */
8501 AccAXRshS(lsb, shCount);
8505 AccAXRsh(lsb, shCount);
8508 _storeAxResults(lsb, result, offr);
8512 /*-----------------------------------------------------------------*/
8513 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8514 /*-----------------------------------------------------------------*/
8516 shiftLLeftOrResult (operand * left, int offl,
8517 operand * result, int offr, int shCount)
8519 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8520 /* shift left accumulator */
8522 /* or with result */
8523 emitcode ("orl", "a,%s",
8524 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8525 /* back to result */
8526 aopPut (AOP (result), "a", offr);
8531 /*-----------------------------------------------------------------*/
8532 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8533 /*-----------------------------------------------------------------*/
8535 shiftRLeftOrResult (operand * left, int offl,
8536 operand * result, int offr, int shCount)
8538 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8539 /* shift right accumulator */
8541 /* or with result */
8542 emitcode ("orl", "a,%s",
8543 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8544 /* back to result */
8545 aopPut (AOP (result), "a", offr);
8549 #ifdef BETTER_LITERAL_SHIFT
8550 /*-----------------------------------------------------------------*/
8551 /* genlshOne - left shift a one byte quantity by known count */
8552 /*-----------------------------------------------------------------*/
8554 genlshOne (operand * result, operand * left, int shCount)
8556 D (emitcode (";", "genlshOne "););
8557 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8561 #ifdef BETTER_LITERAL_SHIFT
8562 /*-----------------------------------------------------------------*/
8563 /* genlshTwo - left shift two bytes by known amount != 0 */
8564 /*-----------------------------------------------------------------*/
8566 genlshTwo (operand * result, operand * left, int shCount)
8570 D (emitcode (";", "genlshTwo "););
8572 size = getDataSize (result);
8574 /* if shCount >= 8 */
8579 _startLazyDPSEvaluation();
8585 _endLazyDPSEvaluation();
8586 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8587 aopPut (AOP (result), zero, LSB);
8591 movLeft2Result (left, LSB, result, MSB16, 0);
8592 aopPut (AOP (result), zero, LSB);
8593 _endLazyDPSEvaluation();
8598 aopPut (AOP (result), zero, LSB);
8599 _endLazyDPSEvaluation();
8603 /* 1 <= shCount <= 7 */
8608 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8612 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8620 /*-----------------------------------------------------------------*/
8621 /* shiftLLong - shift left one long from left to result */
8622 /* offl = LSB or MSB16 */
8623 /*-----------------------------------------------------------------*/
8625 shiftLLong (operand * left, operand * result, int offr)
8628 int size = AOP_SIZE (result);
8630 if (size >= LSB + offr)
8632 l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8634 emitcode ("add", "a,acc");
8635 if (sameRegs (AOP (left), AOP (result)) &&
8636 size >= MSB16 + offr && offr != LSB)
8637 emitcode ("xch", "a,%s",
8638 aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8640 aopPut (AOP (result), "a", LSB + offr);
8643 if (size >= MSB16 + offr)
8645 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8647 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8649 emitcode ("rlc", "a");
8650 if (sameRegs (AOP (left), AOP (result)) &&
8651 size >= MSB24 + offr && offr != LSB)
8652 emitcode ("xch", "a,%s",
8653 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8655 aopPut (AOP (result), "a", MSB16 + offr);
8658 if (size >= MSB24 + offr)
8660 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8662 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8664 emitcode ("rlc", "a");
8665 if (sameRegs (AOP (left), AOP (result)) &&
8666 size >= MSB32 + offr && offr != LSB)
8667 emitcode ("xch", "a,%s",
8668 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8670 aopPut (AOP (result), "a", MSB24 + offr);
8673 if (size > MSB32 + offr)
8675 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8677 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8679 emitcode ("rlc", "a");
8680 aopPut (AOP (result), "a", MSB32 + offr);
8683 aopPut (AOP (result), zero, LSB);
8689 /*-----------------------------------------------------------------*/
8690 /* genlshFour - shift four byte by a known amount != 0 */
8691 /*-----------------------------------------------------------------*/
8693 genlshFour (operand * result, operand * left, int shCount)
8697 D (emitcode (";", "genlshFour ");
8700 size = AOP_SIZE (result);
8702 /* if shifting more that 3 bytes */
8707 /* lowest order of left goes to the highest
8708 order of the destination */
8709 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8711 movLeft2Result (left, LSB, result, MSB32, 0);
8712 aopPut (AOP (result), zero, LSB);
8713 aopPut (AOP (result), zero, MSB16);
8714 aopPut (AOP (result), zero, MSB24);
8718 /* more than two bytes */
8719 else if (shCount >= 16)
8721 /* lower order two bytes goes to higher order two bytes */
8723 /* if some more remaining */
8725 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8728 movLeft2Result (left, MSB16, result, MSB32, 0);
8729 movLeft2Result (left, LSB, result, MSB24, 0);
8731 aopPut (AOP (result), zero, MSB16);
8732 aopPut (AOP (result), zero, LSB);
8736 /* if more than 1 byte */
8737 else if (shCount >= 8)
8739 /* lower order three bytes goes to higher order three bytes */
8744 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8746 movLeft2Result (left, LSB, result, MSB16, 0);
8752 movLeft2Result (left, MSB24, result, MSB32, 0);
8753 movLeft2Result (left, MSB16, result, MSB24, 0);
8754 movLeft2Result (left, LSB, result, MSB16, 0);
8755 aopPut (AOP (result), zero, LSB);
8757 else if (shCount == 1)
8758 shiftLLong (left, result, MSB16);
8761 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8762 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8763 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8764 aopPut (AOP (result), zero, LSB);
8769 /* 1 <= shCount <= 7 */
8770 else if (shCount <= 2)
8772 shiftLLong (left, result, LSB);
8774 shiftLLong (result, result, LSB);
8776 /* 3 <= shCount <= 7, optimize */
8779 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8780 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8781 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8786 #ifdef BETTER_LITERAL_SHIFT
8787 /*-----------------------------------------------------------------*/
8788 /* genLeftShiftLiteral - left shifting by known count */
8789 /*-----------------------------------------------------------------*/
8791 genLeftShiftLiteral (operand * left,
8796 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8799 size = getSize (operandType (result));
8801 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8803 /* We only handle certain easy cases so far. */
8805 && (shCount < (size * 8))
8809 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8813 freeAsmop (right, NULL, ic, TRUE);
8815 aopOp(left, ic, FALSE, FALSE);
8816 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8819 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8821 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8822 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8824 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8827 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8829 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8830 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8832 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8838 emitcode ("; shift left ", "result %d, left %d", size,
8842 /* I suppose that the left size >= result size */
8845 _startLazyDPSEvaluation();
8848 movLeft2Result (left, size, result, size, 0);
8850 _endLazyDPSEvaluation();
8852 else if (shCount >= (size * 8))
8854 _startLazyDPSEvaluation();
8857 aopPut (AOP (result), zero, size);
8859 _endLazyDPSEvaluation();
8866 genlshOne (result, left, shCount);
8870 genlshTwo (result, left, shCount);
8874 genlshFour (result, left, shCount);
8878 fprintf(stderr, "*** ack! mystery literal shift!\n");
8882 freeAsmop (left, NULL, ic, TRUE);
8883 freeAsmop (result, NULL, ic, TRUE);
8888 /*-----------------------------------------------------------------*/
8889 /* genLeftShift - generates code for left shifting */
8890 /*-----------------------------------------------------------------*/
8892 genLeftShift (iCode * ic)
8894 operand *left, *right, *result;
8897 symbol *tlbl, *tlbl1;
8899 D (emitcode (";", "genLeftShift "););
8901 right = IC_RIGHT (ic);
8902 left = IC_LEFT (ic);
8903 result = IC_RESULT (ic);
8905 aopOp (right, ic, FALSE, FALSE);
8908 #ifdef BETTER_LITERAL_SHIFT
8909 /* if the shift count is known then do it
8910 as efficiently as possible */
8911 if (AOP_TYPE (right) == AOP_LIT)
8913 if (genLeftShiftLiteral (left, right, result, ic))
8920 /* shift count is unknown then we have to form
8921 a loop get the loop count in B : Note: we take
8922 only the lower order byte since shifting
8923 more that 32 bits make no sense anyway, ( the
8924 largest size of an object can be only 32 bits ) */
8926 if (AOP_TYPE (right) == AOP_LIT)
8928 /* Really should be handled by genLeftShiftLiteral,
8929 * but since I'm too lazy to fix that today, at least we can make
8930 * some small improvement.
8932 emitcode("mov", "b,#!constbyte",
8933 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8937 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8938 emitcode ("inc", "b");
8940 freeAsmop (right, NULL, ic, TRUE);
8941 aopOp (left, ic, FALSE, FALSE);
8942 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8944 /* now move the left to the result if they are not the
8946 if (!sameRegs (AOP (left), AOP (result)) &&
8947 AOP_SIZE (result) > 1)
8950 size = AOP_SIZE (result);
8952 _startLazyDPSEvaluation ();
8955 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8956 if (*l == '@' && (IS_AOP_PREG (result)))
8959 emitcode ("mov", "a,%s", l);
8960 aopPut (AOP (result), "a", offset);
8963 aopPut (AOP (result), l, offset);
8966 _endLazyDPSEvaluation ();
8969 tlbl = newiTempLabel (NULL);
8970 size = AOP_SIZE (result);
8972 tlbl1 = newiTempLabel (NULL);
8974 /* if it is only one byte then */
8977 symbol *tlbl1 = newiTempLabel (NULL);
8979 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8980 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8981 emitcode ("", "!tlabeldef", tlbl->key + 100);
8982 emitcode ("add", "a,acc");
8983 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8984 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8985 aopPut (AOP (result), "a", 0);
8989 reAdjustPreg (AOP (result));
8991 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8992 emitcode ("", "!tlabeldef", tlbl->key + 100);
8993 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8994 emitcode ("add", "a,acc");
8995 aopPut (AOP (result), "a", offset++);
8996 _startLazyDPSEvaluation ();
8999 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9000 emitcode ("rlc", "a");
9001 aopPut (AOP (result), "a", offset++);
9003 _endLazyDPSEvaluation ();
9004 reAdjustPreg (AOP (result));
9006 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9007 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9009 freeAsmop (left, NULL, ic, TRUE);
9010 freeAsmop (result, NULL, ic, TRUE);
9013 #ifdef BETTER_LITERAL_SHIFT
9014 /*-----------------------------------------------------------------*/
9015 /* genrshOne - right shift a one byte quantity by known count */
9016 /*-----------------------------------------------------------------*/
9018 genrshOne (operand * result, operand * left,
9019 int shCount, int sign)
9021 D (emitcode (";", "genrshOne"););
9022 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9026 #ifdef BETTER_LITERAL_SHIFT
9027 /*-----------------------------------------------------------------*/
9028 /* genrshTwo - right shift two bytes by known amount != 0 */
9029 /*-----------------------------------------------------------------*/
9031 genrshTwo (operand * result, operand * left,
9032 int shCount, int sign)
9034 D (emitcode (";", "genrshTwo"););
9036 /* if shCount >= 8 */
9040 _startLazyDPSEvaluation();
9043 shiftR1Left2Result (left, MSB16, result, LSB,
9048 movLeft2Result (left, MSB16, result, LSB, sign);
9050 addSign (result, MSB16, sign);
9051 _endLazyDPSEvaluation();
9054 /* 1 <= shCount <= 7 */
9057 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9062 /*-----------------------------------------------------------------*/
9063 /* shiftRLong - shift right one long from left to result */
9064 /* offl = LSB or MSB16 */
9065 /*-----------------------------------------------------------------*/
9067 shiftRLong (operand * left, int offl,
9068 operand * result, int sign)
9070 int isSameRegs=sameRegs(AOP(left),AOP(result));
9072 if (isSameRegs && offl>1) {
9073 // we are in big trouble, but this shouldn't happen
9074 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9077 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
9082 emitcode ("rlc", "a");
9083 emitcode ("subb", "a,acc");
9084 emitcode ("xch", "a,%s",
9085 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
9087 aopPut (AOP(result), zero, MSB32);
9092 emitcode ("clr", "c");
9094 emitcode ("mov", "c,acc.7");
9097 emitcode ("rrc", "a");
9099 if (isSameRegs && offl==MSB16) {
9101 "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
9103 aopPut (AOP (result), "a", MSB32);
9104 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
9107 emitcode ("rrc", "a");
9108 if (isSameRegs && offl==1) {
9109 emitcode ("xch", "a,%s",
9110 aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
9112 aopPut (AOP (result), "a", MSB24);
9113 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
9115 emitcode ("rrc", "a");
9116 aopPut (AOP (result), "a", MSB16 - offl);
9120 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
9121 emitcode ("rrc", "a");
9122 aopPut (AOP (result), "a", LSB);
9126 /*-----------------------------------------------------------------*/
9127 /* genrshFour - shift four byte by a known amount != 0 */
9128 /*-----------------------------------------------------------------*/
9130 genrshFour (operand * result, operand * left,
9131 int shCount, int sign)
9133 D (emitcode (";", "genrshFour"););
9135 /* if shifting more that 3 bytes */
9139 _startLazyDPSEvaluation();
9141 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9143 movLeft2Result (left, MSB32, result, LSB, sign);
9144 addSign (result, MSB16, sign);
9145 _endLazyDPSEvaluation();
9147 else if (shCount >= 16)
9150 _startLazyDPSEvaluation();
9152 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9155 movLeft2Result (left, MSB24, result, LSB, 0);
9156 movLeft2Result (left, MSB32, result, MSB16, sign);
9158 addSign (result, MSB24, sign);
9159 _endLazyDPSEvaluation();
9161 else if (shCount >= 8)
9164 _startLazyDPSEvaluation();
9167 shiftRLong (left, MSB16, result, sign);
9169 else if (shCount == 0)
9171 movLeft2Result (left, MSB16, result, LSB, 0);
9172 movLeft2Result (left, MSB24, result, MSB16, 0);
9173 movLeft2Result (left, MSB32, result, MSB24, sign);
9174 addSign (result, MSB32, sign);
9178 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9179 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9180 /* the last shift is signed */
9181 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9182 addSign (result, MSB32, sign);
9184 _endLazyDPSEvaluation();
9188 /* 1 <= shCount <= 7 */
9191 shiftRLong (left, LSB, result, sign);
9193 shiftRLong (result, LSB, result, sign);
9197 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9198 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9199 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9204 #ifdef BETTER_LITERAL_SHIFT
9205 /*-----------------------------------------------------------------*/
9206 /* genRightShiftLiteral - right shifting by known count */
9207 /*-----------------------------------------------------------------*/
9209 genRightShiftLiteral (operand * left,
9215 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9218 size = getSize (operandType (result));
9220 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
9222 /* We only handle certain easy cases so far. */
9224 && (shCount < (size * 8))
9229 D(emitcode (";", "genRightShiftLiteral wimping out"););
9233 freeAsmop (right, NULL, ic, TRUE);
9235 aopOp (left, ic, FALSE, FALSE);
9236 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9239 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9243 /* test the LEFT size !!! */
9245 /* I suppose that the left size >= result size */
9248 size = getDataSize (result);
9249 _startLazyDPSEvaluation();
9252 movLeft2Result (left, size, result, size, 0);
9254 _endLazyDPSEvaluation();
9256 else if (shCount >= (size * 8))
9260 /* get sign in acc.7 */
9261 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
9263 addSign (result, LSB, sign);
9270 genrshOne (result, left, shCount, sign);
9274 genrshTwo (result, left, shCount, sign);
9278 genrshFour (result, left, shCount, sign);
9285 freeAsmop (left, NULL, ic, TRUE);
9286 freeAsmop (result, NULL, ic, TRUE);
9292 /*-----------------------------------------------------------------*/
9293 /* genSignedRightShift - right shift of signed number */
9294 /*-----------------------------------------------------------------*/
9296 genSignedRightShift (iCode * ic)
9298 operand *right, *left, *result;
9301 symbol *tlbl, *tlbl1;
9303 D (emitcode (";", "genSignedRightShift "););
9305 /* we do it the hard way put the shift count in b
9306 and loop thru preserving the sign */
9308 right = IC_RIGHT (ic);
9309 left = IC_LEFT (ic);
9310 result = IC_RESULT (ic);
9312 aopOp (right, ic, FALSE, FALSE);
9314 #ifdef BETTER_LITERAL_SHIFT
9315 if (AOP_TYPE (right) == AOP_LIT)
9317 if (genRightShiftLiteral (left, right, result, ic, 1))
9323 /* shift count is unknown then we have to form
9324 a loop get the loop count in B : Note: we take
9325 only the lower order byte since shifting
9326 more that 32 bits make no sense anyway, ( the
9327 largest size of an object can be only 32 bits ) */
9329 if (AOP_TYPE (right) == AOP_LIT)
9331 /* Really should be handled by genRightShiftLiteral,
9332 * but since I'm too lazy to fix that today, at least we can make
9333 * some small improvement.
9335 emitcode("mov", "b,#!constbyte",
9336 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9340 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9341 emitcode ("inc", "b");
9343 freeAsmop (right, NULL, ic, TRUE);
9344 aopOp (left, ic, FALSE, FALSE);
9345 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9347 /* now move the left to the result if they are not the
9349 if (!sameRegs (AOP (left), AOP (result)) &&
9350 AOP_SIZE (result) > 1)
9353 size = AOP_SIZE (result);
9355 _startLazyDPSEvaluation ();
9358 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9359 if (*l == '@' && IS_AOP_PREG (result))
9362 emitcode ("mov", "a,%s", l);
9363 aopPut (AOP (result), "a", offset);
9366 aopPut (AOP (result), l, offset);
9369 _endLazyDPSEvaluation ();
9372 /* mov the highest order bit to OVR */
9373 tlbl = newiTempLabel (NULL);
9374 tlbl1 = newiTempLabel (NULL);
9376 size = AOP_SIZE (result);
9378 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
9379 emitcode ("rlc", "a");
9380 emitcode ("mov", "ov,c");
9381 /* if it is only one byte then */
9384 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9385 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9386 emitcode ("", "!tlabeldef", tlbl->key + 100);
9387 emitcode ("mov", "c,ov");
9388 emitcode ("rrc", "a");
9389 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9390 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9391 aopPut (AOP (result), "a", 0);
9395 reAdjustPreg (AOP (result));
9396 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9397 emitcode ("", "!tlabeldef", tlbl->key + 100);
9398 emitcode ("mov", "c,ov");
9399 _startLazyDPSEvaluation ();
9402 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9403 emitcode ("rrc", "a");
9404 aopPut (AOP (result), "a", offset--);
9406 _endLazyDPSEvaluation ();
9407 reAdjustPreg (AOP (result));
9408 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9409 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9412 freeAsmop (left, NULL, ic, TRUE);
9413 freeAsmop (result, NULL, ic, TRUE);
9416 /*-----------------------------------------------------------------*/
9417 /* genRightShift - generate code for right shifting */
9418 /*-----------------------------------------------------------------*/
9420 genRightShift (iCode * ic)
9422 operand *right, *left, *result;
9426 symbol *tlbl, *tlbl1;
9428 D (emitcode (";", "genRightShift "););
9430 /* if signed then we do it the hard way preserve the
9431 sign bit moving it inwards */
9432 letype = getSpec (operandType (IC_LEFT (ic)));
9434 if (!SPEC_USIGN (letype))
9436 genSignedRightShift (ic);
9440 /* signed & unsigned types are treated the same : i.e. the
9441 signed is NOT propagated inwards : quoting from the
9442 ANSI - standard : "for E1 >> E2, is equivalent to division
9443 by 2**E2 if unsigned or if it has a non-negative value,
9444 otherwise the result is implementation defined ", MY definition
9445 is that the sign does not get propagated */
9447 right = IC_RIGHT (ic);
9448 left = IC_LEFT (ic);
9449 result = IC_RESULT (ic);
9451 aopOp (right, ic, FALSE, FALSE);
9453 #ifdef BETTER_LITERAL_SHIFT
9454 /* if the shift count is known then do it
9455 as efficiently as possible */
9456 if (AOP_TYPE (right) == AOP_LIT)
9458 if (genRightShiftLiteral (left, right, result, ic, 0))
9465 /* shift count is unknown then we have to form
9466 a loop get the loop count in B : Note: we take
9467 only the lower order byte since shifting
9468 more that 32 bits make no sense anyway, ( the
9469 largest size of an object can be only 32 bits ) */
9471 if (AOP_TYPE (right) == AOP_LIT)
9473 /* Really should be handled by genRightShiftLiteral,
9474 * but since I'm too lazy to fix that today, at least we can make
9475 * some small improvement.
9477 emitcode("mov", "b,#!constbyte",
9478 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9482 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9483 emitcode ("inc", "b");
9485 freeAsmop (right, NULL, ic, TRUE);
9486 aopOp (left, ic, FALSE, FALSE);
9487 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9489 /* now move the left to the result if they are not the
9491 if (!sameRegs (AOP (left), AOP (result)) &&
9492 AOP_SIZE (result) > 1)
9495 size = AOP_SIZE (result);
9497 _startLazyDPSEvaluation ();
9500 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9501 if (*l == '@' && IS_AOP_PREG (result))
9504 emitcode ("mov", "a,%s", l);
9505 aopPut (AOP (result), "a", offset);
9508 aopPut (AOP (result), l, offset);
9511 _endLazyDPSEvaluation ();
9514 tlbl = newiTempLabel (NULL);
9515 tlbl1 = newiTempLabel (NULL);
9516 size = AOP_SIZE (result);
9519 /* if it is only one byte then */
9522 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9523 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9524 emitcode ("", "!tlabeldef", tlbl->key + 100);
9526 emitcode ("rrc", "a");
9527 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9528 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9529 aopPut (AOP (result), "a", 0);
9533 reAdjustPreg (AOP (result));
9534 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9535 emitcode ("", "!tlabeldef", tlbl->key + 100);
9537 _startLazyDPSEvaluation ();
9540 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9541 emitcode ("rrc", "a");
9542 aopPut (AOP (result), "a", offset--);
9544 _endLazyDPSEvaluation ();
9545 reAdjustPreg (AOP (result));
9547 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9548 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9551 freeAsmop (left, NULL, ic, TRUE);
9552 freeAsmop (result, NULL, ic, TRUE);
9556 /*-----------------------------------------------------------------*/
9557 /* emitPtrByteGet - emits code to get a byte into A through a */
9558 /* pointer register (R0, R1, or DPTR). The */
9559 /* original value of A can be preserved in B. */
9560 /*-----------------------------------------------------------------*/
9562 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9569 emitcode ("mov", "b,a");
9570 emitcode ("mov", "a,@%s", rname);
9575 emitcode ("mov", "b,a");
9576 emitcode ("movx", "a,@%s", rname);
9581 emitcode ("mov", "b,a");
9582 emitcode ("movx", "a,@dptr");
9587 emitcode ("mov", "b,a");
9588 emitcode ("clr", "a");
9589 emitcode ("movc", "a,@a+dptr");
9595 emitcode ("push", "b");
9596 emitcode ("push", "acc");
9598 emitcode ("lcall", "__gptrget");
9600 emitcode ("pop", "b");
9605 /*-----------------------------------------------------------------*/
9606 /* emitPtrByteSet - emits code to set a byte from src through a */
9607 /* pointer register (R0, R1, or DPTR). */
9608 /*-----------------------------------------------------------------*/
9610 emitPtrByteSet (char *rname, int p_type, char *src)
9619 emitcode ("mov", "@%s,a", rname);
9622 emitcode ("mov", "@%s,%s", rname, src);
9627 emitcode ("movx", "@%s,a", rname);
9632 emitcode ("movx", "@dptr,a");
9637 emitcode ("lcall", "__gptrput");
9642 /*-----------------------------------------------------------------*/
9643 /* genUnpackBits - generates code for unpacking bits */
9644 /*-----------------------------------------------------------------*/
9646 genUnpackBits (operand * result, char *rname, int ptype)
9648 int offset = 0; /* result byte offset */
9649 int rsize; /* result size */
9650 int rlen = 0; /* remaining bitfield length */
9651 sym_link *etype; /* bitfield type information */
9652 int blen; /* bitfield length */
9653 int bstr; /* bitfield starting bit within byte */
9655 D(emitcode ("; genUnpackBits",""));
9657 etype = getSpec (operandType (result));
9658 rsize = getSize (operandType (result));
9659 blen = SPEC_BLEN (etype);
9660 bstr = SPEC_BSTR (etype);
9662 /* If the bitfield length is less than a byte */
9665 emitPtrByteGet (rname, ptype, FALSE);
9667 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9668 aopPut (AOP (result), "a", offset++);
9672 /* Bit field did not fit in a byte. Copy all
9673 but the partial byte at the end. */
9674 for (rlen=blen;rlen>=8;rlen-=8)
9676 emitPtrByteGet (rname, ptype, FALSE);
9677 aopPut (AOP (result), "a", offset++);
9679 emitcode ("inc", "%s", rname);
9682 /* Handle the partial byte at the end */
9685 emitPtrByteGet (rname, ptype, FALSE);
9686 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9687 aopPut (AOP (result), "a", offset++);
9695 aopPut (AOP (result), zero, offset++);
9700 /*-----------------------------------------------------------------*/
9701 /* genDataPointerGet - generates code when ptr offset is known */
9702 /*-----------------------------------------------------------------*/
9704 genDataPointerGet (operand * left,
9710 int size, offset = 0;
9711 aopOp (result, ic, TRUE, FALSE);
9713 /* get the string representation of the name */
9714 l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9715 size = AOP_SIZE (result);
9716 _startLazyDPSEvaluation ();
9721 SNPRINTF (buff, sizeof(buff),
9722 "(%s + %d)", l + 1, offset);
9726 SNPRINTF (buff, sizeof(buff),
9729 aopPut (AOP (result), buff, offset++);
9731 _endLazyDPSEvaluation ();
9733 freeAsmop (left, NULL, ic, TRUE);
9734 freeAsmop (result, NULL, ic, TRUE);
9737 /*-----------------------------------------------------------------*/
9738 /* genNearPointerGet - emitcode for near pointer fetch */
9739 /*-----------------------------------------------------------------*/
9741 genNearPointerGet (operand * left,
9749 sym_link *rtype, *retype, *letype;
9750 sym_link *ltype = operandType (left);
9753 rtype = operandType (result);
9754 retype = getSpec (rtype);
9755 letype = getSpec (ltype);
9757 aopOp (left, ic, FALSE, FALSE);
9759 /* if left is rematerialisable and
9760 result is not bitfield variable type and
9761 the left is pointer to data space i.e
9762 lower 128 bytes of space */
9763 if (AOP_TYPE (left) == AOP_IMMD &&
9764 !IS_BITFIELD (retype) &&
9765 !IS_BITFIELD (letype) &&
9766 DCL_TYPE (ltype) == POINTER)
9768 genDataPointerGet (left, result, ic);
9772 /* if the value is already in a pointer register
9773 then don't need anything more */
9774 if (!AOP_INPREG (AOP (left)))
9776 /* otherwise get a free pointer register */
9778 preg = getFreePtr (ic, &aop, FALSE);
9779 emitcode ("mov", "%s,%s",
9781 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9785 rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9787 freeAsmop (left, NULL, ic, TRUE);
9788 aopOp (result, ic, FALSE, FALSE);
9790 /* if bitfield then unpack the bits */
9791 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9792 genUnpackBits (result, rname, POINTER);
9795 /* we have can just get the values */
9796 int size = AOP_SIZE (result);
9801 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9804 emitcode ("mov", "a,@%s", rname);
9805 aopPut (AOP (result), "a", offset);
9809 SNPRINTF (buff, sizeof(buff), "@%s", rname);
9810 aopPut (AOP (result), buff, offset);
9815 emitcode ("inc", "%s", rname);
9820 /* now some housekeeping stuff */
9823 /* we had to allocate for this iCode */
9824 if (pi) { /* post increment present */
9825 aopPut(AOP ( left ),rname,0);
9827 freeAsmop (NULL, aop, ic, TRUE);
9831 /* we did not allocate which means left
9832 already in a pointer register, then
9833 if size > 0 && this could be used again
9834 we have to point it back to where it
9836 if (AOP_SIZE (result) > 1 &&
9837 !OP_SYMBOL (left)->remat &&
9838 (OP_SYMBOL (left)->liveTo > ic->seq ||
9842 int size = AOP_SIZE (result) - 1;
9844 emitcode ("dec", "%s", rname);
9849 freeAsmop (result, NULL, ic, TRUE);
9850 if (pi) pi->generated = 1;
9853 /*-----------------------------------------------------------------*/
9854 /* genPagedPointerGet - emitcode for paged pointer fetch */
9855 /*-----------------------------------------------------------------*/
9857 genPagedPointerGet (operand * left,
9865 sym_link *rtype, *retype, *letype;
9867 rtype = operandType (result);
9868 retype = getSpec (rtype);
9869 letype = getSpec (operandType (left));
9870 aopOp (left, ic, FALSE, FALSE);
9872 /* if the value is already in a pointer register
9873 then don't need anything more */
9874 if (!AOP_INPREG (AOP (left)))
9876 /* otherwise get a free pointer register */
9878 preg = getFreePtr (ic, &aop, FALSE);
9879 emitcode ("mov", "%s,%s",
9881 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9885 rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9887 freeAsmop (left, NULL, ic, TRUE);
9888 aopOp (result, ic, FALSE, FALSE);
9890 /* if bitfield then unpack the bits */
9891 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9892 genUnpackBits (result, rname, PPOINTER);
9895 /* we have can just get the values */
9896 int size = AOP_SIZE (result);
9902 emitcode ("movx", "a,@%s", rname);
9903 aopPut (AOP (result), "a", offset);
9908 emitcode ("inc", "%s", rname);
9912 /* now some housekeeping stuff */
9915 /* we had to allocate for this iCode */
9916 if (pi) aopPut ( AOP (left), rname, 0);
9917 freeAsmop (NULL, aop, ic, TRUE);
9921 /* we did not allocate which means left
9922 already in a pointer register, then
9923 if size > 0 && this could be used again
9924 we have to point it back to where it
9926 if (AOP_SIZE (result) > 1 &&
9927 !OP_SYMBOL (left)->remat &&
9928 (OP_SYMBOL (left)->liveTo > ic->seq ||
9932 int size = AOP_SIZE (result) - 1;
9934 emitcode ("dec", "%s", rname);
9939 freeAsmop (result, NULL, ic, TRUE);
9940 if (pi) pi->generated = 1;
9943 /*-----------------------------------------------------------------*/
9944 /* genFarPointerGet - gget value from far space */
9945 /*-----------------------------------------------------------------*/
9947 genFarPointerGet (operand * left,
9948 operand * result, iCode * ic, iCode *pi)
9950 int size, offset, dopi=1;
9951 sym_link *retype = getSpec (operandType (result));
9952 sym_link *letype = getSpec (operandType (left));
9953 D (emitcode (";", "genFarPointerGet"););
9955 aopOp (left, ic, FALSE, FALSE);
9957 /* if the operand is already in dptr
9958 then we do nothing else we move the value to dptr */
9959 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9961 /* if this is remateriazable */
9962 if (AOP_TYPE (left) == AOP_IMMD)
9964 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9968 /* we need to get it byte by byte */
9969 _startLazyDPSEvaluation ();
9970 if (AOP_TYPE (left) != AOP_DPTR)
9972 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9973 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9974 if (options.model == MODEL_FLAT24)
9975 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9979 /* We need to generate a load to DPTR indirect through DPTR. */
9980 D (emitcode (";", "genFarPointerGet -- indirection special case."););
9981 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9982 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9983 if (options.model == MODEL_FLAT24)
9984 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9985 emitcode ("pop", "dph");
9986 emitcode ("pop", "dpl");
9989 _endLazyDPSEvaluation ();
9992 /* so dptr know contains the address */
9993 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9995 /* if bit then unpack */
9996 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9997 if (AOP_INDPTRn(left)) {
9998 genSetDPTR(AOP(left)->aopu.dptr);
10000 genUnpackBits (result, "dptr", FPOINTER);
10001 if (AOP_INDPTRn(left)) {
10006 size = AOP_SIZE (result);
10009 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10011 genSetDPTR(AOP(left)->aopu.dptr);
10012 emitcode ("movx", "a,@dptr");
10013 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10014 emitcode ("inc", "dptr");
10016 aopPut (AOP (result), "a", offset++);
10019 _startLazyDPSEvaluation ();
10021 if (AOP_INDPTRn(left)) {
10022 genSetDPTR(AOP(left)->aopu.dptr);
10028 emitcode ("movx", "a,@dptr");
10029 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10030 emitcode ("inc", "dptr");
10032 aopPut (AOP (result), "a", offset++);
10034 _endLazyDPSEvaluation ();
10037 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10038 if (!AOP_INDPTRn(left)) {
10039 _startLazyDPSEvaluation ();
10040 aopPut ( AOP (left), "dpl", 0);
10041 aopPut ( AOP (left), "dph", 1);
10042 if (options.model == MODEL_FLAT24)
10043 aopPut ( AOP (left), "dpx", 2);
10044 _endLazyDPSEvaluation ();
10047 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
10048 AOP_SIZE(result) > 1 &&
10050 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
10052 size = AOP_SIZE (result) - 1;
10053 if (AOP_INDPTRn(left)) {
10054 genSetDPTR(AOP(left)->aopu.dptr);
10056 while (size--) emitcode ("lcall","__decdptr");
10057 if (AOP_INDPTRn(left)) {
10062 freeAsmop (left, NULL, ic, TRUE);
10063 freeAsmop (result, NULL, ic, TRUE);
10066 /*-----------------------------------------------------------------*/
10067 /* genCodePointerGet - get value from code space */
10068 /*-----------------------------------------------------------------*/
10070 genCodePointerGet (operand * left,
10071 operand * result, iCode * ic, iCode *pi)
10073 int size, offset, dopi=1;
10074 sym_link *retype = getSpec (operandType (result));
10076 aopOp (left, ic, FALSE, FALSE);
10078 /* if the operand is already in dptr
10079 then we do nothing else we move the value to dptr */
10080 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
10082 /* if this is remateriazable */
10083 if (AOP_TYPE (left) == AOP_IMMD)
10085 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10088 { /* we need to get it byte by byte */
10089 _startLazyDPSEvaluation ();
10090 if (AOP_TYPE (left) != AOP_DPTR)
10092 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10093 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10094 if (options.model == MODEL_FLAT24)
10095 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10099 /* We need to generate a load to DPTR indirect through DPTR. */
10100 D (emitcode (";", "gencodePointerGet -- indirection special case."););
10101 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
10102 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
10103 if (options.model == MODEL_FLAT24)
10104 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10105 emitcode ("pop", "dph");
10106 emitcode ("pop", "dpl");
10109 _endLazyDPSEvaluation ();
10112 /* so dptr know contains the address */
10113 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10115 /* if bit then unpack */
10116 if (IS_BITFIELD (retype)) {
10117 if (AOP_INDPTRn(left)) {
10118 genSetDPTR(AOP(left)->aopu.dptr);
10120 genUnpackBits (result, "dptr", CPOINTER);
10121 if (AOP_INDPTRn(left)) {
10126 size = AOP_SIZE (result);
10128 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10130 genSetDPTR(AOP(left)->aopu.dptr);
10131 emitcode ("clr", "a");
10132 emitcode ("movc", "a,@a+dptr");
10133 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10134 emitcode ("inc", "dptr");
10136 aopPut (AOP (result), "a", offset++);
10139 _startLazyDPSEvaluation ();
10142 if (AOP_INDPTRn(left)) {
10143 genSetDPTR(AOP(left)->aopu.dptr);
10149 emitcode ("clr", "a");
10150 emitcode ("movc", "a,@a+dptr");
10151 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10152 emitcode ("inc", "dptr");
10153 aopPut (AOP (result), "a", offset++);
10155 _endLazyDPSEvaluation ();
10158 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10159 if (!AOP_INDPTRn(left)) {
10160 _startLazyDPSEvaluation ();
10162 aopPut ( AOP (left), "dpl", 0);
10163 aopPut ( AOP (left), "dph", 1);
10164 if (options.model == MODEL_FLAT24)
10165 aopPut ( AOP (left), "dpx", 2);
10167 _endLazyDPSEvaluation ();
10170 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
10171 AOP_SIZE(result) > 1 &&
10172 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10174 size = AOP_SIZE (result) - 1;
10175 if (AOP_INDPTRn(left)) {
10176 genSetDPTR(AOP(left)->aopu.dptr);
10178 while (size--) emitcode ("lcall","__decdptr");
10179 if (AOP_INDPTRn(left)) {
10184 freeAsmop (left, NULL, ic, TRUE);
10185 freeAsmop (result, NULL, ic, TRUE);
10188 /*-----------------------------------------------------------------*/
10189 /* genGenPointerGet - gget value from generic pointer space */
10190 /*-----------------------------------------------------------------*/
10192 genGenPointerGet (operand * left,
10193 operand * result, iCode * ic, iCode * pi)
10196 sym_link *retype = getSpec (operandType (result));
10197 sym_link *letype = getSpec (operandType (left));
10199 D (emitcode (";", "genGenPointerGet "); );
10201 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
10203 /* if the operand is already in dptr
10204 then we do nothing else we move the value to dptr */
10205 if (AOP_TYPE (left) != AOP_STR)
10207 /* if this is rematerializable */
10208 if (AOP_TYPE (left) == AOP_IMMD)
10210 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10211 if (AOP(left)->aopu.aop_immd.from_cast_remat)
10213 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
10217 emitcode ("mov", "b,#%d", pointerCode (retype));
10221 { /* we need to get it byte by byte */
10222 _startLazyDPSEvaluation ();
10223 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
10224 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
10225 if (options.model == MODEL_FLAT24) {
10226 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10227 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
10229 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10231 _endLazyDPSEvaluation ();
10235 /* so dptr-b now contains the address */
10237 aopOp (result, ic, FALSE, TRUE);
10240 /* if bit then unpack */
10241 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10243 genUnpackBits (result, "dptr", GPOINTER);
10247 size = AOP_SIZE (result);
10254 // Get two bytes at a time, results in _AP & A.
10255 // dptr will be incremented ONCE by __gptrgetWord.
10257 // Note: any change here must be coordinated
10258 // with the implementation of __gptrgetWord
10259 // in device/lib/_gptrget.c
10260 emitcode ("lcall", "__gptrgetWord");
10261 aopPut (AOP (result), DP2_RESULT_REG, offset++);
10262 aopPut (AOP (result), "a", offset++);
10267 // Only one byte to get.
10268 emitcode ("lcall", "__gptrget");
10269 aopPut (AOP (result), "a", offset++);
10272 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
10274 emitcode ("inc", "dptr");
10279 if (pi && AOP_TYPE (left) != AOP_IMMD) {
10280 _startLazyDPSEvaluation ();
10282 aopPut ( AOP (left), "dpl", 0);
10283 aopPut ( AOP (left), "dph", 1);
10284 if (options.model == MODEL_FLAT24) {
10285 aopPut ( AOP (left), "dpx", 2);
10286 aopPut ( AOP (left), "b", 3);
10287 } else aopPut ( AOP (left), "b", 2);
10289 _endLazyDPSEvaluation ();
10292 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
10293 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10295 size = AOP_SIZE (result) - 1;
10296 while (size--) emitcode ("lcall","__decdptr");
10299 freeAsmop (left, NULL, ic, TRUE);
10300 freeAsmop (result, NULL, ic, TRUE);
10303 /*-----------------------------------------------------------------*/
10304 /* genPointerGet - generate code for pointer get */
10305 /*-----------------------------------------------------------------*/
10307 genPointerGet (iCode * ic, iCode *pi)
10309 operand *left, *result;
10310 sym_link *type, *etype;
10313 D (emitcode (";", "genPointerGet ");
10316 left = IC_LEFT (ic);
10317 result = IC_RESULT (ic);
10319 /* depending on the type of pointer we need to
10320 move it to the correct pointer register */
10321 type = operandType (left);
10322 etype = getSpec (type);
10323 /* if left is of type of pointer then it is simple */
10324 if (IS_PTR (type) && !IS_FUNC (type->next))
10325 p_type = DCL_TYPE (type);
10328 /* we have to go by the storage class */
10329 p_type = PTR_TYPE (SPEC_OCLS (etype));
10331 /* special case when cast remat */
10332 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10333 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10335 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10336 type = operandType (left);
10337 p_type = DCL_TYPE (type);
10339 /* now that we have the pointer type we assign
10340 the pointer values */
10346 genNearPointerGet (left, result, ic, pi);
10350 genPagedPointerGet (left, result, ic, pi);
10354 genFarPointerGet (left, result, ic, pi);
10358 genCodePointerGet (left, result, ic, pi);
10362 genGenPointerGet (left, result, ic, pi);
10368 /*-----------------------------------------------------------------*/
10369 /* genPackBits - generates code for packed bit storage */
10370 /*-----------------------------------------------------------------*/
10372 genPackBits (sym_link * etype,
10374 char *rname, int p_type)
10376 int offset = 0; /* source byte offset */
10377 int rlen = 0; /* remaining bitfield length */
10378 int blen; /* bitfield length */
10379 int bstr; /* bitfield starting bit within byte */
10380 int litval; /* source literal value (if AOP_LIT) */
10381 unsigned char mask; /* bitmask within current byte */
10383 D(emitcode ("; genPackBits",""));
10385 blen = SPEC_BLEN (etype);
10386 bstr = SPEC_BSTR (etype);
10388 /* If the bitfield length is less than a byte */
10391 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10392 (unsigned char) (0xFF >> (8 - bstr)));
10394 if (AOP_TYPE (right) == AOP_LIT)
10396 /* Case with a bitfield length <8 and literal source
10398 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10400 litval &= (~mask) & 0xff;
10401 emitPtrByteGet (rname, p_type, FALSE);
10402 if ((mask|litval)!=0xff)
10403 emitcode ("anl","a,#!constbyte", mask);
10405 emitcode ("orl","a,#!constbyte", litval);
10409 if ((blen==1) && (p_type!=GPOINTER))
10411 /* Case with a bitfield length == 1 and no generic pointer
10413 if (AOP_TYPE (right) == AOP_CRY)
10414 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10417 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10418 emitcode ("rrc","a");
10420 emitPtrByteGet (rname, p_type, FALSE);
10421 emitcode ("mov","acc.%d,c",bstr);
10425 /* Case with a bitfield length < 8 and arbitrary source
10427 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10428 /* shift and mask source value */
10430 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10432 /* transfer A to B and get next byte */
10433 emitPtrByteGet (rname, p_type, TRUE);
10435 emitcode ("anl", "a,#!constbyte", mask);
10436 emitcode ("orl", "a,b");
10437 if (p_type == GPOINTER)
10438 emitcode ("pop", "b");
10442 emitPtrByteSet (rname, p_type, "a");
10446 /* Bit length is greater than 7 bits. In this case, copy */
10447 /* all except the partial byte at the end */
10448 for (rlen=blen;rlen>=8;rlen-=8)
10450 emitPtrByteSet (rname, p_type,
10451 aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
10453 emitcode ("inc", "%s", rname);
10456 /* If there was a partial byte at the end */
10459 mask = (((unsigned char) -1 << rlen) & 0xff);
10461 if (AOP_TYPE (right) == AOP_LIT)
10463 /* Case with partial byte and literal source
10465 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10466 litval >>= (blen-rlen);
10467 litval &= (~mask) & 0xff;
10468 emitPtrByteGet (rname, p_type, FALSE);
10469 if ((mask|litval)!=0xff)
10470 emitcode ("anl","a,#!constbyte", mask);
10472 emitcode ("orl","a,#!constbyte", litval);
10476 /* Case with partial byte and arbitrary source
10478 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10479 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10481 /* transfer A to B and get next byte */
10482 emitPtrByteGet (rname, p_type, TRUE);
10484 emitcode ("anl", "a,#!constbyte", mask);
10485 emitcode ("orl", "a,b");
10486 if (p_type == GPOINTER)
10487 emitcode ("pop", "b");
10489 emitPtrByteSet (rname, p_type, "a");
10495 /*-----------------------------------------------------------------*/
10496 /* genDataPointerSet - remat pointer to data space */
10497 /*-----------------------------------------------------------------*/
10499 genDataPointerSet (operand * right,
10503 int size, offset = 0;
10504 char *l, buff[256];
10506 aopOp (right, ic, FALSE, FALSE);
10508 l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
10509 size = AOP_SIZE (right);
10514 SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
10518 SNPRINTF (buff, sizeof(buff), "%s", l + 1);
10521 emitcode ("mov", "%s,%s", buff,
10522 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10525 freeAsmop (right, NULL, ic, TRUE);
10526 freeAsmop (result, NULL, ic, TRUE);
10529 /*-----------------------------------------------------------------*/
10530 /* genNearPointerSet - emitcode for near pointer put */
10531 /*-----------------------------------------------------------------*/
10533 genNearPointerSet (operand * right,
10540 sym_link *retype, *letype;
10541 sym_link *ptype = operandType (result);
10543 retype = getSpec (operandType (right));
10544 letype = getSpec (ptype);
10546 aopOp (result, ic, FALSE, FALSE);
10548 /* if the result is rematerializable &
10549 in data space & not a bit variable */
10550 if (AOP_TYPE (result) == AOP_IMMD &&
10551 DCL_TYPE (ptype) == POINTER &&
10552 !IS_BITVAR (retype) &&
10553 !IS_BITVAR (letype))
10555 genDataPointerSet (right, result, ic);
10559 /* if the value is already in a pointer register
10560 then don't need anything more */
10561 if (!AOP_INPREG (AOP (result)))
10563 /* otherwise get a free pointer register */
10566 aop = newAsmop (0);
10567 preg = getFreePtr (ic, &aop, FALSE);
10568 emitcode ("mov", "%s,%s",
10570 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10571 rname = preg->name;
10574 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10576 aopOp (right, ic, FALSE, FALSE);
10578 /* if bitfield then unpack the bits */
10579 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10580 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10583 /* we have can just get the values */
10584 int size = AOP_SIZE (right);
10589 l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10593 emitcode ("mov", "@%s,a", rname);
10596 emitcode ("mov", "@%s,%s", rname, l);
10598 emitcode ("inc", "%s", rname);
10603 /* now some housekeeping stuff */
10606 /* we had to allocate for this iCode */
10607 if (pi) aopPut (AOP (result),rname,0);
10608 freeAsmop (NULL, aop, ic, TRUE);
10612 /* we did not allocate which means left
10613 already in a pointer register, then
10614 if size > 0 && this could be used again
10615 we have to point it back to where it
10617 if (AOP_SIZE (right) > 1 &&
10618 !OP_SYMBOL (result)->remat &&
10619 (OP_SYMBOL (result)->liveTo > ic->seq ||
10623 int size = AOP_SIZE (right) - 1;
10625 emitcode ("dec", "%s", rname);
10630 if (pi) pi->generated = 1;
10631 freeAsmop (result, NULL, ic, TRUE);
10632 freeAsmop (right, NULL, ic, TRUE);
10637 /*-----------------------------------------------------------------*/
10638 /* genPagedPointerSet - emitcode for Paged pointer put */
10639 /*-----------------------------------------------------------------*/
10641 genPagedPointerSet (operand * right,
10648 sym_link *retype, *letype;
10650 retype = getSpec (operandType (right));
10651 letype = getSpec (operandType (result));
10653 aopOp (result, ic, FALSE, FALSE);
10655 /* if the value is already in a pointer register
10656 then don't need anything more */
10657 if (!AOP_INPREG (AOP (result)))
10659 /* otherwise get a free pointer register */
10662 aop = newAsmop (0);
10663 preg = getFreePtr (ic, &aop, FALSE);
10664 emitcode ("mov", "%s,%s",
10666 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10667 rname = preg->name;
10670 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10672 aopOp (right, ic, FALSE, FALSE);
10674 /* if bitfield then unpack the bits */
10675 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10676 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10679 /* we have can just get the values */
10680 int size = AOP_SIZE (right);
10685 MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10687 emitcode ("movx", "@%s,a", rname);
10690 emitcode ("inc", "%s", rname);
10696 /* now some housekeeping stuff */
10699 if (pi) aopPut (AOP (result),rname,0);
10700 /* we had to allocate for this iCode */
10701 freeAsmop (NULL, aop, ic, TRUE);
10705 /* we did not allocate which means left
10706 already in a pointer register, then
10707 if size > 0 && this could be used again
10708 we have to point it back to where it
10710 if (AOP_SIZE (right) > 1 &&
10711 !OP_SYMBOL (result)->remat &&
10712 (OP_SYMBOL (result)->liveTo > ic->seq ||
10716 int size = AOP_SIZE (right) - 1;
10718 emitcode ("dec", "%s", rname);
10723 if (pi) pi->generated = 1;
10724 freeAsmop (result, NULL, ic, TRUE);
10725 freeAsmop (right, NULL, ic, TRUE);
10730 /*-----------------------------------------------------------------*/
10731 /* genFarPointerSet - set value from far space */
10732 /*-----------------------------------------------------------------*/
10734 genFarPointerSet (operand * right,
10735 operand * result, iCode * ic, iCode *pi)
10737 int size, offset, dopi=1;
10738 sym_link *retype = getSpec (operandType (right));
10739 sym_link *letype = getSpec (operandType (result));
10741 aopOp (result, ic, FALSE, FALSE);
10743 /* if the operand is already in dptr
10744 then we do nothing else we move the value to dptr */
10745 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10747 /* if this is remateriazable */
10748 if (AOP_TYPE (result) == AOP_IMMD)
10749 emitcode ("mov", "dptr,%s",
10750 aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10753 /* we need to get it byte by byte */
10754 _startLazyDPSEvaluation ();
10755 if (AOP_TYPE (result) != AOP_DPTR)
10757 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10758 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10759 if (options.model == MODEL_FLAT24)
10760 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10764 /* We need to generate a load to DPTR indirect through DPTR. */
10765 D (emitcode (";", "genFarPointerSet -- indirection special case."););
10767 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10768 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10769 if (options.model == MODEL_FLAT24)
10770 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10771 emitcode ("pop", "dph");
10772 emitcode ("pop", "dpl");
10775 _endLazyDPSEvaluation ();
10778 /* so dptr know contains the address */
10779 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10781 /* if bit then unpack */
10782 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10783 if (AOP_INDPTRn(result)) {
10784 genSetDPTR(AOP(result)->aopu.dptr);
10786 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10787 if (AOP_INDPTRn(result)) {
10791 size = AOP_SIZE (right);
10793 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10795 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10797 genSetDPTR(AOP(result)->aopu.dptr);
10798 emitcode ("movx", "@dptr,a");
10799 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10800 emitcode ("inc", "dptr");
10804 _startLazyDPSEvaluation ();
10806 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10808 if (AOP_INDPTRn(result)) {
10809 genSetDPTR(AOP(result)->aopu.dptr);
10815 emitcode ("movx", "@dptr,a");
10816 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10817 emitcode ("inc", "dptr");
10819 _endLazyDPSEvaluation ();
10823 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10824 if (!AOP_INDPTRn(result)) {
10825 _startLazyDPSEvaluation ();
10827 aopPut (AOP(result),"dpl",0);
10828 aopPut (AOP(result),"dph",1);
10829 if (options.model == MODEL_FLAT24)
10830 aopPut (AOP(result),"dpx",2);
10832 _endLazyDPSEvaluation ();
10835 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10836 AOP_SIZE(right) > 1 &&
10837 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10839 size = AOP_SIZE (right) - 1;
10840 if (AOP_INDPTRn(result)) {
10841 genSetDPTR(AOP(result)->aopu.dptr);
10843 while (size--) emitcode ("lcall","__decdptr");
10844 if (AOP_INDPTRn(result)) {
10848 freeAsmop (result, NULL, ic, TRUE);
10849 freeAsmop (right, NULL, ic, TRUE);
10852 /*-----------------------------------------------------------------*/
10853 /* genGenPointerSet - set value from generic pointer space */
10854 /*-----------------------------------------------------------------*/
10856 genGenPointerSet (operand * right,
10857 operand * result, iCode * ic, iCode *pi)
10860 sym_link *retype = getSpec (operandType (right));
10861 sym_link *letype = getSpec (operandType (result));
10863 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10865 /* if the operand is already in dptr
10866 then we do nothing else we move the value to dptr */
10867 if (AOP_TYPE (result) != AOP_STR)
10869 _startLazyDPSEvaluation ();
10870 /* if this is remateriazable */
10871 if (AOP_TYPE (result) == AOP_IMMD)
10873 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10874 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10876 MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10881 "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10885 { /* we need to get it byte by byte */
10886 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10887 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10888 if (options.model == MODEL_FLAT24) {
10889 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10890 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10892 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10895 _endLazyDPSEvaluation ();
10897 /* so dptr + b now contains the address */
10899 aopOp (right, ic, FALSE, TRUE);
10903 /* if bit then unpack */
10904 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10906 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10910 size = AOP_SIZE (right);
10913 _startLazyDPSEvaluation ();
10918 // Set two bytes at a time, passed in _AP & A.
10919 // dptr will be incremented ONCE by __gptrputWord.
10921 // Note: any change here must be coordinated
10922 // with the implementation of __gptrputWord
10923 // in device/lib/_gptrput.c
10924 emitcode("mov", "_ap, %s",
10925 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10926 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10930 emitcode ("lcall", "__gptrputWord");
10935 // Only one byte to put.
10936 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10940 emitcode ("lcall", "__gptrput");
10943 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10945 emitcode ("inc", "dptr");
10948 _endLazyDPSEvaluation ();
10951 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10952 _startLazyDPSEvaluation ();
10954 aopPut (AOP(result),"dpl",0);
10955 aopPut (AOP(result),"dph",1);
10956 if (options.model == MODEL_FLAT24) {
10957 aopPut (AOP(result),"dpx",2);
10958 aopPut (AOP(result),"b",3);
10960 aopPut (AOP(result),"b",2);
10962 _endLazyDPSEvaluation ();
10965 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10966 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10968 size = AOP_SIZE (right) - 1;
10969 while (size--) emitcode ("lcall","__decdptr");
10971 freeAsmop (result, NULL, ic, TRUE);
10972 freeAsmop (right, NULL, ic, TRUE);
10975 /*-----------------------------------------------------------------*/
10976 /* genPointerSet - stores the value into a pointer location */
10977 /*-----------------------------------------------------------------*/
10979 genPointerSet (iCode * ic, iCode *pi)
10981 operand *right, *result;
10982 sym_link *type, *etype;
10985 D (emitcode (";", "genPointerSet "););
10987 right = IC_RIGHT (ic);
10988 result = IC_RESULT (ic);
10990 /* depending on the type of pointer we need to
10991 move it to the correct pointer register */
10992 type = operandType (result);
10993 etype = getSpec (type);
10994 /* if left is of type of pointer then it is simple */
10995 if (IS_PTR (type) && !IS_FUNC (type->next))
10997 p_type = DCL_TYPE (type);
11001 /* we have to go by the storage class */
11002 p_type = PTR_TYPE (SPEC_OCLS (etype));
11004 /* special case when cast remat */
11005 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
11006 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
11007 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
11008 type = operandType (result);
11009 p_type = DCL_TYPE (type);
11012 /* now that we have the pointer type we assign
11013 the pointer values */
11019 genNearPointerSet (right, result, ic, pi);
11023 genPagedPointerSet (right, result, ic, pi);
11027 genFarPointerSet (right, result, ic, pi);
11031 genGenPointerSet (right, result, ic, pi);
11035 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11036 "genPointerSet: illegal pointer type");
11041 /*-----------------------------------------------------------------*/
11042 /* genIfx - generate code for Ifx statement */
11043 /*-----------------------------------------------------------------*/
11045 genIfx (iCode * ic, iCode * popIc)
11047 operand *cond = IC_COND (ic);
11050 D (emitcode (";", "genIfx "););
11052 aopOp (cond, ic, FALSE, FALSE);
11054 /* get the value into acc */
11055 if (AOP_TYPE (cond) != AOP_CRY)
11064 /* the result is now in the accumulator */
11065 freeAsmop (cond, NULL, ic, TRUE);
11067 /* if there was something to be popped then do it */
11071 /* if the condition is a bit variable */
11072 if (isbit && IS_ITEMP (cond) &&
11075 genIfxJump (ic, SPIL_LOC (cond)->rname);
11077 else if (isbit && !IS_ITEMP (cond))
11079 genIfxJump (ic, OP_SYMBOL (cond)->rname);
11083 genIfxJump (ic, "a");
11089 /*-----------------------------------------------------------------*/
11090 /* genAddrOf - generates code for address of */
11091 /*-----------------------------------------------------------------*/
11093 genAddrOf (iCode * ic)
11095 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11098 D (emitcode (";", "genAddrOf ");
11101 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11103 /* if the operand is on the stack then we
11104 need to get the stack offset of this
11106 if (sym->onStack) {
11108 /* if 10 bit stack */
11109 if (options.stack10bit) {
11113 tsprintf(buff, sizeof(buff),
11114 "#!constbyte",(options.stack_loc >> 16) & 0xff);
11115 /* if it has an offset then we need to compute it */
11116 /* emitcode ("subb", "a,#!constbyte", */
11117 /* -((sym->stack < 0) ? */
11118 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11119 /* ((short) sym->stack)) & 0xff); */
11120 /* emitcode ("mov","b,a"); */
11121 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
11122 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11123 /* ((short) sym->stack)) >> 8) & 0xff); */
11125 emitcode ("mov", "a,_bpx");
11126 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
11127 ((char) (sym->stack - _G.nRegsSaved)) :
11128 ((char) sym->stack )) & 0xff);
11129 emitcode ("mov", "b,a");
11130 emitcode ("mov", "a,_bpx+1");
11132 offset = (((sym->stack < 0) ?
11133 ((short) (sym->stack - _G.nRegsSaved)) :
11134 ((short) sym->stack )) >> 8) & 0xff;
11136 emitcode ("addc","a,#!constbyte", offset);
11138 aopPut (AOP (IC_RESULT (ic)), "b", 0);
11139 aopPut (AOP (IC_RESULT (ic)), "a", 1);
11140 aopPut (AOP (IC_RESULT (ic)), buff, 2);
11142 /* we can just move _bp */
11143 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
11144 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
11145 aopPut (AOP (IC_RESULT (ic)), buff, 2);
11148 /* if it has an offset then we need to compute it */
11150 emitcode ("mov", "a,_bp");
11151 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
11152 aopPut (AOP (IC_RESULT (ic)), "a", 0);
11154 /* we can just move _bp */
11155 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
11157 /* fill the result with zero */
11158 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11161 if (options.stack10bit && size < (FPTRSIZE - 1)) {
11163 "*** warning: pointer to stack var truncated.\n");
11168 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
11174 /* object not on stack then we need the name */
11175 size = AOP_SIZE (IC_RESULT (ic));
11180 char s[SDCC_NAME_MAX];
11184 tsprintf(s, sizeof(s), "#!his",sym->rname);
11187 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
11190 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
11192 default: /* should not need this (just in case) */
11193 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
11200 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11203 aopPut (AOP (IC_RESULT (ic)), s, offset++);
11207 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11211 #if 0 // obsolete, and buggy for != xdata
11212 /*-----------------------------------------------------------------*/
11213 /* genArrayInit - generates code for address of */
11214 /*-----------------------------------------------------------------*/
11216 genArrayInit (iCode * ic)
11218 literalList *iLoop;
11220 int elementSize = 0, eIndex;
11221 unsigned val, lastVal;
11223 operand *left=IC_LEFT(ic);
11225 D (emitcode (";", "genArrayInit "););
11227 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
11229 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
11231 // Load immediate value into DPTR.
11232 emitcode("mov", "dptr, %s",
11233 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
11235 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
11238 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11239 "Unexpected operand to genArrayInit.\n");
11242 // a regression because of SDCCcse.c:1.52
11243 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
11244 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
11245 if (options.model == MODEL_FLAT24)
11246 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
11250 type = operandType(IC_LEFT(ic));
11252 if (type && type->next)
11254 elementSize = getSize(type->next);
11258 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11259 "can't determine element size in genArrayInit.\n");
11263 iLoop = IC_ARRAYILIST(ic);
11268 bool firstpass = TRUE;
11270 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
11271 iLoop->count, (int)iLoop->literalValue, elementSize);
11277 symbol *tlbl = NULL;
11279 count = ix > 256 ? 256 : ix;
11283 tlbl = newiTempLabel (NULL);
11284 if (firstpass || (count & 0xff))
11286 emitcode("mov", "b, #!constbyte", count & 0xff);
11289 emitcode ("", "!tlabeldef", tlbl->key + 100);
11294 for (eIndex = 0; eIndex < elementSize; eIndex++)
11296 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
11297 if (val != lastVal)
11299 emitcode("mov", "a, #!constbyte", val);
11303 emitcode("movx", "@dptr, a");
11304 emitcode("inc", "dptr");
11309 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
11315 iLoop = iLoop->next;
11318 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
11322 /*-----------------------------------------------------------------*/
11323 /* genFarFarAssign - assignment when both are in far space */
11324 /*-----------------------------------------------------------------*/
11326 genFarFarAssign (operand * result, operand * right, iCode * ic)
11328 int size = AOP_SIZE (right);
11330 symbol *rSym = NULL;
11334 /* quick & easy case. */
11335 D(emitcode(";","genFarFarAssign (1 byte case)"););
11336 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
11337 freeAsmop (right, NULL, ic, FALSE);
11338 /* now assign DPTR to result */
11340 aopOp(result, ic, FALSE, FALSE);
11342 aopPut(AOP(result), "a", 0);
11343 freeAsmop(result, NULL, ic, FALSE);
11347 /* See if we've got an underlying symbol to abuse. */
11348 if (IS_SYMOP(result) && OP_SYMBOL(result))
11350 if (IS_TRUE_SYMOP(result))
11352 rSym = OP_SYMBOL(result);
11354 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
11356 rSym = OP_SYMBOL(result)->usl.spillLoc;
11360 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
11362 /* We can use the '390 auto-toggle feature to good effect here. */
11364 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
11365 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11366 emitcode ("mov", "dptr,#%s", rSym->rname);
11367 /* DP2 = result, DP1 = right, DP1 is current. */
11370 emitcode("movx", "a,@dptr");
11371 emitcode("movx", "@dptr,a");
11374 emitcode("inc", "dptr");
11375 emitcode("inc", "dptr");
11378 emitcode("mov", "dps,#0");
11379 freeAsmop (right, NULL, ic, FALSE);
11381 some alternative code for processors without auto-toggle
11382 no time to test now, so later well put in...kpb
11383 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
11384 emitcode("mov", "dps,#1"); /* Select DPTR2. */
11385 emitcode ("mov", "dptr,#%s", rSym->rname);
11386 /* DP2 = result, DP1 = right, DP1 is current. */
11390 emitcode("movx", "a,@dptr");
11392 emitcode("inc", "dptr");
11393 emitcode("inc", "dps");
11394 emitcode("movx", "@dptr,a");
11396 emitcode("inc", "dptr");
11397 emitcode("inc", "dps");
11399 emitcode("mov", "dps,#0");
11400 freeAsmop (right, NULL, ic, FALSE);
11405 D (emitcode (";", "genFarFarAssign"););
11406 aopOp (result, ic, TRUE, TRUE);
11408 _startLazyDPSEvaluation ();
11412 aopPut (AOP (result),
11413 aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
11416 _endLazyDPSEvaluation ();
11417 freeAsmop (result, NULL, ic, FALSE);
11418 freeAsmop (right, NULL, ic, FALSE);
11422 /*-----------------------------------------------------------------*/
11423 /* genAssign - generate code for assignment */
11424 /*-----------------------------------------------------------------*/
11426 genAssign (iCode * ic)
11428 operand *result, *right;
11430 unsigned long lit = 0L;
11432 D (emitcode (";", "genAssign ");
11435 result = IC_RESULT (ic);
11436 right = IC_RIGHT (ic);
11438 /* if they are the same */
11439 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11442 aopOp (right, ic, FALSE, FALSE);
11444 emitcode (";", "genAssign: resultIsFar = %s",
11445 isOperandInFarSpace (result) ?
11448 /* special case both in far space */
11449 if ((AOP_TYPE (right) == AOP_DPTR ||
11450 AOP_TYPE (right) == AOP_DPTR2) &&
11451 /* IS_TRUE_SYMOP(result) && */
11452 isOperandInFarSpace (result))
11454 genFarFarAssign (result, right, ic);
11458 aopOp (result, ic, TRUE, FALSE);
11460 /* if they are the same registers */
11461 if (sameRegs (AOP (right), AOP (result)))
11464 /* if the result is a bit */
11465 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
11467 /* if the right size is a literal then
11468 we know what the value is */
11469 if (AOP_TYPE (right) == AOP_LIT)
11471 if (((int) operandLitValue (right)))
11472 aopPut (AOP (result), one, 0);
11474 aopPut (AOP (result), zero, 0);
11478 /* the right is also a bit variable */
11479 if (AOP_TYPE (right) == AOP_CRY)
11481 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11482 aopPut (AOP (result), "c", 0);
11486 /* we need to or */
11488 aopPut (AOP (result), "a", 0);
11492 /* bit variables done */
11494 size = AOP_SIZE (result);
11496 if (AOP_TYPE (right) == AOP_LIT)
11497 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11500 (AOP_TYPE (result) != AOP_REG) &&
11501 (AOP_TYPE (right) == AOP_LIT) &&
11502 !IS_FLOAT (operandType (right)))
11504 _startLazyDPSEvaluation ();
11505 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
11507 aopPut (AOP (result),
11508 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11513 /* And now fill the rest with zeros. */
11516 emitcode ("clr", "a");
11520 aopPut (AOP (result), "a", offset++);
11522 _endLazyDPSEvaluation ();
11526 _startLazyDPSEvaluation ();
11529 aopPut (AOP (result),
11530 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11534 _endLazyDPSEvaluation ();
11538 freeAsmop (right, NULL, ic, FALSE);
11539 freeAsmop (result, NULL, ic, TRUE);
11542 /*-----------------------------------------------------------------*/
11543 /* genJumpTab - generates code for jump table */
11544 /*-----------------------------------------------------------------*/
11546 genJumpTab (iCode * ic)
11551 D (emitcode (";", "genJumpTab ");
11554 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11555 /* get the condition into accumulator */
11556 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11558 /* multiply by four! */
11559 emitcode ("add", "a,acc");
11560 emitcode ("add", "a,acc");
11561 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11563 jtab = newiTempLabel (NULL);
11564 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11565 emitcode ("jmp", "@a+dptr");
11566 emitcode ("", "!tlabeldef", jtab->key + 100);
11567 /* now generate the jump labels */
11568 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11569 jtab = setNextItem (IC_JTLABELS (ic)))
11570 emitcode ("ljmp", "!tlabel", jtab->key + 100);
11574 /*-----------------------------------------------------------------*/
11575 /* genCast - gen code for casting */
11576 /*-----------------------------------------------------------------*/
11578 genCast (iCode * ic)
11580 operand *result = IC_RESULT (ic);
11581 sym_link *ctype = operandType (IC_LEFT (ic));
11582 sym_link *rtype = operandType (IC_RIGHT (ic));
11583 operand *right = IC_RIGHT (ic);
11586 D (emitcode (";", "genCast "););
11588 /* if they are equivalent then do nothing */
11589 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11592 aopOp (right, ic, FALSE, AOP_IS_STR (result));
11593 aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
11595 /* if the result is a bit */
11596 if (IS_BITVAR (OP_SYMBOL (result)->type)
11597 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11599 /* if the right size is a literal then
11600 we know what the value is */
11601 if (AOP_TYPE (right) == AOP_LIT)
11603 if (((int) operandLitValue (right)))
11604 aopPut (AOP (result), one, 0);
11606 aopPut (AOP (result), zero, 0);
11611 /* the right is also a bit variable */
11612 if (AOP_TYPE (right) == AOP_CRY)
11614 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11615 aopPut (AOP (result), "c", 0);
11619 /* we need to or */
11621 aopPut (AOP (result), "a", 0);
11625 /* if they are the same size : or less */
11626 if (AOP_SIZE (result) <= AOP_SIZE (right))
11629 /* if they are in the same place */
11630 if (sameRegs (AOP (right), AOP (result)))
11633 /* if they in different places then copy */
11634 size = AOP_SIZE (result);
11636 _startLazyDPSEvaluation ();
11639 aopPut (AOP (result),
11640 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11644 _endLazyDPSEvaluation ();
11649 /* if the result is of type pointer */
11650 if (IS_PTR (ctype))
11654 sym_link *type = operandType (right);
11656 /* pointer to generic pointer */
11657 if (IS_GENPTR (ctype))
11661 p_type = DCL_TYPE (type);
11665 #if OLD_CAST_BEHAVIOR
11666 /* KV: we are converting a non-pointer type to
11667 * a generic pointer. This (ifdef'd out) code
11668 * says that the resulting generic pointer
11669 * should have the same class as the storage
11670 * location of the non-pointer variable.
11672 * For example, converting an int (which happens
11673 * to be stored in DATA space) to a pointer results
11674 * in a DATA generic pointer; if the original int
11675 * in XDATA space, so will be the resulting pointer.
11677 * I don't like that behavior, and thus this change:
11678 * all such conversions will be forced to XDATA and
11679 * throw a warning. If you want some non-XDATA
11680 * type, or you want to suppress the warning, you
11681 * must go through an intermediate cast, like so:
11683 * char _generic *gp = (char _xdata *)(intVar);
11685 sym_link *etype = getSpec (type);
11687 /* we have to go by the storage class */
11688 if (SPEC_OCLS (etype) != generic)
11690 p_type = PTR_TYPE (SPEC_OCLS (etype));
11695 /* Converting unknown class (i.e. register variable)
11696 * to generic pointer. This is not good, but
11697 * we'll make a guess (and throw a warning).
11700 werror (W_INT_TO_GEN_PTR_CAST);
11704 /* the first two bytes are known */
11705 size = GPTRSIZE - 1;
11707 _startLazyDPSEvaluation ();
11710 aopPut (AOP (result),
11711 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11715 _endLazyDPSEvaluation ();
11717 /* the last byte depending on type */
11719 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11724 // pointerTypeToGPByte will have bitched.
11728 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11729 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11734 /* just copy the pointers */
11735 size = AOP_SIZE (result);
11737 _startLazyDPSEvaluation ();
11740 aopPut (AOP (result),
11741 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11745 _endLazyDPSEvaluation ();
11749 /* so we now know that the size of destination is greater
11750 than the size of the source */
11751 /* we move to result for the size of source */
11752 size = AOP_SIZE (right);
11754 _startLazyDPSEvaluation ();
11757 aopPut (AOP (result),
11758 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11762 _endLazyDPSEvaluation ();
11764 /* now depending on the sign of the source && destination */
11765 size = AOP_SIZE (result) - AOP_SIZE (right);
11766 /* if unsigned or not an integral type */
11767 /* also, if the source is a bit, we don't need to sign extend, because
11768 * it can't possibly have set the sign bit.
11770 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11774 aopPut (AOP (result), zero, offset++);
11779 /* we need to extend the sign :{ */
11780 MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11781 FALSE, FALSE, NULL));
11782 emitcode ("rlc", "a");
11783 emitcode ("subb", "a,acc");
11785 aopPut (AOP (result), "a", offset++);
11788 /* we are done hurray !!!! */
11791 freeAsmop (right, NULL, ic, TRUE);
11792 freeAsmop (result, NULL, ic, TRUE);
11796 /*-----------------------------------------------------------------*/
11797 /* genDjnz - generate decrement & jump if not zero instrucion */
11798 /*-----------------------------------------------------------------*/
11800 genDjnz (iCode * ic, iCode * ifx)
11802 symbol *lbl, *lbl1;
11806 /* if the if condition has a false label
11807 then we cannot save */
11808 if (IC_FALSE (ifx))
11811 /* if the minus is not of the form
11813 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11814 !IS_OP_LITERAL (IC_RIGHT (ic)))
11817 if (operandLitValue (IC_RIGHT (ic)) != 1)
11820 /* if the size of this greater than one then no
11822 if (getSize (operandType (IC_RESULT (ic))) > 1)
11825 /* otherwise we can save BIG */
11826 D(emitcode(";", "genDjnz"););
11828 lbl = newiTempLabel (NULL);
11829 lbl1 = newiTempLabel (NULL);
11831 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11833 if (AOP_NEEDSACC(IC_RESULT(ic)))
11835 /* If the result is accessed indirectly via
11836 * the accumulator, we must explicitly write
11837 * it back after the decrement.
11839 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11841 if (strcmp(rByte, "a"))
11843 /* Something is hopelessly wrong */
11844 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11845 __FILE__, __LINE__);
11846 /* We can just give up; the generated code will be inefficient,
11847 * but what the hey.
11849 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11852 emitcode ("dec", "%s", rByte);
11853 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11854 emitcode ("jnz", "!tlabel", lbl->key + 100);
11856 else if (IS_AOP_PREG (IC_RESULT (ic)))
11858 emitcode ("dec", "%s",
11859 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11860 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11861 emitcode ("jnz", "!tlabel", lbl->key + 100);
11865 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11868 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11869 emitcode ("", "!tlabeldef", lbl->key + 100);
11870 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11871 emitcode ("", "!tlabeldef", lbl1->key + 100);
11873 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11874 ifx->generated = 1;
11878 /*-----------------------------------------------------------------*/
11879 /* genReceive - generate code for a receive iCode */
11880 /*-----------------------------------------------------------------*/
11882 genReceive (iCode * ic)
11884 int size = getSize (operandType (IC_RESULT (ic)));
11888 D (emitcode (";", "genReceive "););
11890 if (ic->argreg == 1)
11892 /* first parameter */
11893 if (AOP_IS_STR(IC_RESULT(ic)))
11895 /* Nothing to do: it's already in the proper place. */
11902 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11903 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11904 IS_TRUE_SYMOP (IC_RESULT (ic)));
11907 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11910 /* Sanity checking... */
11911 if (AOP_USESDPTR(IC_RESULT(ic)))
11913 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11914 "genReceive got unexpected DPTR.");
11916 assignResultValue (IC_RESULT (ic));
11921 /* second receive onwards */
11922 /* this gets a little tricky since unused recevies will be
11923 eliminated, we have saved the reg in the type field . and
11924 we use that to figure out which register to use */
11925 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11926 rb1off = ic->argreg;
11929 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11932 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11935 /*-----------------------------------------------------------------*/
11936 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11937 /*-----------------------------------------------------------------*/
11938 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11940 operand *from , *to , *count;
11945 /* we know it has to be 3 parameters */
11946 assert (nparms == 3);
11948 rsave = newBitVect(16);
11949 /* save DPTR if it needs to be saved */
11950 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11951 if (bitVectBitValue(ic->rMask,i))
11952 rsave = bitVectSetBit(rsave,i);
11954 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11955 ds390_rUmaskForOp (IC_RESULT(ic))));
11962 aopOp (from, ic->next, FALSE, FALSE);
11964 /* get from into DPTR1 */
11965 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11966 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11967 if (options.model == MODEL_FLAT24) {
11968 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11971 freeAsmop (from, NULL, ic, FALSE);
11972 aopOp (to, ic, FALSE, FALSE);
11973 /* get "to" into DPTR */
11974 /* if the operand is already in dptr
11975 then we do nothing else we move the value to dptr */
11976 if (AOP_TYPE (to) != AOP_STR) {
11977 /* if already in DPTR then we need to push */
11978 if (AOP_TYPE(to) == AOP_DPTR) {
11979 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11980 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11981 if (options.model == MODEL_FLAT24)
11982 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11983 emitcode ("pop", "dph");
11984 emitcode ("pop", "dpl");
11986 _startLazyDPSEvaluation ();
11987 /* if this is remateriazable */
11988 if (AOP_TYPE (to) == AOP_IMMD) {
11989 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11990 } else { /* we need to get it byte by byte */
11991 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11992 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11993 if (options.model == MODEL_FLAT24) {
11994 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11997 _endLazyDPSEvaluation ();
12000 freeAsmop (to, NULL, ic, FALSE);
12001 _G.dptrInUse = _G.dptr1InUse = 1;
12002 aopOp (count, ic->next->next, FALSE,FALSE);
12003 lbl =newiTempLabel(NULL);
12005 /* now for the actual copy */
12006 if (AOP_TYPE(count) == AOP_LIT &&
12007 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12008 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12010 emitcode ("lcall","__bi_memcpyc2x_s");
12012 emitcode ("lcall","__bi_memcpyx2x_s");
12014 freeAsmop (count, NULL, ic, FALSE);
12016 symbol *lbl1 = newiTempLabel(NULL);
12018 emitcode (";"," Auto increment but no djnz");
12019 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12020 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12021 freeAsmop (count, NULL, ic, FALSE);
12022 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12023 emitcode ("","!tlabeldef",lbl->key+100);
12025 emitcode ("clr","a");
12026 emitcode ("movc", "a,@a+dptr");
12028 emitcode ("movx", "a,@dptr");
12029 emitcode ("movx", "@dptr,a");
12030 emitcode ("inc", "dptr");
12031 emitcode ("inc", "dptr");
12032 emitcode ("mov","a,b");
12033 emitcode ("orl","a,_ap");
12034 emitcode ("jz","!tlabel",lbl1->key+100);
12035 emitcode ("mov","a,_ap");
12036 emitcode ("add","a,#!constbyte",0xFF);
12037 emitcode ("mov","_ap,a");
12038 emitcode ("mov","a,b");
12039 emitcode ("addc","a,#!constbyte",0xFF);
12040 emitcode ("mov","b,a");
12041 emitcode ("sjmp","!tlabel",lbl->key+100);
12042 emitcode ("","!tlabeldef",lbl1->key+100);
12044 emitcode ("mov", "dps,#0");
12045 _G.dptrInUse = _G.dptr1InUse = 0;
12046 unsavermask(rsave);
12050 /*-----------------------------------------------------------------*/
12051 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
12052 /*-----------------------------------------------------------------*/
12053 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
12055 operand *from , *to , *count;
12060 /* we know it has to be 3 parameters */
12061 assert (nparms == 3);
12063 rsave = newBitVect(16);
12064 /* save DPTR if it needs to be saved */
12065 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12066 if (bitVectBitValue(ic->rMask,i))
12067 rsave = bitVectSetBit(rsave,i);
12069 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12070 ds390_rUmaskForOp (IC_RESULT(ic))));
12077 aopOp (from, ic->next, FALSE, FALSE);
12079 /* get from into DPTR1 */
12080 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12081 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12082 if (options.model == MODEL_FLAT24) {
12083 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12086 freeAsmop (from, NULL, ic, FALSE);
12087 aopOp (to, ic, FALSE, FALSE);
12088 /* get "to" into DPTR */
12089 /* if the operand is already in dptr
12090 then we do nothing else we move the value to dptr */
12091 if (AOP_TYPE (to) != AOP_STR) {
12092 /* if already in DPTR then we need to push */
12093 if (AOP_TYPE(to) == AOP_DPTR) {
12094 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12095 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12096 if (options.model == MODEL_FLAT24)
12097 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12098 emitcode ("pop", "dph");
12099 emitcode ("pop", "dpl");
12101 _startLazyDPSEvaluation ();
12102 /* if this is remateriazable */
12103 if (AOP_TYPE (to) == AOP_IMMD) {
12104 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12105 } else { /* we need to get it byte by byte */
12106 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12107 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12108 if (options.model == MODEL_FLAT24) {
12109 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12112 _endLazyDPSEvaluation ();
12115 freeAsmop (to, NULL, ic, FALSE);
12116 _G.dptrInUse = _G.dptr1InUse = 1;
12117 aopOp (count, ic->next->next, FALSE,FALSE);
12118 lbl =newiTempLabel(NULL);
12119 lbl2 =newiTempLabel(NULL);
12121 /* now for the actual compare */
12122 if (AOP_TYPE(count) == AOP_LIT &&
12123 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12124 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12126 emitcode("lcall","__bi_memcmpc2x_s");
12128 emitcode("lcall","__bi_memcmpx2x_s");
12129 freeAsmop (count, NULL, ic, FALSE);
12130 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12131 aopPut(AOP(IC_RESULT(ic)),"a",0);
12132 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12134 symbol *lbl1 = newiTempLabel(NULL);
12136 emitcode("push","ar0");
12137 emitcode (";"," Auto increment but no djnz");
12138 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12139 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12140 freeAsmop (count, NULL, ic, FALSE);
12141 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12142 emitcode ("","!tlabeldef",lbl->key+100);
12144 emitcode ("clr","a");
12145 emitcode ("movc", "a,@a+dptr");
12147 emitcode ("movx", "a,@dptr");
12148 emitcode ("mov","r0,a");
12149 emitcode ("movx", "a,@dptr");
12150 emitcode ("clr","c");
12151 emitcode ("subb","a,r0");
12152 emitcode ("jnz","!tlabel",lbl2->key+100);
12153 emitcode ("inc", "dptr");
12154 emitcode ("inc", "dptr");
12155 emitcode ("mov","a,b");
12156 emitcode ("orl","a,_ap");
12157 emitcode ("jz","!tlabel",lbl1->key+100);
12158 emitcode ("mov","a,_ap");
12159 emitcode ("add","a,#!constbyte",0xFF);
12160 emitcode ("mov","_ap,a");
12161 emitcode ("mov","a,b");
12162 emitcode ("addc","a,#!constbyte",0xFF);
12163 emitcode ("mov","b,a");
12164 emitcode ("sjmp","!tlabel",lbl->key+100);
12165 emitcode ("","!tlabeldef",lbl1->key+100);
12166 emitcode ("clr","a");
12167 emitcode ("","!tlabeldef",lbl2->key+100);
12168 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12169 aopPut(AOP(IC_RESULT(ic)),"a",0);
12170 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12171 emitcode("pop","ar0");
12172 emitcode ("mov", "dps,#0");
12174 _G.dptrInUse = _G.dptr1InUse = 0;
12175 unsavermask(rsave);
12179 /*-----------------------------------------------------------------*/
12180 /* genInp - gen code for __builtin_inp read data from a mem mapped */
12181 /* port, first parameter output area second parameter pointer to */
12182 /* port third parameter count */
12183 /*-----------------------------------------------------------------*/
12184 static void genInp( iCode *ic, int nparms, operand **parms)
12186 operand *from , *to , *count;
12191 /* we know it has to be 3 parameters */
12192 assert (nparms == 3);
12194 rsave = newBitVect(16);
12195 /* save DPTR if it needs to be saved */
12196 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12197 if (bitVectBitValue(ic->rMask,i))
12198 rsave = bitVectSetBit(rsave,i);
12200 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12201 ds390_rUmaskForOp (IC_RESULT(ic))));
12208 aopOp (from, ic->next, FALSE, FALSE);
12210 /* get from into DPTR1 */
12211 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12212 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12213 if (options.model == MODEL_FLAT24) {
12214 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12217 freeAsmop (from, NULL, ic, FALSE);
12218 aopOp (to, ic, FALSE, FALSE);
12219 /* get "to" into DPTR */
12220 /* if the operand is already in dptr
12221 then we do nothing else we move the value to dptr */
12222 if (AOP_TYPE (to) != AOP_STR) {
12223 /* if already in DPTR then we need to push */
12224 if (AOP_TYPE(to) == AOP_DPTR) {
12225 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12226 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12227 if (options.model == MODEL_FLAT24)
12228 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12229 emitcode ("pop", "dph");
12230 emitcode ("pop", "dpl");
12232 _startLazyDPSEvaluation ();
12233 /* if this is remateriazable */
12234 if (AOP_TYPE (to) == AOP_IMMD) {
12235 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12236 } else { /* we need to get it byte by byte */
12237 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12238 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12239 if (options.model == MODEL_FLAT24) {
12240 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12243 _endLazyDPSEvaluation ();
12246 freeAsmop (to, NULL, ic, FALSE);
12248 _G.dptrInUse = _G.dptr1InUse = 1;
12249 aopOp (count, ic->next->next, FALSE,FALSE);
12250 lbl =newiTempLabel(NULL);
12252 /* now for the actual copy */
12253 if (AOP_TYPE(count) == AOP_LIT &&
12254 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12255 emitcode (";","OH JOY auto increment with djnz (very fast)");
12256 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12257 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12258 freeAsmop (count, NULL, ic, FALSE);
12259 emitcode ("","!tlabeldef",lbl->key+100);
12260 emitcode ("movx", "a,@dptr"); /* read data from port */
12261 emitcode ("dec","dps"); /* switch to DPTR */
12262 emitcode ("movx", "@dptr,a"); /* save into location */
12263 emitcode ("inc", "dptr"); /* point to next area */
12264 emitcode ("inc","dps"); /* switch to DPTR2 */
12265 emitcode ("djnz","b,!tlabel",lbl->key+100);
12267 symbol *lbl1 = newiTempLabel(NULL);
12269 emitcode (";"," Auto increment but no djnz");
12270 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12271 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12272 freeAsmop (count, NULL, ic, FALSE);
12273 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12274 emitcode ("","!tlabeldef",lbl->key+100);
12275 emitcode ("movx", "a,@dptr");
12276 emitcode ("dec","dps"); /* switch to DPTR */
12277 emitcode ("movx", "@dptr,a");
12278 emitcode ("inc", "dptr");
12279 emitcode ("inc","dps"); /* switch to DPTR2 */
12280 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
12281 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
12282 emitcode ("mov","a,b");
12283 emitcode ("orl","a,_ap");
12284 emitcode ("jz","!tlabel",lbl1->key+100);
12285 emitcode ("mov","a,_ap");
12286 emitcode ("add","a,#!constbyte",0xFF);
12287 emitcode ("mov","_ap,a");
12288 emitcode ("mov","a,b");
12289 emitcode ("addc","a,#!constbyte",0xFF);
12290 emitcode ("mov","b,a");
12291 emitcode ("sjmp","!tlabel",lbl->key+100);
12292 emitcode ("","!tlabeldef",lbl1->key+100);
12294 emitcode ("mov", "dps,#0");
12295 _G.dptrInUse = _G.dptr1InUse = 0;
12296 unsavermask(rsave);
12300 /*-----------------------------------------------------------------*/
12301 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
12302 /* port, first parameter output area second parameter pointer to */
12303 /* port third parameter count */
12304 /*-----------------------------------------------------------------*/
12305 static void genOutp( iCode *ic, int nparms, operand **parms)
12307 operand *from , *to , *count;
12312 /* we know it has to be 3 parameters */
12313 assert (nparms == 3);
12315 rsave = newBitVect(16);
12316 /* save DPTR if it needs to be saved */
12317 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12318 if (bitVectBitValue(ic->rMask,i))
12319 rsave = bitVectSetBit(rsave,i);
12321 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12322 ds390_rUmaskForOp (IC_RESULT(ic))));
12329 aopOp (from, ic->next, FALSE, FALSE);
12331 /* get from into DPTR1 */
12332 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12333 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12334 if (options.model == MODEL_FLAT24) {
12335 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12338 freeAsmop (from, NULL, ic, FALSE);
12339 aopOp (to, ic, FALSE, FALSE);
12340 /* get "to" into DPTR */
12341 /* if the operand is already in dptr
12342 then we do nothing else we move the value to dptr */
12343 if (AOP_TYPE (to) != AOP_STR) {
12344 /* if already in DPTR then we need to push */
12345 if (AOP_TYPE(to) == AOP_DPTR) {
12346 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12347 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12348 if (options.model == MODEL_FLAT24)
12349 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12350 emitcode ("pop", "dph");
12351 emitcode ("pop", "dpl");
12353 _startLazyDPSEvaluation ();
12354 /* if this is remateriazable */
12355 if (AOP_TYPE (to) == AOP_IMMD) {
12356 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12357 } else { /* we need to get it byte by byte */
12358 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12359 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12360 if (options.model == MODEL_FLAT24) {
12361 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12364 _endLazyDPSEvaluation ();
12367 freeAsmop (to, NULL, ic, FALSE);
12369 _G.dptrInUse = _G.dptr1InUse = 1;
12370 aopOp (count, ic->next->next, FALSE,FALSE);
12371 lbl =newiTempLabel(NULL);
12373 /* now for the actual copy */
12374 if (AOP_TYPE(count) == AOP_LIT &&
12375 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12376 emitcode (";","OH JOY auto increment with djnz (very fast)");
12377 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12378 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12379 emitcode ("","!tlabeldef",lbl->key+100);
12380 emitcode ("movx", "a,@dptr"); /* read data from port */
12381 emitcode ("inc","dps"); /* switch to DPTR2 */
12382 emitcode ("movx", "@dptr,a"); /* save into location */
12383 emitcode ("inc", "dptr"); /* point to next area */
12384 emitcode ("dec","dps"); /* switch to DPTR */
12385 emitcode ("djnz","b,!tlabel",lbl->key+100);
12386 freeAsmop (count, NULL, ic, FALSE);
12388 symbol *lbl1 = newiTempLabel(NULL);
12390 emitcode (";"," Auto increment but no djnz");
12391 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12392 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12393 freeAsmop (count, NULL, ic, FALSE);
12394 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12395 emitcode ("","!tlabeldef",lbl->key+100);
12396 emitcode ("movx", "a,@dptr");
12397 emitcode ("inc", "dptr");
12398 emitcode ("inc","dps"); /* switch to DPTR2 */
12399 emitcode ("movx", "@dptr,a");
12400 emitcode ("dec","dps"); /* switch to DPTR */
12401 emitcode ("mov","a,b");
12402 emitcode ("orl","a,_ap");
12403 emitcode ("jz","!tlabel",lbl1->key+100);
12404 emitcode ("mov","a,_ap");
12405 emitcode ("add","a,#!constbyte",0xFF);
12406 emitcode ("mov","_ap,a");
12407 emitcode ("mov","a,b");
12408 emitcode ("addc","a,#!constbyte",0xFF);
12409 emitcode ("mov","b,a");
12410 emitcode ("sjmp","!tlabel",lbl->key+100);
12411 emitcode ("","!tlabeldef",lbl1->key+100);
12413 emitcode ("mov", "dps,#0");
12414 _G.dptrInUse = _G.dptr1InUse = 0;
12415 unsavermask(rsave);
12419 /*-----------------------------------------------------------------*/
12420 /* genSwapW - swap lower & high order bytes */
12421 /*-----------------------------------------------------------------*/
12422 static void genSwapW(iCode *ic, int nparms, operand **parms)
12426 assert (nparms==1);
12429 dest=IC_RESULT(ic);
12431 assert(getSize(operandType(src))==2);
12433 aopOp (src, ic, FALSE, FALSE);
12434 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
12436 MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
12438 freeAsmop (src, NULL, ic, FALSE);
12440 aopOp (dest,ic, FALSE, FALSE);
12441 aopPut(AOP(dest),"b",0);
12442 aopPut(AOP(dest),"a",1);
12443 freeAsmop (dest, NULL, ic, FALSE);
12446 /*-----------------------------------------------------------------*/
12447 /* genMemsetX - gencode for memSetX data */
12448 /*-----------------------------------------------------------------*/
12449 static void genMemsetX(iCode *ic, int nparms, operand **parms)
12451 operand *to , *val , *count;
12457 /* we know it has to be 3 parameters */
12458 assert (nparms == 3);
12464 /* save DPTR if it needs to be saved */
12465 rsave = newBitVect(16);
12466 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12467 if (bitVectBitValue(ic->rMask,i))
12468 rsave = bitVectSetBit(rsave,i);
12470 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12471 ds390_rUmaskForOp (IC_RESULT(ic))));
12474 aopOp (to, ic, FALSE, FALSE);
12475 /* get "to" into DPTR */
12476 /* if the operand is already in dptr
12477 then we do nothing else we move the value to dptr */
12478 if (AOP_TYPE (to) != AOP_STR) {
12479 /* if already in DPTR then we need to push */
12480 if (AOP_TYPE(to) == AOP_DPTR) {
12481 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12482 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12483 if (options.model == MODEL_FLAT24)
12484 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12485 emitcode ("pop", "dph");
12486 emitcode ("pop", "dpl");
12488 _startLazyDPSEvaluation ();
12489 /* if this is remateriazable */
12490 if (AOP_TYPE (to) == AOP_IMMD) {
12491 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12492 } else { /* we need to get it byte by byte */
12493 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12494 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12495 if (options.model == MODEL_FLAT24) {
12496 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12499 _endLazyDPSEvaluation ();
12502 freeAsmop (to, NULL, ic, FALSE);
12504 aopOp (val, ic->next->next, FALSE,FALSE);
12505 aopOp (count, ic->next->next, FALSE,FALSE);
12506 lbl =newiTempLabel(NULL);
12507 /* now for the actual copy */
12508 if (AOP_TYPE(count) == AOP_LIT &&
12509 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12510 l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
12511 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12513 emitcode ("","!tlabeldef",lbl->key+100);
12514 emitcode ("movx", "@dptr,a");
12515 emitcode ("inc", "dptr");
12516 emitcode ("djnz","b,!tlabel",lbl->key+100);
12518 symbol *lbl1 = newiTempLabel(NULL);
12520 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12521 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12522 emitcode ("","!tlabeldef",lbl->key+100);
12523 MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
12524 emitcode ("movx", "@dptr,a");
12525 emitcode ("inc", "dptr");
12526 emitcode ("mov","a,b");
12527 emitcode ("orl","a,_ap");
12528 emitcode ("jz","!tlabel",lbl1->key+100);
12529 emitcode ("mov","a,_ap");
12530 emitcode ("add","a,#!constbyte",0xFF);
12531 emitcode ("mov","_ap,a");
12532 emitcode ("mov","a,b");
12533 emitcode ("addc","a,#!constbyte",0xFF);
12534 emitcode ("mov","b,a");
12535 emitcode ("sjmp","!tlabel",lbl->key+100);
12536 emitcode ("","!tlabeldef",lbl1->key+100);
12538 freeAsmop (count, NULL, ic, FALSE);
12539 unsavermask(rsave);
12542 /*-----------------------------------------------------------------*/
12543 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12544 /*-----------------------------------------------------------------*/
12545 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12548 operand *pnum, *result;
12551 assert (nparms==1);
12552 /* save registers that need to be saved */
12553 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12554 ds390_rUmaskForOp (IC_RESULT(ic))));
12557 aopOp (pnum, ic, FALSE, FALSE);
12558 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12559 freeAsmop (pnum, NULL, ic, FALSE);
12560 emitcode ("lcall","NatLib_LoadPrimitive");
12561 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12562 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
12563 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12564 for (i = (size-1) ; i >= 0 ; i-- ) {
12565 emitcode ("push","a%s",javaRet[i]);
12567 for (i=0; i < size ; i++ ) {
12568 emitcode ("pop","a%s",
12569 aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12572 for (i = 0 ; i < size ; i++ ) {
12573 aopPut(AOP(result),javaRet[i],i);
12576 freeAsmop (result, NULL, ic, FALSE);
12577 unsavermask(rsave);
12580 /*-----------------------------------------------------------------*/
12581 /* genNatLibLoadPointer - calls TINI api function to load pointer */
12582 /*-----------------------------------------------------------------*/
12583 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12586 operand *pnum, *result;
12590 assert (nparms==1);
12591 /* save registers that need to be saved */
12592 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12593 ds390_rUmaskForOp (IC_RESULT(ic))));
12596 aopOp (pnum, ic, FALSE, FALSE);
12597 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12598 freeAsmop (pnum, NULL, ic, FALSE);
12599 emitcode ("lcall","NatLib_LoadPointer");
12600 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12601 if (AOP_TYPE(result)!=AOP_STR) {
12602 for (i = 0 ; i < size ; i++ ) {
12603 aopPut(AOP(result),fReturn[i],i);
12606 freeAsmop (result, NULL, ic, FALSE);
12607 unsavermask(rsave);
12610 /*-----------------------------------------------------------------*/
12611 /* genNatLibInstallStateBlock - */
12612 /*-----------------------------------------------------------------*/
12613 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
12614 operand **parms, const char *name)
12617 operand *psb, *handle;
12618 assert (nparms==2);
12620 /* save registers that need to be saved */
12621 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12622 ds390_rUmaskForOp (IC_RESULT(ic))));
12626 /* put pointer to state block into DPTR1 */
12627 aopOp (psb, ic, FALSE, FALSE);
12628 if (AOP_TYPE (psb) == AOP_IMMD) {
12629 emitcode ("mov","dps,#1");
12630 emitcode ("mov", "dptr,%s",
12631 aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12632 emitcode ("mov","dps,#0");
12634 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12635 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12636 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12638 freeAsmop (psb, NULL, ic, FALSE);
12640 /* put libraryID into DPTR */
12641 emitcode ("mov","dptr,#LibraryID");
12643 /* put handle into r3:r2 */
12644 aopOp (handle, ic, FALSE, FALSE);
12645 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12646 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12647 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12648 emitcode ("pop","ar3");
12649 emitcode ("pop","ar2");
12651 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12652 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12654 freeAsmop (psb, NULL, ic, FALSE);
12656 /* make the call */
12657 emitcode ("lcall","NatLib_Install%sStateBlock",name);
12659 /* put return value into place*/
12661 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12663 aopPut(AOP(IC_RESULT(ic)),"a",0);
12664 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12665 unsavermask(rsave);
12668 /*-----------------------------------------------------------------*/
12669 /* genNatLibRemoveStateBlock - */
12670 /*-----------------------------------------------------------------*/
12671 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12677 /* save registers that need to be saved */
12678 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12679 ds390_rUmaskForOp (IC_RESULT(ic))));
12681 /* put libraryID into DPTR */
12682 emitcode ("mov","dptr,#LibraryID");
12683 /* make the call */
12684 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12685 unsavermask(rsave);
12688 /*-----------------------------------------------------------------*/
12689 /* genNatLibGetStateBlock - */
12690 /*-----------------------------------------------------------------*/
12691 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12692 operand **parms,const char *name)
12695 symbol *lbl = newiTempLabel(NULL);
12698 /* save registers that need to be saved */
12699 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12700 ds390_rUmaskForOp (IC_RESULT(ic))));
12702 /* put libraryID into DPTR */
12703 emitcode ("mov","dptr,#LibraryID");
12704 /* make the call */
12705 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12706 emitcode ("jnz","!tlabel",lbl->key+100);
12708 /* put return value into place */
12709 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12710 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12711 emitcode ("push","ar3");
12712 emitcode ("push","ar2");
12713 emitcode ("pop","%s",
12714 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12715 emitcode ("pop","%s",
12716 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12718 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12719 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12721 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12722 emitcode ("","!tlabeldef",lbl->key+100);
12723 unsavermask(rsave);
12726 /*-----------------------------------------------------------------*/
12727 /* genMMMalloc - */
12728 /*-----------------------------------------------------------------*/
12729 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12730 int size, const char *name)
12735 symbol *lbl = newiTempLabel(NULL);
12737 assert (nparms == 1);
12738 /* save registers that need to be saved */
12739 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12740 ds390_rUmaskForOp (IC_RESULT(ic))));
12743 aopOp (bsize,ic,FALSE,FALSE);
12745 /* put the size in R4-R2 */
12746 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12747 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12748 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12750 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12751 emitcode("pop","ar4");
12753 emitcode("pop","ar3");
12754 emitcode("pop","ar2");
12756 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12757 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12759 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12762 freeAsmop (bsize, NULL, ic, FALSE);
12764 /* make the call */
12765 emitcode ("lcall","MM_%s",name);
12766 emitcode ("jz","!tlabel",lbl->key+100);
12767 emitcode ("mov","r2,#!constbyte",0xff);
12768 emitcode ("mov","r3,#!constbyte",0xff);
12769 emitcode ("","!tlabeldef",lbl->key+100);
12770 /* we don't care about the pointer : we just save the handle */
12771 rsym = OP_SYMBOL(IC_RESULT(ic));
12772 if (rsym->liveFrom != rsym->liveTo) {
12773 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12774 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12775 emitcode ("push","ar3");
12776 emitcode ("push","ar2");
12777 emitcode ("pop","%s",
12778 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12779 emitcode ("pop","%s",
12780 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12782 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12783 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12785 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12787 unsavermask(rsave);
12790 /*-----------------------------------------------------------------*/
12792 /*-----------------------------------------------------------------*/
12793 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12798 assert (nparms == 1);
12799 /* save registers that need to be saved */
12800 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12801 ds390_rUmaskForOp (IC_RESULT(ic))));
12804 aopOp (handle,ic,FALSE,FALSE);
12806 /* put the size in R4-R2 */
12807 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12808 emitcode("push","%s",
12809 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12810 emitcode("push","%s",
12811 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12812 emitcode("pop","ar3");
12813 emitcode("pop","ar2");
12815 emitcode ("mov","r2,%s",
12816 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12817 emitcode ("mov","r3,%s",
12818 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12820 freeAsmop (handle, NULL, ic, FALSE);
12822 /* make the call */
12823 emitcode ("lcall","MM_Deref");
12826 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12827 if (rsym->liveFrom != rsym->liveTo) {
12828 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12829 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12830 _startLazyDPSEvaluation ();
12832 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12833 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12834 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12836 _endLazyDPSEvaluation ();
12841 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12842 unsavermask(rsave);
12845 /*-----------------------------------------------------------------*/
12846 /* genMMUnrestrictedPersist - */
12847 /*-----------------------------------------------------------------*/
12848 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12853 assert (nparms == 1);
12854 /* save registers that need to be saved */
12855 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12856 ds390_rUmaskForOp (IC_RESULT(ic))));
12859 aopOp (handle,ic,FALSE,FALSE);
12861 /* put the size in R3-R2 */
12862 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12863 emitcode("push","%s",
12864 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12865 emitcode("push","%s",
12866 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12867 emitcode("pop","ar3");
12868 emitcode("pop","ar2");
12870 emitcode ("mov","r2,%s",
12871 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12872 emitcode ("mov","r3,%s",
12873 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12875 freeAsmop (handle, NULL, ic, FALSE);
12877 /* make the call */
12878 emitcode ("lcall","MM_UnrestrictedPersist");
12881 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12882 if (rsym->liveFrom != rsym->liveTo) {
12883 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12884 aopPut(AOP(IC_RESULT(ic)),"a",0);
12885 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12888 unsavermask(rsave);
12891 /*-----------------------------------------------------------------*/
12892 /* genSystemExecJavaProcess - */
12893 /*-----------------------------------------------------------------*/
12894 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12897 operand *handle, *pp;
12899 assert (nparms==2);
12900 /* save registers that need to be saved */
12901 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12902 ds390_rUmaskForOp (IC_RESULT(ic))));
12907 /* put the handle in R3-R2 */
12908 aopOp (handle,ic,FALSE,FALSE);
12909 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12910 emitcode("push","%s",
12911 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12912 emitcode("push","%s",
12913 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12914 emitcode("pop","ar3");
12915 emitcode("pop","ar2");
12917 emitcode ("mov","r2,%s",
12918 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12919 emitcode ("mov","r3,%s",
12920 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12922 freeAsmop (handle, NULL, ic, FALSE);
12924 /* put pointer in DPTR */
12925 aopOp (pp,ic,FALSE,FALSE);
12926 if (AOP_TYPE(pp) == AOP_IMMD) {
12927 emitcode ("mov", "dptr,%s",
12928 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12929 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12930 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12931 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12932 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12934 freeAsmop (handle, NULL, ic, FALSE);
12936 /* make the call */
12937 emitcode ("lcall","System_ExecJavaProcess");
12939 /* put result in place */
12941 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12942 if (rsym->liveFrom != rsym->liveTo) {
12943 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12944 aopPut(AOP(IC_RESULT(ic)),"a",0);
12945 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12949 unsavermask(rsave);
12952 /*-----------------------------------------------------------------*/
12953 /* genSystemRTCRegisters - */
12954 /*-----------------------------------------------------------------*/
12955 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12961 assert (nparms==1);
12962 /* save registers that need to be saved */
12963 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12964 ds390_rUmaskForOp (IC_RESULT(ic))));
12967 /* put pointer in DPTR */
12968 aopOp (pp,ic,FALSE,FALSE);
12969 if (AOP_TYPE (pp) == AOP_IMMD) {
12970 emitcode ("mov","dps,#1");
12971 emitcode ("mov", "dptr,%s",
12972 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12973 emitcode ("mov","dps,#0");
12975 emitcode ("mov","dpl1,%s",
12976 aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12977 emitcode ("mov","dph1,%s",
12978 aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12979 emitcode ("mov","dpx1,%s",
12980 aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12982 freeAsmop (pp, NULL, ic, FALSE);
12984 /* make the call */
12985 emitcode ("lcall","System_%sRTCRegisters",name);
12987 unsavermask(rsave);
12990 /*-----------------------------------------------------------------*/
12991 /* genSystemThreadSleep - */
12992 /*-----------------------------------------------------------------*/
12993 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12998 assert (nparms==1);
12999 /* save registers that need to be saved */
13000 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13001 ds390_rUmaskForOp (IC_RESULT(ic))));
13004 aopOp(to,ic,FALSE,FALSE);
13005 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
13006 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
13007 emitcode ("push","%s",
13008 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
13009 emitcode ("push","%s",
13010 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
13011 emitcode ("push","%s",
13012 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
13013 emitcode ("push","%s",
13014 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
13015 emitcode ("pop","ar3");
13016 emitcode ("pop","ar2");
13017 emitcode ("pop","ar1");
13018 emitcode ("pop","ar0");
13020 emitcode ("mov","r0,%s",
13021 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
13022 emitcode ("mov","r1,%s",
13023 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
13024 emitcode ("mov","r2,%s",
13025 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
13026 emitcode ("mov","r3,%s",
13027 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
13029 freeAsmop (to, NULL, ic, FALSE);
13031 /* suspend in acc */
13033 aopOp(s,ic,FALSE,FALSE);
13034 emitcode ("mov","a,%s",
13035 aopGet(AOP(s),0,FALSE,TRUE,NULL));
13036 freeAsmop (s, NULL, ic, FALSE);
13038 /* make the call */
13039 emitcode ("lcall","System_%s",name);
13041 unsavermask(rsave);
13044 /*-----------------------------------------------------------------*/
13045 /* genSystemThreadResume - */
13046 /*-----------------------------------------------------------------*/
13047 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
13052 assert (nparms==2);
13053 /* save registers that need to be saved */
13054 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13055 ds390_rUmaskForOp (IC_RESULT(ic))));
13061 aopOp(pid,ic,FALSE,FALSE);
13062 emitcode ("mov","r0,%s",
13063 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13064 freeAsmop (pid, NULL, ic, FALSE);
13067 aopOp(tid,ic,FALSE,FALSE);
13068 emitcode ("mov","a,%s",
13069 aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
13070 freeAsmop (tid, NULL, ic, FALSE);
13072 emitcode ("lcall","System_ThreadResume");
13074 /* put result into place */
13076 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13077 if (rsym->liveFrom != rsym->liveTo) {
13078 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13079 aopPut(AOP(IC_RESULT(ic)),"a",0);
13080 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13083 unsavermask(rsave);
13086 /*-----------------------------------------------------------------*/
13087 /* genSystemProcessResume - */
13088 /*-----------------------------------------------------------------*/
13089 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
13094 assert (nparms==1);
13095 /* save registers that need to be saved */
13096 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13097 ds390_rUmaskForOp (IC_RESULT(ic))));
13102 aopOp(pid,ic,FALSE,FALSE);
13103 emitcode ("mov","a,%s",
13104 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13105 freeAsmop (pid, NULL, ic, FALSE);
13107 emitcode ("lcall","System_ProcessResume");
13109 unsavermask(rsave);
13112 /*-----------------------------------------------------------------*/
13114 /*-----------------------------------------------------------------*/
13115 static void genSystem (iCode *ic,int nparms,char *name)
13117 assert(nparms == 0);
13119 emitcode ("lcall","System_%s",name);
13122 /*-----------------------------------------------------------------*/
13123 /* genSystemPoll - */
13124 /*-----------------------------------------------------------------*/
13125 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
13130 assert (nparms==1);
13131 /* save registers that need to be saved */
13132 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13133 ds390_rUmaskForOp (IC_RESULT(ic))));
13136 aopOp (fp,ic,FALSE,FALSE);
13137 if (AOP_TYPE (fp) == AOP_IMMD) {
13138 emitcode ("mov", "dptr,%s",
13139 aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
13140 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
13141 emitcode ("mov","dpl,%s",
13142 aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
13143 emitcode ("mov","dph,%s",
13144 aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
13145 emitcode ("mov","dpx,%s",
13146 aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
13148 freeAsmop (fp, NULL, ic, FALSE);
13150 emitcode ("lcall","System_%sPoll",name);
13152 /* put result into place */
13154 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13155 if (rsym->liveFrom != rsym->liveTo) {
13156 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13157 aopPut(AOP(IC_RESULT(ic)),"a",0);
13158 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13161 unsavermask(rsave);
13164 /*-----------------------------------------------------------------*/
13165 /* genSystemGetCurrentID - */
13166 /*-----------------------------------------------------------------*/
13167 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
13169 assert (nparms==0);
13171 emitcode ("lcall","System_GetCurrent%sId",name);
13172 /* put result into place */
13174 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13175 if (rsym->liveFrom != rsym->liveTo) {
13176 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13177 aopPut(AOP(IC_RESULT(ic)),"a",0);
13178 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13183 /*-----------------------------------------------------------------*/
13184 /* genDummyRead - generate code for dummy read of volatiles */
13185 /*-----------------------------------------------------------------*/
13187 genDummyRead (iCode * ic)
13192 D(emitcode("; genDummyRead",""));
13194 op = IC_RIGHT (ic);
13195 if (op && IS_SYMOP (op))
13197 aopOp (op, ic, FALSE, FALSE);
13199 /* if the result is a bit */
13200 if (AOP_TYPE (op) == AOP_CRY)
13201 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13204 /* bit variables done */
13206 size = AOP_SIZE (op);
13210 MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13215 freeAsmop (op, NULL, ic, TRUE);
13219 if (op && IS_SYMOP (op))
13221 aopOp (op, ic, FALSE, FALSE);
13223 /* if the result is a bit */
13224 if (AOP_TYPE (op) == AOP_CRY)
13225 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13228 /* bit variables done */
13230 size = AOP_SIZE (op);
13234 MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13239 freeAsmop (op, NULL, ic, TRUE);
13244 /*-----------------------------------------------------------------*/
13245 /* genCritical - generate code for start of a critical sequence */
13246 /*-----------------------------------------------------------------*/
13248 genCritical (iCode *ic)
13250 symbol *tlbl = newiTempLabel (NULL);
13252 D(emitcode("; genCritical",""));
13254 if (IC_RESULT (ic))
13255 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
13257 emitcode ("setb", "c");
13258 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
13259 emitcode ("clr", "c");
13260 emitcode ("", "%05d$:", (tlbl->key + 100));
13262 if (IC_RESULT (ic))
13263 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
13265 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
13267 if (IC_RESULT (ic))
13268 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13271 /*-----------------------------------------------------------------*/
13272 /* genEndCritical - generate code for end of a critical sequence */
13273 /*-----------------------------------------------------------------*/
13275 genEndCritical (iCode *ic)
13277 D(emitcode("; genEndCritical",""));
13281 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
13282 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
13284 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
13285 emitcode ("mov", "ea,c");
13289 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE));
13290 emitcode ("rrc", "a");
13291 emitcode ("mov", "ea,c");
13293 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
13297 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
13298 emitcode ("mov", "ea,c");
13304 /*-----------------------------------------------------------------*/
13305 /* genBuiltIn - calls the appropriate function to generating code */
13306 /* for a built in function */
13307 /*-----------------------------------------------------------------*/
13308 static void genBuiltIn (iCode *ic)
13310 operand *bi_parms[MAX_BUILTIN_ARGS];
13315 /* get all the arguments for a built in function */
13316 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
13318 /* which function is it */
13319 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
13320 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
13321 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
13322 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
13323 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
13324 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
13325 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
13326 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
13327 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
13328 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
13329 genMemsetX(bi_iCode,nbi_parms,bi_parms);
13330 } else if (strcmp(bif->name,"__builtin_inp")==0) {
13331 genInp(bi_iCode,nbi_parms,bi_parms);
13332 } else if (strcmp(bif->name,"__builtin_outp")==0) {
13333 genOutp(bi_iCode,nbi_parms,bi_parms);
13334 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
13335 genSwapW(bi_iCode,nbi_parms,bi_parms);
13336 /* JavaNative builtIns */
13337 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
13338 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
13339 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
13340 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
13341 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
13342 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
13343 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
13344 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
13345 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
13346 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13347 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
13348 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13349 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
13350 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
13351 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
13352 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
13353 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
13354 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13355 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
13356 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13357 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
13358 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
13359 } else if (strcmp(bif->name,"MM_Malloc")==0) {
13360 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
13361 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
13362 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
13363 } else if (strcmp(bif->name,"MM_Free")==0) {
13364 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
13365 } else if (strcmp(bif->name,"MM_Deref")==0) {
13366 genMMDeref(bi_iCode,nbi_parms,bi_parms);
13367 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
13368 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
13369 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
13370 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
13371 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
13372 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
13373 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
13374 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
13375 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
13376 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
13377 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
13378 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
13379 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
13380 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
13381 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
13382 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
13383 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13384 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13385 } else if (strcmp(bif->name,"System_SaveThread")==0) {
13386 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13387 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13388 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13389 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
13390 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
13391 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
13392 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
13393 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
13394 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
13395 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
13396 genSystem(bi_iCode,nbi_parms,"ProcessYield");
13397 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
13398 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
13399 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
13400 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
13401 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
13402 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
13403 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
13404 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
13405 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
13406 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
13408 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
13414 /*-----------------------------------------------------------------*/
13415 /* gen390Code - generate code for Dallas 390 based controllers */
13416 /*-----------------------------------------------------------------*/
13418 gen390Code (iCode * lic)
13423 lineHead = lineCurr = NULL;
13424 dptrn[1][0] = "dpl1";
13425 dptrn[1][1] = "dph1";
13426 dptrn[1][2] = "dpx1";
13428 if (options.model == MODEL_FLAT24) {
13429 fReturnSizeDS390 = 5;
13430 fReturn = fReturn24;
13432 fReturnSizeDS390 = 4;
13433 fReturn = fReturn16;
13434 options.stack10bit=0;
13437 /* print the allocation information */
13438 if (allocInfo && currFunc)
13439 printAllocInfo (currFunc, codeOutFile);
13441 /* if debug information required */
13442 if (options.debug && currFunc)
13444 debugFile->writeFunction (currFunc, lic);
13446 /* stack pointer name */
13447 if (options.useXstack)
13453 for (ic = lic; ic; ic = ic->next)
13455 _G.current_iCode = ic;
13457 if (ic->lineno && cln != ic->lineno)
13461 debugFile->writeCLine (ic);
13463 if (!options.noCcodeInAsm) {
13464 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
13465 printCLine(ic->filename, ic->lineno));
13469 if (options.iCodeInAsm) {
13470 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
13472 /* if the result is marked as
13473 spilt and rematerializable or code for
13474 this has already been generated then
13476 if (resultRemat (ic) || ic->generated)
13479 /* depending on the operation */
13499 /* IPOP happens only when trying to restore a
13500 spilt live range, if there is an ifx statement
13501 following this pop then the if statement might
13502 be using some of the registers being popped which
13503 would destory the contents of the register so
13504 we need to check for this condition and handle it */
13506 ic->next->op == IFX &&
13507 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
13508 genIfx (ic->next, ic);
13526 genEndFunction (ic);
13546 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
13563 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
13567 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
13574 /* note these two are xlated by algebraic equivalence
13575 during parsing SDCC.y */
13576 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13577 "got '>=' or '<=' shouldn't have come here");
13581 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
13593 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
13597 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
13601 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
13625 genRightShift (ic);
13628 case GET_VALUE_AT_ADDRESS:
13629 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13633 if (POINTER_SET (ic))
13634 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13660 if (ic->builtinSEND) genBuiltIn(ic);
13661 else addSet (&_G.sendSet, ic);
13664 case DUMMY_READ_VOLATILE:
13673 genEndCritical (ic);
13680 #if 0 // obsolete, and buggy for != xdata
13692 /* now we are ready to call the
13693 peep hole optimizer */
13694 if (!options.nopeep)
13695 peepHole (&lineHead);
13697 /* now do the actual printing */
13698 printLine (lineHead, codeOutFile);