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 /*-----------------------------------------------------------------*/
1918 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) {
1927 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1928 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1929 emitcode ("cpl", "c");
1930 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1933 tlbl=newiTempLabel(NULL);
1934 emitcode ("cjne", "%s,#0x01,%05d$",
1935 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1936 emitcode ("", "%05d$:", tlbl->key+100);
1937 outBitC (IC_RESULT(ic));
1941 size = AOP_SIZE (IC_RESULT (ic));
1942 _startLazyDPSEvaluation ();
1945 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1946 emitcode ("cpl", "a");
1947 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1949 _endLazyDPSEvaluation ();
1953 /* release the aops */
1954 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1955 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1958 /*-----------------------------------------------------------------*/
1959 /* genUminusFloat - unary minus for floating points */
1960 /*-----------------------------------------------------------------*/
1962 genUminusFloat (operand * op, operand * result)
1964 int size, offset = 0;
1966 D(emitcode (";", "genUminusFloat"););
1968 /* for this we just copy and then flip the bit */
1970 _startLazyDPSEvaluation ();
1971 size = AOP_SIZE (op) - 1;
1975 aopPut (AOP (result),
1976 aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1981 MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1983 emitcode ("cpl", "acc.7");
1984 aopPut (AOP (result), "a", offset);
1985 _endLazyDPSEvaluation ();
1988 /*-----------------------------------------------------------------*/
1989 /* genUminus - unary minus code generation */
1990 /*-----------------------------------------------------------------*/
1992 genUminus (iCode * ic)
1997 D (emitcode (";", "genUminus "););
2000 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2001 aopOp (IC_RESULT (ic), ic, TRUE, (AOP_TYPE(IC_LEFT (ic)) == AOP_DPTR));
2003 /* if both in bit space then special
2005 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2006 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2009 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2010 emitcode ("cpl", "c");
2011 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2015 optype = operandType (IC_LEFT (ic));
2017 /* if float then do float stuff */
2018 if (IS_FLOAT (optype))
2020 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2024 /* otherwise subtract from zero */
2025 size = AOP_SIZE (IC_LEFT (ic));
2027 _startLazyDPSEvaluation ();
2030 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
2031 if (!strcmp (l, "a"))
2035 emitcode ("cpl", "a");
2036 emitcode ("addc", "a,#0");
2042 emitcode ("clr", "a");
2043 emitcode ("subb", "a,%s", l);
2045 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2047 _endLazyDPSEvaluation ();
2049 /* if any remaining bytes in the result */
2050 /* we just need to propagate the sign */
2051 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
2053 emitcode ("rlc", "a");
2054 emitcode ("subb", "a,acc");
2056 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2060 /* release the aops */
2061 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2062 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2065 /*-----------------------------------------------------------------*/
2066 /* savermask - saves registers in the mask */
2067 /*-----------------------------------------------------------------*/
2068 static void savermask(bitVect *rs_mask)
2071 if (options.useXstack) {
2072 if (bitVectBitValue (rs_mask, R0_IDX))
2073 emitcode ("mov", "b,r0");
2074 emitcode ("mov", "r0,%s", spname);
2075 for (i = 0; i < ds390_nRegs; i++) {
2076 if (bitVectBitValue (rs_mask, i)) {
2078 emitcode ("mov", "a,b");
2080 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2081 emitcode ("movx", "@r0,a");
2082 emitcode ("inc", "r0");
2085 emitcode ("mov", "%s,r0", spname);
2086 if (bitVectBitValue (rs_mask, R0_IDX))
2087 emitcode ("mov", "r0,b");
2089 for (i = 0; i < ds390_nRegs; i++) {
2090 if (bitVectBitValue (rs_mask, i))
2091 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2096 /*-----------------------------------------------------------------*/
2097 /* saveRegisters - will look for a call and save the registers */
2098 /*-----------------------------------------------------------------*/
2100 saveRegisters (iCode * lic)
2106 for (ic = lic; ic; ic = ic->next)
2107 if (ic->op == CALL || ic->op == PCALL)
2112 fprintf (stderr, "found parameter push with no function call\n");
2116 /* if the registers have been saved already then
2119 || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2122 /* special case if DPTR alive across a function call then must save it
2123 even though callee saves */
2124 if (IS_SYMOP(IC_LEFT(ic)) &&
2125 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2127 rsave = newBitVect(ic->rMask->size);
2128 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2129 if (bitVectBitValue(ic->rMask,i))
2130 rsave = bitVectSetBit(rsave,i);
2132 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2134 /* safe the registers in use at this time but skip the
2135 ones for the result */
2136 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2137 ds390_rUmaskForOp (IC_RESULT(ic)));
2143 /*-----------------------------------------------------------------*/
2144 /* usavermask - restore registers with mask */
2145 /*-----------------------------------------------------------------*/
2146 static void unsavermask(bitVect *rs_mask)
2149 if (options.useXstack) {
2150 emitcode ("mov", "r0,%s", spname);
2151 for (i = ds390_nRegs; i >= 0; i--) {
2152 if (bitVectBitValue (rs_mask, i)) {
2153 emitcode ("dec", "r0");
2154 emitcode ("movx", "a,@r0");
2156 emitcode ("mov", "b,a");
2158 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2161 emitcode ("mov", "%s,r0", spname);
2162 if (bitVectBitValue (rs_mask, R0_IDX))
2163 emitcode ("mov", "r0,b");
2165 for (i = ds390_nRegs; i >= 0; i--) {
2166 if (bitVectBitValue (rs_mask, i))
2167 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2172 /*-----------------------------------------------------------------*/
2173 /* unsaveRegisters - pop the pushed registers */
2174 /*-----------------------------------------------------------------*/
2176 unsaveRegisters (iCode * ic)
2180 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2182 rsave = newBitVect(ic->rMask->size);
2183 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2184 if (bitVectBitValue(ic->rMask,i))
2185 rsave = bitVectSetBit(rsave,i);
2187 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2189 /* restore the registers in use at this time but skip the
2190 ones for the result */
2191 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2192 ds390_rUmaskForOp (IC_RESULT(ic)));
2198 /*-----------------------------------------------------------------*/
2200 /*-----------------------------------------------------------------*/
2202 pushSide (operand * oper, int size)
2205 _startLazyDPSEvaluation ();
2208 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2209 if (AOP_TYPE (oper) != AOP_REG &&
2210 AOP_TYPE (oper) != AOP_DIR &&
2213 emitcode ("mov", "a,%s", l);
2214 emitcode ("push", "acc");
2217 emitcode ("push", "%s", l);
2219 _endLazyDPSEvaluation ();
2222 /*-----------------------------------------------------------------*/
2223 /* assignResultValue - */
2224 /*-----------------------------------------------------------------*/
2226 assignResultValue (operand * oper)
2229 int size = AOP_SIZE (oper);
2230 bool pushedAcc = FALSE;
2232 if (size == fReturnSizeDS390)
2234 /* I don't think this case can ever happen... */
2235 /* ACC is the last part of this. If writing the result
2236 * uses AC, we must preserve it.
2238 if (AOP_NEEDSACC(oper))
2240 emitcode(";", "assignResultValue special case for ACC.");
2241 emitcode("push", "acc");
2248 _startLazyDPSEvaluation ();
2251 aopPut (AOP (oper), fReturn[offset], offset);
2254 _endLazyDPSEvaluation ();
2258 emitcode("pop", "acc");
2259 aopPut(AOP(oper), "a", offset);
2264 /*-----------------------------------------------------------------*/
2265 /* genXpush - pushes onto the external stack */
2266 /*-----------------------------------------------------------------*/
2268 genXpush (iCode * ic)
2270 asmop *aop = newAsmop (0);
2272 int size, offset = 0;
2274 D (emitcode (";", "genXpush ");
2277 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2278 r = getFreePtr (ic, &aop, FALSE);
2281 emitcode ("mov", "%s,_spx", r->name);
2283 size = AOP_SIZE (IC_LEFT (ic));
2284 _startLazyDPSEvaluation ();
2288 MOVA (aopGet (AOP (IC_LEFT (ic)),
2289 offset++, FALSE, FALSE, NULL));
2290 emitcode ("movx", "@%s,a", r->name);
2291 emitcode ("inc", "%s", r->name);
2294 _endLazyDPSEvaluation ();
2297 emitcode ("mov", "_spx,%s", r->name);
2299 freeAsmop (NULL, aop, ic, TRUE);
2300 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2303 /*-----------------------------------------------------------------*/
2304 /* genIpush - generate code for pushing this gets a little complex */
2305 /*-----------------------------------------------------------------*/
2307 genIpush (iCode * ic)
2309 int size, offset = 0;
2312 D (emitcode (";", "genIpush ");
2315 /* if this is not a parm push : ie. it is spill push
2316 and spill push is always done on the local stack */
2320 /* and the item is spilt then do nothing */
2321 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2324 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2325 size = AOP_SIZE (IC_LEFT (ic));
2326 /* push it on the stack */
2327 _startLazyDPSEvaluation ();
2330 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2336 emitcode ("push", "%s", l);
2338 _endLazyDPSEvaluation ();
2342 /* this is a paramter push: in this case we call
2343 the routine to find the call and save those
2344 registers that need to be saved */
2347 /* if use external stack then call the external
2348 stack pushing routine */
2349 if (options.useXstack)
2355 /* then do the push */
2356 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2358 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2359 size = AOP_SIZE (IC_LEFT (ic));
2361 _startLazyDPSEvaluation ();
2364 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2365 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2366 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2369 emitcode ("mov", "a,%s", l);
2370 emitcode ("push", "acc");
2374 emitcode ("push", "%s", l);
2377 _endLazyDPSEvaluation ();
2379 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2382 /*-----------------------------------------------------------------*/
2383 /* genIpop - recover the registers: can happen only for spilling */
2384 /*-----------------------------------------------------------------*/
2386 genIpop (iCode * ic)
2390 D (emitcode (";", "genIpop ");
2394 /* if the temp was not pushed then */
2395 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2398 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2399 size = AOP_SIZE (IC_LEFT (ic));
2400 offset = (size - 1);
2401 _startLazyDPSEvaluation ();
2404 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2405 FALSE, TRUE, NULL));
2407 _endLazyDPSEvaluation ();
2409 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2412 /*-----------------------------------------------------------------*/
2413 /* unsaveRBank - restores the resgister bank from stack */
2414 /*-----------------------------------------------------------------*/
2416 unsaveRBank (int bank, iCode * ic, bool popPsw)
2422 if (options.useXstack)
2426 /* Assume r0 is available for use. */
2427 r = ds390_regWithIdx (R0_IDX);;
2432 r = getFreePtr (ic, &aop, FALSE);
2434 emitcode ("mov", "%s,_spx", r->name);
2439 if (options.useXstack)
2441 emitcode ("movx", "a,@%s", r->name);
2442 emitcode ("mov", "psw,a");
2443 emitcode ("dec", "%s", r->name);
2447 emitcode ("pop", "psw");
2451 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2453 if (options.useXstack)
2455 emitcode ("movx", "a,@%s", r->name);
2456 emitcode ("mov", "(%s+%d),a",
2457 regs390[i].base, 8 * bank + regs390[i].offset);
2458 emitcode ("dec", "%s", r->name);
2462 emitcode ("pop", "(%s+%d)",
2463 regs390[i].base, 8 * bank + regs390[i].offset);
2466 if (options.useXstack)
2468 emitcode ("mov", "_spx,%s", r->name);
2473 freeAsmop (NULL, aop, ic, TRUE);
2477 /*-----------------------------------------------------------------*/
2478 /* saveRBank - saves an entire register bank on the stack */
2479 /*-----------------------------------------------------------------*/
2481 saveRBank (int bank, iCode * ic, bool pushPsw)
2487 if (options.useXstack)
2491 /* Assume r0 is available for use. */
2492 r = ds390_regWithIdx (R0_IDX);;
2497 r = getFreePtr (ic, &aop, FALSE);
2499 emitcode ("mov", "%s,_spx", r->name);
2502 for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2504 if (options.useXstack)
2506 emitcode ("inc", "%s", r->name);
2507 emitcode ("mov", "a,(%s+%d)",
2508 regs390[i].base, 8 * bank + regs390[i].offset);
2509 emitcode ("movx", "@%s,a", r->name);
2512 emitcode ("push", "(%s+%d)",
2513 regs390[i].base, 8 * bank + regs390[i].offset);
2518 if (options.useXstack)
2520 emitcode ("mov", "a,psw");
2521 emitcode ("movx", "@%s,a", r->name);
2522 emitcode ("inc", "%s", r->name);
2523 emitcode ("mov", "_spx,%s", r->name);
2527 emitcode ("push", "psw");
2530 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2535 freeAsmop (NULL, aop, ic, TRUE);
2544 /*-----------------------------------------------------------------*/
2545 /* genSend - gen code for SEND */
2546 /*-----------------------------------------------------------------*/
2547 static void genSend(set *sendSet)
2551 static int rb1_count = 0;
2553 for (sic = setFirstItem (sendSet); sic;
2554 sic = setNextItem (sendSet)) {
2555 int size, offset = 0;
2557 size=getSize(operandType(IC_LEFT(sic)));
2558 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2559 if (sendCount == 0) { /* first parameter */
2560 // we know that dpl(hxb) is the result, so
2562 _startLazyDPSEvaluation ();
2564 aopOp (IC_LEFT (sic), sic, FALSE,
2565 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2567 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2570 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2571 FALSE, FALSE, NULL);
2572 if (strcmp (l, fReturn[offset])) {
2573 emitcode ("mov", "%s,%s",
2579 _endLazyDPSEvaluation ();
2580 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2582 } else { /* if more parameter in registers */
2583 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2585 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2586 FALSE, FALSE, NULL));
2588 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2595 adjustEsp(const char *reg)
2597 emitcode ("anl","%s,#3", reg);
2598 if (TARGET_IS_DS400)
2600 emitcode ("orl","%s,#!constbyte",
2602 (options.stack_loc >> 8) & 0xff);
2606 /*-----------------------------------------------------------------*/
2607 /* genCall - generates a call statement */
2608 /*-----------------------------------------------------------------*/
2610 genCall (iCode * ic)
2613 bool restoreBank = FALSE;
2614 bool swapBanks = FALSE;
2616 D (emitcode (";", "genCall "););
2618 /* if we are calling a not _naked function that is not using
2619 the same register bank then we need to save the
2620 destination registers on the stack */
2621 dtype = operandType (IC_LEFT (ic));
2622 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2623 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2624 IFFUNC_ISISR (currFunc->type))
2628 /* This is unexpected; the bank should have been saved in
2631 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2637 /* if caller saves & we have not saved then */
2641 /* if send set is not empty the assign */
2642 /* We've saved all the registers we care about;
2643 * therefore, we may clobber any register not used
2644 * in the calling convention (i.e. anything not in
2649 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2650 genSend(reverseSet(_G.sendSet));
2652 genSend(_G.sendSet);
2659 emitcode ("mov", "psw,#!constbyte",
2660 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2664 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2665 OP_SYMBOL (IC_LEFT (ic))->rname :
2666 OP_SYMBOL (IC_LEFT (ic))->name));
2670 emitcode ("mov", "psw,#!constbyte",
2671 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2674 /* if we need assign a result value */
2675 if ((IS_ITEMP (IC_RESULT (ic)) &&
2676 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2677 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2678 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2679 IS_TRUE_SYMOP (IC_RESULT (ic)))
2681 if (isOperandInFarSpace (IC_RESULT (ic))
2682 && getSize (operandType (IC_RESULT (ic))) <= 2)
2684 int size = getSize (operandType (IC_RESULT (ic)));
2686 /* Special case for 1 or 2 byte return in far space. */
2690 emitcode ("mov", "b,%s", fReturn[1]);
2695 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2701 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2705 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2707 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2712 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2715 assignResultValue (IC_RESULT (ic));
2717 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2721 /* adjust the stack for parameters if
2723 if (ic->parmBytes) {
2725 if (options.stack10bit) {
2726 if (ic->parmBytes <= 10) {
2727 emitcode(";","stack adjustment for parms");
2728 for (i=0; i < ic->parmBytes ; i++) {
2729 emitcode("pop","acc");
2733 emitcode ("clr","c");
2734 emitcode ("mov","a,sp");
2735 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2736 emitcode ("mov","sp,a");
2737 emitcode ("mov","a,esp");
2739 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2740 emitcode ("mov","esp,a");
2744 if (ic->parmBytes > 3) {
2745 emitcode ("mov", "a,%s", spname);
2746 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2747 emitcode ("mov", "%s,a", spname);
2749 for (i = 0; i < ic->parmBytes; i++)
2750 emitcode ("dec", "%s", spname);
2754 /* if we hade saved some registers then unsave them */
2756 unsaveRegisters (ic);
2758 /* if register bank was saved then pop them */
2760 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2763 /*-----------------------------------------------------------------*/
2764 /* genPcall - generates a call by pointer statement */
2765 /*-----------------------------------------------------------------*/
2767 genPcall (iCode * ic)
2770 symbol *rlbl = newiTempLabel (NULL);
2771 bool restoreBank=FALSE;
2773 D (emitcode (";", "genPcall ");
2777 /* if caller saves & we have not saved then */
2781 /* if we are calling a function that is not using
2782 the same register bank then we need to save the
2783 destination registers on the stack */
2784 dtype = operandType (IC_LEFT (ic));
2785 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2786 IFFUNC_ISISR (currFunc->type) &&
2787 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2788 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2792 /* push the return address on to the stack */
2793 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2794 emitcode ("push", "acc");
2795 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2796 emitcode ("push", "acc");
2798 if (options.model == MODEL_FLAT24)
2800 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2801 emitcode ("push", "acc");
2804 /* now push the calling address */
2805 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2807 pushSide (IC_LEFT (ic), FPTRSIZE);
2809 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2811 /* if send set is not empty the assign */
2814 genSend(reverseSet(_G.sendSet));
2818 emitcode ("ret", "");
2819 emitcode ("", "!tlabeldef", (rlbl->key + 100));
2822 /* if we need assign a result value */
2823 if ((IS_ITEMP (IC_RESULT (ic)) &&
2824 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2825 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2826 IS_TRUE_SYMOP (IC_RESULT (ic)))
2830 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2833 assignResultValue (IC_RESULT (ic));
2835 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2838 /* adjust the stack for parameters if
2843 if (options.stack10bit) {
2844 if (ic->parmBytes <= 10) {
2845 emitcode(";","stack adjustment for parms");
2846 for (i=0; i < ic->parmBytes ; i++) {
2847 emitcode("pop","acc");
2851 emitcode ("clr","c");
2852 emitcode ("mov","a,sp");
2853 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2854 emitcode ("mov","sp,a");
2855 emitcode ("mov","a,esp");
2857 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2858 emitcode ("mov","esp,a");
2862 if (ic->parmBytes > 3) {
2863 emitcode ("mov", "a,%s", spname);
2864 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2865 emitcode ("mov", "%s,a", spname);
2868 for (i = 0; i < ic->parmBytes; i++)
2869 emitcode ("dec", "%s", spname);
2873 /* if register bank was saved then unsave them */
2875 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2877 /* if we hade saved some registers then
2880 unsaveRegisters (ic);
2884 /*-----------------------------------------------------------------*/
2885 /* resultRemat - result is rematerializable */
2886 /*-----------------------------------------------------------------*/
2888 resultRemat (iCode * ic)
2890 if (SKIP_IC (ic) || ic->op == IFX)
2893 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2895 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2896 if (sym->remat && !POINTER_SET (ic))
2903 #if defined(__BORLANDC__) || defined(_MSC_VER)
2904 #define STRCASECMP stricmp
2906 #define STRCASECMP strcasecmp
2909 /*-----------------------------------------------------------------*/
2910 /* inExcludeList - return 1 if the string is in exclude Reg list */
2911 /*-----------------------------------------------------------------*/
2913 regsCmp(void *p1, void *p2)
2915 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2919 inExcludeList (char *s)
2921 const char *p = setFirstItem(options.excludeRegsSet);
2923 if (p == NULL || STRCASECMP(p, "none") == 0)
2927 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2930 /*-----------------------------------------------------------------*/
2931 /* genFunction - generated code for function entry */
2932 /*-----------------------------------------------------------------*/
2934 genFunction (iCode * ic)
2938 bool switchedPSW = FALSE;
2940 D (emitcode (";", "genFunction "););
2943 /* create the function header */
2944 emitcode (";", "-----------------------------------------");
2945 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2946 emitcode (";", "-----------------------------------------");
2948 emitcode ("", "%s:", sym->rname);
2949 ftype = operandType (IC_LEFT (ic));
2951 if (IFFUNC_ISNAKED(ftype))
2953 emitcode(";", "naked function: no prologue.");
2957 if (options.stack_probe)
2958 emitcode ("lcall","__stack_probe");
2960 /* here we need to generate the equates for the
2961 register bank if required */
2962 if (FUNC_REGBANK (ftype) != rbank)
2966 rbank = FUNC_REGBANK (ftype);
2967 for (i = 0; i < ds390_nRegs; i++)
2969 if (regs390[i].print) {
2970 if (strcmp (regs390[i].base, "0") == 0)
2971 emitcode ("", "%s !equ !constbyte",
2973 8 * rbank + regs390[i].offset);
2975 emitcode ("", "%s !equ %s + !constbyte",
2978 8 * rbank + regs390[i].offset);
2983 /* if this is an interrupt service routine then
2984 save acc, b, dpl, dph */
2985 if (IFFUNC_ISISR (sym->type))
2987 if (!inExcludeList ("acc"))
2988 emitcode ("push", "acc");
2989 if (!inExcludeList ("b"))
2990 emitcode ("push", "b");
2991 if (!inExcludeList ("dpl"))
2992 emitcode ("push", "dpl");
2993 if (!inExcludeList ("dph"))
2994 emitcode ("push", "dph");
2995 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2997 emitcode ("push", "dpx");
2998 /* Make sure we're using standard DPTR */
2999 emitcode ("push", "dps");
3000 emitcode ("mov", "dps,#0");
3001 if (options.stack10bit)
3003 /* This ISR could conceivably use DPTR2. Better save it. */
3004 emitcode ("push", "dpl1");
3005 emitcode ("push", "dph1");
3006 emitcode ("push", "dpx1");
3007 emitcode ("push", DP2_RESULT_REG);
3010 /* if this isr has no bank i.e. is going to
3011 run with bank 0 , then we need to save more
3013 if (!FUNC_REGBANK (sym->type))
3017 /* if this function does not call any other
3018 function then we can be economical and
3019 save only those registers that are used */
3020 if (!IFFUNC_HASFCALL(sym->type))
3023 /* if any registers used */
3026 /* save the registers used */
3027 for (i = 0; i < sym->regsUsed->size; i++)
3029 if (bitVectBitValue (sym->regsUsed, i))
3030 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3036 /* this function has a function call cannot
3037 determines register usage so we will have to push the
3039 saveRBank (0, ic, FALSE);
3040 if (options.parms_in_bank1) {
3041 for (i=0; i < 8 ; i++ ) {
3042 emitcode ("push","%s",rb1regs[i]);
3049 /* This ISR uses a non-zero bank.
3051 * We assume that the bank is available for our
3054 * However, if this ISR calls a function which uses some
3055 * other bank, we must save that bank entirely.
3057 unsigned long banksToSave = 0;
3059 if (IFFUNC_HASFCALL(sym->type))
3062 #define MAX_REGISTER_BANKS 4
3067 for (i = ic; i; i = i->next)
3069 if (i->op == ENDFUNCTION)
3071 /* we got to the end OK. */
3079 dtype = operandType (IC_LEFT(i));
3081 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3083 /* Mark this bank for saving. */
3084 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3086 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3090 banksToSave |= (1 << FUNC_REGBANK(dtype));
3093 /* And note that we don't need to do it in
3101 /* This is a mess; we have no idea what
3102 * register bank the called function might
3105 * The only thing I can think of to do is
3106 * throw a warning and hope.
3108 werror(W_FUNCPTR_IN_USING_ISR);
3112 if (banksToSave && options.useXstack)
3114 /* Since we aren't passing it an ic,
3115 * saveRBank will assume r0 is available to abuse.
3117 * So switch to our (trashable) bank now, so
3118 * the caller's R0 isn't trashed.
3120 emitcode ("push", "psw");
3121 emitcode ("mov", "psw,#!constbyte",
3122 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3126 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3128 if (banksToSave & (1 << ix))
3130 saveRBank(ix, NULL, FALSE);
3134 // TODO: this needs a closer look
3135 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3140 /* if callee-save to be used for this function
3141 then save the registers being used in this function */
3142 if (IFFUNC_CALLEESAVES(sym->type))
3146 /* if any registers used */
3149 /* save the registers used */
3150 for (i = 0; i < sym->regsUsed->size; i++)
3152 if (bitVectBitValue (sym->regsUsed, i))
3154 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3162 /* set the register bank to the desired value */
3163 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3166 emitcode ("push", "psw");
3167 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3170 if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3171 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3172 if (options.stack10bit) {
3173 emitcode ("push","_bpx");
3174 emitcode ("push","_bpx+1");
3175 emitcode ("mov","_bpx,%s",spname);
3176 emitcode ("mov","_bpx+1,esp");
3177 adjustEsp("_bpx+1");
3179 if (options.useXstack) {
3180 emitcode ("mov", "r0,%s", spname);
3181 emitcode ("mov", "a,_bp");
3182 emitcode ("movx", "@r0,a");
3183 emitcode ("inc", "%s", spname);
3185 /* set up the stack */
3186 emitcode ("push", "_bp"); /* save the callers stack */
3188 emitcode ("mov", "_bp,%s", spname);
3192 /* adjust the stack for the function */
3195 if (options.stack10bit) {
3196 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3197 assert (sym->recvSize <= 4);
3198 if (sym->stack <= 8) {
3199 while (i--) emitcode ("push","acc");
3202 emitcode ("mov","a,sp");
3203 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3204 emitcode ("mov","sp,a");
3205 emitcode ("mov","a,esp");
3207 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3208 emitcode ("mov","esp,a");
3213 werror (W_STACK_OVERFLOW, sym->name);
3215 if (i > 3 && sym->recvSize < 4) {
3217 emitcode ("mov", "a,sp");
3218 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3219 emitcode ("mov", "sp,a");
3223 emitcode ("inc", "sp");
3230 emitcode ("mov", "a,_spx");
3231 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3232 emitcode ("mov", "_spx,a");
3235 /* if critical function then turn interrupts off */
3236 if (IFFUNC_ISCRITICAL (ftype))
3238 symbol *tlbl = newiTempLabel (NULL);
3239 emitcode ("setb", "c");
3240 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3241 emitcode ("clr", "c");
3242 emitcode ("", "%05d$:", (tlbl->key + 100));
3243 emitcode ("push", "psw"); /* save old ea via c in psw */
3248 /*-----------------------------------------------------------------*/
3249 /* genEndFunction - generates epilogue for functions */
3250 /*-----------------------------------------------------------------*/
3252 genEndFunction (iCode * ic)
3254 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3255 lineNode *lnp = lineCurr;
3257 bitVect *regsUsedPrologue;
3258 bitVect *regsUnneeded;
3261 D (emitcode (";", "genEndFunction "););
3263 if (IFFUNC_ISNAKED(sym->type))
3265 emitcode(";", "naked function: no epilogue.");
3266 if (options.debug && currFunc)
3267 debugFile->writeEndFunction (currFunc, ic, 0);
3271 if (IFFUNC_ISCRITICAL (sym->type))
3273 emitcode ("pop", "psw"); /* restore ea via c in psw */
3274 emitcode ("mov", "ea,c");
3277 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3278 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3280 if (options.stack10bit) {
3282 emitcode ("mov", "sp,_bpx", spname);
3283 emitcode ("mov", "esp,_bpx+1", spname);
3286 emitcode ("mov", "%s,_bp", spname);
3290 /* if use external stack but some variables were
3291 added to the local stack then decrement the
3293 if (options.useXstack && sym->stack) {
3294 emitcode ("mov", "a,sp");
3295 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3296 emitcode ("mov", "sp,a");
3300 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3301 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3303 if (options.useXstack) {
3304 emitcode ("mov", "r0,%s", spname);
3305 emitcode ("movx", "a,@r0");
3306 emitcode ("mov", "_bp,a");
3307 emitcode ("dec", "%s", spname);
3309 if (options.stack10bit) {
3310 emitcode ("pop", "_bpx+1");
3311 emitcode ("pop", "_bpx");
3313 emitcode ("pop", "_bp");
3318 /* restore the register bank */
3319 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3321 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3322 || !options.useXstack)
3324 /* Special case of ISR using non-zero bank with useXstack
3327 emitcode ("pop", "psw");
3331 if (IFFUNC_ISISR (sym->type))
3334 /* now we need to restore the registers */
3335 /* if this isr has no bank i.e. is going to
3336 run with bank 0 , then we need to save more
3338 if (!FUNC_REGBANK (sym->type))
3341 /* if this function does not call any other
3342 function then we can be economical and
3343 save only those registers that are used */
3344 if (!IFFUNC_HASFCALL(sym->type))
3347 /* if any registers used */
3350 /* save the registers used */
3351 for (i = sym->regsUsed->size; i >= 0; i--)
3353 if (bitVectBitValue (sym->regsUsed, i))
3354 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3360 /* this function has a function call cannot
3361 determines register usage so we will have to pop the
3363 if (options.parms_in_bank1) {
3364 for (i = 7 ; i >= 0 ; i-- ) {
3365 emitcode ("pop","%s",rb1regs[i]);
3368 unsaveRBank (0, ic, FALSE);
3373 /* This ISR uses a non-zero bank.
3375 * Restore any register banks saved by genFunction
3378 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3381 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3383 if (savedBanks & (1 << ix))
3385 unsaveRBank(ix, NULL, FALSE);
3389 if (options.useXstack)
3391 /* Restore bank AFTER calling unsaveRBank,
3392 * since it can trash r0.
3394 emitcode ("pop", "psw");
3398 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3400 if (options.stack10bit)
3402 emitcode ("pop", DP2_RESULT_REG);
3403 emitcode ("pop", "dpx1");
3404 emitcode ("pop", "dph1");
3405 emitcode ("pop", "dpl1");
3407 emitcode ("pop", "dps");
3408 emitcode ("pop", "dpx");
3410 if (!inExcludeList ("dph"))
3411 emitcode ("pop", "dph");
3412 if (!inExcludeList ("dpl"))
3413 emitcode ("pop", "dpl");
3414 if (!inExcludeList ("b"))
3415 emitcode ("pop", "b");
3416 if (!inExcludeList ("acc"))
3417 emitcode ("pop", "acc");
3419 /* if debug then send end of function */
3420 if (options.debug && currFunc) {
3421 debugFile->writeEndFunction (currFunc, ic, 1);
3424 emitcode ("reti", "");
3428 if (IFFUNC_CALLEESAVES(sym->type))
3432 /* if any registers used */
3435 /* save the registers used */
3436 for (i = sym->regsUsed->size; i >= 0; i--)
3438 if (bitVectBitValue (sym->regsUsed, i))
3439 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3444 /* if debug then send end of function */
3445 if (options.debug && currFunc)
3447 debugFile->writeEndFunction (currFunc, ic, 1);
3450 emitcode ("ret", "");
3453 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3456 /* If this was an interrupt handler using bank 0 that called another */
3457 /* function, then all registers must be saved; nothing to optimized. */
3458 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3459 && !FUNC_REGBANK(sym->type))
3462 /* There are no push/pops to optimize if not callee-saves or ISR */
3463 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3466 /* If there were stack parameters, we cannot optimize without also */
3467 /* fixing all of the stack offsets; this is too dificult to consider. */
3468 if (FUNC_HASSTACKPARM(sym->type))
3471 /* Compute the registers actually used */
3472 regsUsed = newBitVect (ds390_nRegs);
3473 regsUsedPrologue = newBitVect (ds390_nRegs);
3476 if (lnp->ic && lnp->ic->op == FUNCTION)
3477 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3479 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3481 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3482 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3489 if (bitVectBitValue (regsUsedPrologue, DPS_IDX)
3490 && !bitVectBitValue (regsUsed, DPS_IDX))
3492 bitVectUnSetBit (regsUsedPrologue, DPS_IDX);
3495 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3496 && !bitVectBitValue (regsUsed, CND_IDX))
3498 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3499 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3500 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3501 bitVectUnSetBit (regsUsed, CND_IDX);
3504 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3506 /* If this was an interrupt handler that called another function */
3507 /* function, then assume working registers may be modified by it. */
3508 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3510 regsUsed = bitVectSetBit (regsUsed, AP_IDX);
3511 regsUsed = bitVectSetBit (regsUsed, DPX1_IDX);
3512 regsUsed = bitVectSetBit (regsUsed, DPL1_IDX);
3513 regsUsed = bitVectSetBit (regsUsed, DPH1_IDX);
3514 regsUsed = bitVectSetBit (regsUsed, DPX_IDX);
3515 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3516 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3517 regsUsed = bitVectSetBit (regsUsed, DPS_IDX);
3518 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3519 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3520 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3523 /* Remove the unneeded push/pops */
3524 regsUnneeded = newBitVect (ds390_nRegs);
3527 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3529 if (!strncmp(lnp->line, "push", 4))
3531 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3532 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3534 connectLine (lnp->prev, lnp->next);
3535 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3538 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3540 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3541 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3543 connectLine (lnp->prev, lnp->next);
3544 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3551 for (idx = 0; idx < regsUnneeded->size; idx++)
3552 if (bitVectBitValue (regsUnneeded, idx))
3553 emitcode ("", ";\teliminated unneeded push/pop %s", ds390_regWithIdx (idx)->dname);
3555 freeBitVect (regsUnneeded);
3556 freeBitVect (regsUsed);
3557 freeBitVect (regsUsedPrologue);
3560 /*-----------------------------------------------------------------*/
3561 /* genJavaNativeRet - generate code for return JavaNative */
3562 /*-----------------------------------------------------------------*/
3563 static void genJavaNativeRet(iCode *ic)
3567 aopOp (IC_LEFT (ic), ic, FALSE,
3568 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3569 size = AOP_SIZE (IC_LEFT (ic));
3573 /* it is assigned to GPR0-R3 then push them */
3574 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3575 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3576 for (i = 0 ; i < size ; i++ ) {
3577 emitcode ("push","%s",
3578 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3580 for (i = (size-1) ; i >= 0 ; i--) {
3581 emitcode ("pop","a%s",javaRet[i]);
3584 for (i = 0 ; i < size ; i++)
3585 emitcode ("mov","%s,%s",javaRet[i],
3586 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3588 for (i = size ; i < 4 ; i++ )
3589 emitcode ("mov","%s,#0",javaRet[i]);
3593 /*-----------------------------------------------------------------*/
3594 /* genRet - generate code for return statement */
3595 /*-----------------------------------------------------------------*/
3599 int size, offset = 0, pushed = 0;
3601 D (emitcode (";", "genRet "););
3603 /* if we have no return value then
3604 just generate the "ret" */
3608 /* if this is a JavaNative function then return
3609 value in different register */
3610 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3611 genJavaNativeRet(ic);
3614 /* we have something to return then
3615 move the return value into place */
3616 aopOp (IC_LEFT (ic), ic, FALSE,
3617 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3618 size = AOP_SIZE (IC_LEFT (ic));
3620 _startLazyDPSEvaluation ();
3624 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3626 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3628 emitcode ("push", "%s", l);
3633 /* Since A is the last element of fReturn,
3634 * is is OK to clobber it in the aopGet.
3636 l = aopGet (AOP (IC_LEFT (ic)), offset,
3637 FALSE, FALSE, NULL);
3638 if (strcmp (fReturn[offset], l))
3639 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3642 _endLazyDPSEvaluation ();
3649 if (strcmp (fReturn[pushed], "a"))
3650 emitcode ("pop", fReturn[pushed]);
3652 emitcode ("pop", "acc");
3655 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3658 /* generate a jump to the return label
3659 if the next is not the return statement */
3660 if (!(ic->next && ic->next->op == LABEL &&
3661 IC_LABEL (ic->next) == returnLabel))
3663 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3667 /*-----------------------------------------------------------------*/
3668 /* genLabel - generates a label */
3669 /*-----------------------------------------------------------------*/
3671 genLabel (iCode * ic)
3673 /* special case never generate */
3674 if (IC_LABEL (ic) == entryLabel)
3677 D (emitcode (";", "genLabel ");
3680 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3683 /*-----------------------------------------------------------------*/
3684 /* genGoto - generates a ljmp */
3685 /*-----------------------------------------------------------------*/
3687 genGoto (iCode * ic)
3689 D (emitcode (";", "genGoto ");
3691 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3694 /*-----------------------------------------------------------------*/
3695 /* findLabelBackwards: walks back through the iCode chain looking */
3696 /* for the given label. Returns number of iCode instructions */
3697 /* between that label and given ic. */
3698 /* Returns zero if label not found. */
3699 /*-----------------------------------------------------------------*/
3701 findLabelBackwards (iCode * ic, int key)
3710 /* If we have any pushes or pops, we cannot predict the distance.
3711 I don't like this at all, this should be dealt with in the
3713 if (ic->op == IPUSH || ic->op == IPOP) {
3717 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3719 /* printf("findLabelBackwards = %d\n", count); */
3727 /*-----------------------------------------------------------------*/
3728 /* genPlusIncr :- does addition with increment if possible */
3729 /*-----------------------------------------------------------------*/
3731 genPlusIncr (iCode * ic)
3733 unsigned int icount;
3734 unsigned int size = getDataSize (IC_RESULT (ic));
3736 /* will try to generate an increment */
3737 /* if the right side is not a literal
3739 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3742 /* if the literal value of the right hand side
3743 is greater than 4 then it is not worth it */
3744 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3747 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3748 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3750 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3754 /* if increment 16 bits in register */
3756 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3757 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3758 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3767 /* If the next instruction is a goto and the goto target
3768 * is <= 5 instructions previous to this, we can generate
3769 * jumps straight to that target.
3771 if (ic->next && ic->next->op == GOTO
3772 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3775 D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3776 tlbl = IC_LABEL (ic->next);
3781 tlbl = newiTempLabel (NULL);
3785 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3786 emitcode ("inc", "%s", l);
3788 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3789 IS_AOP_PREG (IC_RESULT (ic)))
3791 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3795 emitcode ("clr", "a");
3796 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3799 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
3800 emitcode ("inc", "%s", l);
3803 if (!strcmp(l, "acc"))
3805 emitcode("jnz", "!tlabel", tlbl->key + 100);
3807 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3808 IS_AOP_PREG (IC_RESULT (ic)))
3810 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3814 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3817 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3818 emitcode ("inc", "%s", l);
3822 if (!strcmp(l, "acc"))
3824 emitcode("jnz", "!tlabel", tlbl->key + 100);
3826 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3827 IS_AOP_PREG (IC_RESULT (ic)))
3829 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3833 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3836 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3837 emitcode ("inc", "%s", l);
3842 emitcode ("", "!tlabeldef", tlbl->key + 100);
3847 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3848 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
3849 options.model == MODEL_FLAT24 )
3851 if (IC_RESULT(ic)->isGptr)
3853 emitcode ("mov","b,%s",aopGet(AOP (IC_LEFT (ic)), 3, FALSE, FALSE, NULL));
3857 emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3859 emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3861 emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3864 while (icount--) emitcode ("inc","dptr");
3868 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3869 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3871 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3872 while (icount--) emitcode ("inc","dptr");
3873 emitcode ("mov","dps,#0");
3877 /* if the sizes are greater than 1 then we cannot */
3878 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3879 AOP_SIZE (IC_LEFT (ic)) > 1)
3882 /* we can if the aops of the left & result match or
3883 if they are in registers and the registers are the
3886 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3887 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3888 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3893 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3894 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3895 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3900 _startLazyDPSEvaluation ();
3903 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3905 _endLazyDPSEvaluation ();
3914 /*-----------------------------------------------------------------*/
3915 /* outBitAcc - output a bit in acc */
3916 /*-----------------------------------------------------------------*/
3918 outBitAcc (operand * result)
3920 symbol *tlbl = newiTempLabel (NULL);
3921 /* if the result is a bit */
3922 if (AOP_TYPE (result) == AOP_CRY)
3924 aopPut (AOP (result), "a", 0);
3928 emitcode ("jz", "!tlabel", tlbl->key + 100);
3929 emitcode ("mov", "a,%s", one);
3930 emitcode ("", "!tlabeldef", tlbl->key + 100);
3935 /*-----------------------------------------------------------------*/
3936 /* genPlusBits - generates code for addition of two bits */
3937 /*-----------------------------------------------------------------*/
3939 genPlusBits (iCode * ic)
3941 D (emitcode (";", "genPlusBits "););
3943 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3945 symbol *lbl = newiTempLabel (NULL);
3946 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3947 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3948 emitcode ("cpl", "c");
3949 emitcode ("", "!tlabeldef", (lbl->key + 100));
3950 outBitC (IC_RESULT (ic));
3954 emitcode ("clr", "a");
3955 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3956 emitcode ("rlc", "a");
3957 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3958 emitcode ("addc", "a,#0");
3959 outAcc (IC_RESULT (ic));
3964 adjustArithmeticResult (iCode * ic)
3966 if (opIsGptr (IC_RESULT (ic)) &&
3967 opIsGptr (IC_LEFT (ic)) &&
3968 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3970 aopPut (AOP (IC_RESULT (ic)),
3971 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3975 if (opIsGptr (IC_RESULT (ic)) &&
3976 opIsGptr (IC_RIGHT (ic)) &&
3977 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3979 aopPut (AOP (IC_RESULT (ic)),
3980 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3984 if (opIsGptr (IC_RESULT (ic)) &&
3985 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3986 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3987 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3988 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3991 SNPRINTF (buff, sizeof(buff),
3992 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3993 aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3997 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3998 // generates the result if possible. If result is generated, returns TRUE; otherwise
3999 // returns false and caller must deal with fact that result isn't aopOp'd.
4000 bool aopOp3(iCode * ic)
4002 bool dp1InUse, dp2InUse;
4005 // First, generate the right opcode. DPTR may be used if neither left nor result are
4008 // D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
4009 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
4010 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
4011 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
4013 // D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
4014 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
4015 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
4016 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
4019 // Right uses DPTR unless left or result is an AOP_STR; however,
4020 // if right is an AOP_STR, it must use DPTR regardless.
4021 if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
4022 && !AOP_IS_STR(IC_RIGHT(ic)))
4031 aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
4033 // if the right used DPTR, left MUST use DPTR2.
4034 // if the right used DPTR2, left MUST use DPTR.
4035 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
4036 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
4037 // enabling us to assign DPTR to result.
4039 if (AOP_USESDPTR(IC_RIGHT(ic)))
4043 else if (AOP_USESDPTR2(IC_RIGHT(ic)))
4049 if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
4059 aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
4062 // We've op'd the left & right. So, if left or right are the same operand as result,
4063 // we know aopOp will succeed, and we can just do it & bail.
4064 if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))
4066 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4069 if (isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
4071 // D(emitcode(";", "aopOp3: (left | right) & result equal"););
4072 aopOp(IC_RESULT(ic),ic,TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4076 // Operands may be equivalent (but not equal) if they share a spill location. If
4077 // so, use the same DPTR or DPTR2.
4078 if (operandsEqu (IC_LEFT(ic), IC_RESULT(ic)))
4080 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4083 if (operandsEqu (IC_RIGHT(ic), IC_RESULT(ic)))
4085 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4089 // Note which dptrs are currently in use.
4090 dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
4091 dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
4093 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
4095 if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
4100 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
4101 if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
4106 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
4107 if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
4112 aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
4114 // Some sanity checking...
4115 if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
4118 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
4119 __FILE__, __LINE__, ic->filename, ic->lineno);
4120 emitcode(";", ">>> unexpected DPTR here.");
4123 if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
4126 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
4127 __FILE__, __LINE__, ic->filename, ic->lineno);
4128 emitcode(";", ">>> unexpected DPTR2 here.");
4134 // Macro to aopOp all three operands of an ic. If this cannot be done,
4135 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
4136 // will be set TRUE. The caller must then handle the case specially, noting
4137 // that the IC_RESULT operand is not aopOp'd.
4139 #define AOP_OP_3_NOFATAL(ic, rc) \
4140 do { rc = !aopOp3(ic); } while (0)
4142 // aopOp the left & right operands of an ic.
4143 #define AOP_OP_2(ic) \
4144 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
4145 aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
4147 // convienience macro.
4148 #define AOP_SET_LOCALS(ic) \
4149 left = IC_LEFT(ic); \
4150 right = IC_RIGHT(ic); \
4151 result = IC_RESULT(ic);
4154 // Given an integer value of pushedSize bytes on the stack,
4155 // adjust it to be resultSize bytes, either by discarding
4156 // the most significant bytes or by zero-padding.
4158 // On exit from this macro, pushedSize will have been adjusted to
4159 // equal resultSize, and ACC may be trashed.
4160 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
4161 /* If the pushed data is bigger than the result, \
4162 * simply discard unused bytes. Icky, but works. \
4164 while (pushedSize > resultSize) \
4166 D (emitcode (";", "discarding unused result byte."););\
4167 emitcode ("pop", "acc"); \
4170 if (pushedSize < resultSize) \
4172 emitcode ("clr", "a"); \
4173 /* Conversly, we haven't pushed enough here. \
4174 * just zero-pad, and all is well. \
4176 while (pushedSize < resultSize) \
4178 emitcode("push", "acc"); \
4182 assert(pushedSize == resultSize);
4184 /*-----------------------------------------------------------------*/
4185 /* genPlus - generates code for addition */
4186 /*-----------------------------------------------------------------*/
4188 genPlus (iCode * ic)
4190 int size, offset = 0;
4194 D (emitcode (";", "genPlus "););
4196 /* special cases :- */
4197 if ( AOP_IS_STR(IC_LEFT(ic)) &&
4198 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4199 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4200 size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4202 while (size--) emitcode ("inc","dptr");
4204 emitcode ("mov","a,dpl");
4205 emitcode ("add","a,#!constbyte",size & 0xff);
4206 emitcode ("mov","dpl,a");
4207 emitcode ("mov","a,dph");
4208 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4209 emitcode ("mov","dph,a");
4210 emitcode ("mov","a,dpx");
4211 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4212 emitcode ("mov","dpx,a");
4214 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4217 if ( IS_SYMOP(IC_LEFT(ic)) &&
4218 OP_SYMBOL(IC_LEFT(ic))->remat &&
4219 isOperandInFarSpace(IC_RIGHT(ic))) {
4220 operand *op = IC_RIGHT(ic);
4221 IC_RIGHT(ic) = IC_LEFT(ic);
4225 AOP_OP_3_NOFATAL (ic, pushResult);
4229 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4234 /* if literal, literal on the right or
4235 if left requires ACC or right is already
4237 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4238 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4239 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4241 operand *t = IC_RIGHT (ic);
4242 IC_RIGHT (ic) = IC_LEFT (ic);
4244 emitcode (";", "Swapped plus args.");
4247 /* if both left & right are in bit
4249 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4250 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4256 /* if left in bit space & right literal */
4257 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4258 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4260 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4261 /* if result in bit space */
4262 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4264 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4265 emitcode ("cpl", "c");
4266 outBitC (IC_RESULT (ic));
4270 size = getDataSize (IC_RESULT (ic));
4271 _startLazyDPSEvaluation ();
4274 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4275 emitcode ("addc", "a,#0");
4276 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4278 _endLazyDPSEvaluation ();
4283 /* if I can do an increment instead
4284 of add then GOOD for ME */
4285 if (genPlusIncr (ic) == TRUE)
4287 emitcode (";", "did genPlusIncr");
4292 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4294 _startLazyDPSEvaluation ();
4297 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4299 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4301 emitcode ("add", "a,%s",
4302 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4304 emitcode ("addc", "a,%s",
4305 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4309 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4311 /* right is going to use ACC or we would have taken the
4314 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4316 D(emitcode(";", "+ AOP_ACC special case."););
4317 emitcode("xch", "a, %s", DP2_RESULT_REG);
4319 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4322 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4325 emitcode("add", "a, %s", DP2_RESULT_REG);
4329 emitcode ("add", "a,%s",
4330 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4336 emitcode ("addc", "a,%s",
4337 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4343 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4347 emitcode ("push", "acc");
4351 _endLazyDPSEvaluation ();
4355 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4357 size = getDataSize (IC_LEFT (ic));
4358 rSize = getDataSize (IC_RESULT (ic));
4360 ADJUST_PUSHED_RESULT(size, rSize);
4362 _startLazyDPSEvaluation ();
4365 emitcode ("pop", "acc");
4366 aopPut (AOP (IC_RESULT (ic)), "a", size);
4368 _endLazyDPSEvaluation ();
4371 adjustArithmeticResult (ic);
4374 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4375 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4376 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4379 /*-----------------------------------------------------------------*/
4380 /* genMinusDec :- does subtraction with deccrement if possible */
4381 /*-----------------------------------------------------------------*/
4383 genMinusDec (iCode * ic)
4385 unsigned int icount;
4386 unsigned int size = getDataSize (IC_RESULT (ic));
4388 /* will try to generate an increment */
4389 /* if the right side is not a literal
4391 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4394 /* if the literal value of the right hand side
4395 is greater than 4 then it is not worth it */
4396 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4399 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4400 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4402 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4406 /* if decrement 16 bits in register */
4407 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4408 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4409 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4418 /* If the next instruction is a goto and the goto target
4419 * is <= 5 instructions previous to this, we can generate
4420 * jumps straight to that target.
4422 if (ic->next && ic->next->op == GOTO
4423 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4426 emitcode (";", "tail decrement optimized (range %d)", labelRange);
4427 tlbl = IC_LABEL (ic->next);
4432 tlbl = newiTempLabel (NULL);
4436 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4437 emitcode ("dec", "%s", l);
4439 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4440 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4441 IS_AOP_PREG (IC_RESULT (ic)))
4443 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4447 emitcode ("mov", "a,#!constbyte",0xff);
4448 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4450 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4451 emitcode ("dec", "%s", l);
4454 if (!strcmp(l, "acc"))
4456 emitcode("jnz", "!tlabel", tlbl->key + 100);
4458 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4459 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4460 IS_AOP_PREG (IC_RESULT (ic)))
4462 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4466 emitcode ("mov", "a,#!constbyte",0xff);
4467 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4469 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4470 emitcode ("dec", "%s", l);
4474 if (!strcmp(l, "acc"))
4476 emitcode("jnz", "!tlabel", tlbl->key + 100);
4478 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4479 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4480 IS_AOP_PREG (IC_RESULT (ic)))
4482 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4486 emitcode ("mov", "a,#!constbyte",0xff);
4487 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4489 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4490 emitcode ("dec", "%s", l);
4494 emitcode ("", "!tlabeldef", tlbl->key + 100);
4499 /* if the sizes are greater than 1 then we cannot */
4500 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4501 AOP_SIZE (IC_LEFT (ic)) > 1)
4504 /* we can if the aops of the left & result match or
4505 if they are in registers and the registers are the
4508 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4509 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4510 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4513 _startLazyDPSEvaluation ();
4516 emitcode ("dec", "%s",
4517 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4519 _endLazyDPSEvaluation ();
4527 /*-----------------------------------------------------------------*/
4528 /* addSign - complete with sign */
4529 /*-----------------------------------------------------------------*/
4531 addSign (operand * result, int offset, int sign)
4533 int size = (getDataSize (result) - offset);
4536 _startLazyDPSEvaluation();
4539 emitcode ("rlc", "a");
4540 emitcode ("subb", "a,acc");
4543 aopPut (AOP (result), "a", offset++);
4550 aopPut (AOP (result), zero, offset++);
4553 _endLazyDPSEvaluation();
4557 /*-----------------------------------------------------------------*/
4558 /* genMinusBits - generates code for subtraction of two bits */
4559 /*-----------------------------------------------------------------*/
4561 genMinusBits (iCode * ic)
4563 symbol *lbl = newiTempLabel (NULL);
4565 D (emitcode (";", "genMinusBits "););
4567 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4569 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4570 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4571 emitcode ("cpl", "c");
4572 emitcode ("", "!tlabeldef", (lbl->key + 100));
4573 outBitC (IC_RESULT (ic));
4577 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4578 emitcode ("subb", "a,acc");
4579 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4580 emitcode ("inc", "a");
4581 emitcode ("", "!tlabeldef", (lbl->key + 100));
4582 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4583 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4587 /*-----------------------------------------------------------------*/
4588 /* genMinus - generates code for subtraction */
4589 /*-----------------------------------------------------------------*/
4591 genMinus (iCode * ic)
4593 int size, offset = 0;
4598 D (emitcode (";", "genMinus "););
4600 AOP_OP_3_NOFATAL(ic, pushResult);
4604 /* special cases :- */
4605 /* if both left & right are in bit space */
4606 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4607 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4613 /* if I can do an decrement instead
4614 of subtract then GOOD for ME */
4615 if (genMinusDec (ic) == TRUE)
4620 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4622 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4628 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4633 /* if literal, add a,#-lit, else normal subb */
4634 _startLazyDPSEvaluation ();
4636 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4637 if (AOP_USESDPTR(IC_RIGHT(ic))) {
4638 emitcode ("mov","b,%s",
4639 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4640 MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4641 emitcode ("subb","a,b");
4643 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4644 emitcode ("subb", "a,%s",
4645 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE,
4649 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4650 /* first add without previous c */
4652 if (!size && lit==-1) {
4653 emitcode ("dec", "a");
4655 emitcode ("add", "a,#!constbyte",
4656 (unsigned int) (lit & 0x0FFL));
4659 emitcode ("addc", "a,#!constbyte",
4660 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4665 emitcode ("push", "acc");
4667 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4671 _endLazyDPSEvaluation ();
4675 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4677 size = getDataSize (IC_LEFT (ic));
4678 rSize = getDataSize (IC_RESULT (ic));
4680 ADJUST_PUSHED_RESULT(size, rSize);
4682 _startLazyDPSEvaluation ();
4685 emitcode ("pop", "acc");
4686 aopPut (AOP (IC_RESULT (ic)), "a", size);
4688 _endLazyDPSEvaluation ();
4691 adjustArithmeticResult (ic);
4694 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4695 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4696 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4700 /*-----------------------------------------------------------------*/
4701 /* genMultbits :- multiplication of bits */
4702 /*-----------------------------------------------------------------*/
4704 genMultbits (operand * left,
4709 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4710 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4711 aopOp(result, ic, TRUE, FALSE);
4716 /*-----------------------------------------------------------------*/
4717 /* genMultOneByte : 8*8=8/16 bit multiplication */
4718 /*-----------------------------------------------------------------*/
4720 genMultOneByte (operand * left,
4727 bool runtimeSign, compiletimeSign;
4728 bool lUnsigned, rUnsigned;
4731 /* (if two literals: the value is computed before) */
4732 /* if one literal, literal on the right */
4733 if (AOP_TYPE (left) == AOP_LIT)
4738 emitcode (";", "swapped left and right");
4741 /* (if two literals: the value is computed before) */
4742 /* if one literal, literal on the right */
4743 if (AOP_TYPE (left) == AOP_LIT)
4748 /* emitcode (";", "swapped left and right"); */
4750 /* if no literal, unsigned on the right: shorter code */
4751 if ( AOP_TYPE (right) != AOP_LIT
4752 && SPEC_USIGN (getSpec (operandType (left))))
4759 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4760 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4762 if ((lUnsigned && rUnsigned)
4763 /* sorry, I don't know how to get size
4764 without calling aopOp (result,...);
4765 see Feature Request */
4766 /* || size == 1 */ ) /* no, this is not a bug; with a 1 byte result there's
4767 no need to take care about the signedness! */
4769 /* just an unsigned 8 * 8 = 8 multiply
4771 /* emitcode (";","unsigned"); */
4772 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4773 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4774 emitcode ("mul", "ab");
4776 _G.accInUse++; _G.bInUse++;
4777 aopOp (result, ic, TRUE, FALSE);
4778 size = AOP_SIZE (result);
4780 if (size < 1 || size > 2)
4782 /* this should never happen */
4783 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4784 size, __FILE__, lineno);
4788 aopPut (AOP (result), "a", 0);
4789 _G.accInUse--; _G.bInUse--;
4791 aopPut (AOP (result), "b", 1);
4795 /* we have to do a signed multiply */
4796 /* emitcode (";", "signed"); */
4798 /* now sign adjust for both left & right */
4800 /* let's see what's needed: */
4801 /* apply negative sign during runtime */
4802 runtimeSign = FALSE;
4803 /* negative sign from literals */
4804 compiletimeSign = FALSE;
4808 if (AOP_TYPE(left) == AOP_LIT)
4810 /* signed literal */
4811 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4813 compiletimeSign = TRUE;
4816 /* signed but not literal */
4822 if (AOP_TYPE(right) == AOP_LIT)
4824 /* signed literal */
4825 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4827 compiletimeSign ^= TRUE;
4830 /* signed but not literal */
4834 /* initialize F0, which stores the runtime sign */
4837 if (compiletimeSign)
4838 emitcode ("setb", "F0"); /* set sign flag */
4840 emitcode ("clr", "F0"); /* reset sign flag */
4843 /* save the signs of the operands */
4844 if (AOP_TYPE(right) == AOP_LIT)
4846 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4848 if (!rUnsigned && val < 0)
4849 emitcode ("mov", "b,#!constbyte", -val);
4851 emitcode ("mov", "b,#!constbyte", (unsigned char) val);
4853 else /* ! literal */
4855 if (rUnsigned) /* emitcode (";", "signed"); */
4856 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4859 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4860 lbl = newiTempLabel (NULL);
4861 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
4862 emitcode ("cpl", "F0"); /* complement sign flag */
4863 emitcode ("cpl", "a"); /* 2's complement */
4864 emitcode ("inc", "a");
4865 emitcode ("", "!tlabeldef", lbl->key + 100);
4866 emitcode ("mov", "b,a");
4870 if (AOP_TYPE(left) == AOP_LIT)
4872 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4874 if (!lUnsigned && val < 0)
4875 emitcode ("mov", "a,#!constbyte", -val);
4877 emitcode ("mov", "a,#!constbyte", (unsigned char) val);
4879 else /* ! literal */
4881 if (lUnsigned) /* emitcode (";", "signed"); */
4883 emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4886 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4887 lbl = newiTempLabel (NULL);
4888 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
4889 emitcode ("cpl", "F0"); /* complement sign flag */
4890 emitcode ("cpl", "a"); /* 2's complement */
4891 emitcode ("inc", "a");
4892 emitcode ("", "!tlabeldef", lbl->key + 100);
4896 /* now the multiplication */
4897 emitcode ("mul", "ab");
4898 _G.accInUse++;_G.bInUse++;
4899 aopOp(result, ic, TRUE, FALSE);
4900 size = AOP_SIZE (result);
4902 if (size < 1 || size > 2)
4904 /* this should never happen */
4905 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4906 size, __FILE__, lineno);
4910 if (runtimeSign || compiletimeSign)
4912 lbl = newiTempLabel (NULL);
4914 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
4915 emitcode ("cpl", "a"); /* lsb 2's complement */
4917 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4920 emitcode ("add", "a,#1"); /* this sets carry flag */
4921 emitcode ("xch", "a,b");
4922 emitcode ("cpl", "a"); /* msb 2's complement */
4923 emitcode ("addc", "a,#0");
4924 emitcode ("xch", "a,b");
4926 emitcode ("", "!tlabeldef", lbl->key + 100);
4928 aopPut (AOP (result), "a", 0);
4929 _G.accInUse--;_G.bInUse--;
4931 aopPut (AOP (result), "b", 1);
4934 /*-----------------------------------------------------------------*/
4935 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4936 /*-----------------------------------------------------------------*/
4937 static void genMultTwoByte (operand *left, operand *right,
4938 operand *result, iCode *ic)
4940 sym_link *retype = getSpec(operandType(right));
4941 sym_link *letype = getSpec(operandType(left));
4942 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4945 if (AOP_TYPE (left) == AOP_LIT) {
4950 /* save EA bit in F1 */
4951 lbl = newiTempLabel(NULL);
4952 emitcode ("setb","F1");
4953 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4954 emitcode ("clr","F1");
4955 emitcode("","!tlabeldef",lbl->key+100);
4957 /* load up MB with right */
4959 emitcode("clr","F0");
4960 if (AOP_TYPE(right) == AOP_LIT) {
4961 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4963 emitcode("setb","F0");
4966 emitcode ("mov","mb,#!constbyte",val & 0xff);
4967 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4969 lbl = newiTempLabel(NULL);
4970 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4971 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4972 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4973 emitcode ("xch", "a,b");
4974 emitcode ("cpl","a");
4975 emitcode ("add", "a,#1");
4976 emitcode ("xch", "a,b");
4977 emitcode ("cpl", "a"); // msb
4978 emitcode ("addc", "a,#0");
4979 emitcode ("setb","F0");
4980 emitcode ("","!tlabeldef",lbl->key+100);
4981 emitcode ("mov","mb,b");
4982 emitcode ("mov","mb,a");
4985 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4986 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4988 /* load up MA with left */
4990 lbl = newiTempLabel(NULL);
4991 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4992 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4993 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4994 emitcode ("xch", "a,b");
4995 emitcode ("cpl","a");
4996 emitcode ("add", "a,#1");
4997 emitcode ("xch", "a,b");
4998 emitcode ("cpl", "a"); // msb
4999 emitcode ("addc","a,#0");
5000 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5001 emitcode ("setb","F0");
5002 emitcode ("","!tlabeldef",lbl->key+100);
5003 emitcode ("mov","ma,b");
5004 emitcode ("mov","ma,a");
5006 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5007 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5009 /* wait for multiplication to finish */
5010 lbl = newiTempLabel(NULL);
5011 emitcode("","!tlabeldef", lbl->key+100);
5012 emitcode("mov","a,mcnt1");
5013 emitcode("anl","a,#!constbyte",0x80);
5014 emitcode("jnz","!tlabel",lbl->key+100);
5016 freeAsmop (left, NULL, ic, TRUE);
5017 freeAsmop (right, NULL, ic,TRUE);
5018 aopOp(result, ic, TRUE, FALSE);
5020 /* if unsigned then simple */
5022 emitcode ("mov","a,ma");
5023 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
5024 emitcode ("mov","a,ma");
5025 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
5026 aopPut(AOP(result),"ma",1);
5027 aopPut(AOP(result),"ma",0);
5029 emitcode("push","ma");
5030 emitcode("push","ma");
5031 emitcode("push","ma");
5033 /* negate result if needed */
5034 lbl = newiTempLabel(NULL);
5035 emitcode("jnb","F0,!tlabel",lbl->key+100);
5036 emitcode("cpl","a");
5037 emitcode("add","a,#1");
5038 emitcode("","!tlabeldef", lbl->key+100);
5039 if (AOP_TYPE(result) == AOP_ACC)
5041 D(emitcode(";", "ACC special case."););
5042 /* We know result is the only live aop, and
5043 * it's obviously not a DPTR2, so AP is available.
5045 emitcode("mov", "%s,acc", DP2_RESULT_REG);
5049 aopPut(AOP(result),"a",0);
5052 emitcode("pop","acc");
5053 lbl = newiTempLabel(NULL);
5054 emitcode("jnb","F0,!tlabel",lbl->key+100);
5055 emitcode("cpl","a");
5056 emitcode("addc","a,#0");
5057 emitcode("","!tlabeldef", lbl->key+100);
5058 aopPut(AOP(result),"a",1);
5059 emitcode("pop","acc");
5060 if (AOP_SIZE(result) >= 3) {
5061 lbl = newiTempLabel(NULL);
5062 emitcode("jnb","F0,!tlabel",lbl->key+100);
5063 emitcode("cpl","a");
5064 emitcode("addc","a,#0");
5065 emitcode("","!tlabeldef", lbl->key+100);
5066 aopPut(AOP(result),"a",2);
5068 emitcode("pop","acc");
5069 if (AOP_SIZE(result) >= 4) {
5070 lbl = newiTempLabel(NULL);
5071 emitcode("jnb","F0,!tlabel",lbl->key+100);
5072 emitcode("cpl","a");
5073 emitcode("addc","a,#0");
5074 emitcode("","!tlabeldef", lbl->key+100);
5075 aopPut(AOP(result),"a",3);
5077 if (AOP_TYPE(result) == AOP_ACC)
5079 /* We stashed the result away above. */
5080 emitcode("mov", "acc,%s", DP2_RESULT_REG);
5084 freeAsmop (result, NULL, ic, TRUE);
5086 /* restore EA bit in F1 */
5087 lbl = newiTempLabel(NULL);
5088 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5089 emitcode ("setb","EA");
5090 emitcode("","!tlabeldef",lbl->key+100);
5094 /*-----------------------------------------------------------------*/
5095 /* genMult - generates code for multiplication */
5096 /*-----------------------------------------------------------------*/
5098 genMult (iCode * ic)
5100 operand *left = IC_LEFT (ic);
5101 operand *right = IC_RIGHT (ic);
5102 operand *result = IC_RESULT (ic);
5104 D (emitcode (";", "genMult "););
5106 /* assign the amsops */
5109 /* special cases first */
5111 if (AOP_TYPE (left) == AOP_CRY &&
5112 AOP_TYPE (right) == AOP_CRY)
5114 genMultbits (left, right, result, ic);
5118 /* if both are of size == 1 */
5119 if (AOP_SIZE (left) == 1 &&
5120 AOP_SIZE (right) == 1)
5122 genMultOneByte (left, right, result, ic);
5126 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5127 /* use the ds390 ARITHMETIC accel UNIT */
5128 genMultTwoByte (left, right, result, ic);
5131 /* should have been converted to function call */
5135 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5136 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5137 freeAsmop (result, NULL, ic, TRUE);
5140 /*-----------------------------------------------------------------*/
5141 /* genDivbits :- division of bits */
5142 /*-----------------------------------------------------------------*/
5144 genDivbits (operand * left,
5152 /* the result must be bit */
5153 LOAD_AB_FOR_DIV (left, right, l);
5154 emitcode ("div", "ab");
5155 emitcode ("rrc", "a");
5156 aopOp(result, ic, TRUE, FALSE);
5158 aopPut (AOP (result), "c", 0);
5161 /*-----------------------------------------------------------------*/
5162 /* genDivOneByte : 8 bit division */
5163 /*-----------------------------------------------------------------*/
5165 genDivOneByte (operand * left,
5170 bool lUnsigned, rUnsigned;
5171 bool runtimeSign, compiletimeSign;
5177 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5178 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5180 /* signed or unsigned */
5181 if (lUnsigned && rUnsigned)
5183 /* unsigned is easy */
5184 LOAD_AB_FOR_DIV (left, right, l);
5185 emitcode ("div", "ab");
5188 aopOp (result, ic, TRUE, FALSE);
5189 aopPut (AOP (result), "a", 0);
5192 size = AOP_SIZE (result) - 1;
5195 aopPut (AOP (result), zero, offset++);
5199 /* signed is a little bit more difficult */
5201 /* now sign adjust for both left & right */
5203 /* let's see what's needed: */
5204 /* apply negative sign during runtime */
5205 runtimeSign = FALSE;
5206 /* negative sign from literals */
5207 compiletimeSign = FALSE;
5211 if (AOP_TYPE(left) == AOP_LIT)
5213 /* signed literal */
5214 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5216 compiletimeSign = TRUE;
5219 /* signed but not literal */
5225 if (AOP_TYPE(right) == AOP_LIT)
5227 /* signed literal */
5228 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5230 compiletimeSign ^= TRUE;
5233 /* signed but not literal */
5237 /* initialize F0, which stores the runtime sign */
5240 if (compiletimeSign)
5241 emitcode ("setb", "F0"); /* set sign flag */
5243 emitcode ("clr", "F0"); /* reset sign flag */
5246 /* save the signs of the operands */
5247 if (AOP_TYPE(right) == AOP_LIT)
5249 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5251 if (!rUnsigned && val < 0)
5252 emitcode ("mov", "b,#0x%02x", -val);
5254 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5256 else /* ! literal */
5259 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5262 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5263 lbl = newiTempLabel (NULL);
5264 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5265 emitcode ("cpl", "F0"); /* complement sign flag */
5266 emitcode ("cpl", "a"); /* 2's complement */
5267 emitcode ("inc", "a");
5268 emitcode ("", "!tlabeldef", lbl->key + 100);
5269 emitcode ("mov", "b,a");
5273 if (AOP_TYPE(left) == AOP_LIT)
5275 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5277 if (!lUnsigned && val < 0)
5278 emitcode ("mov", "a,#0x%02x", -val);
5280 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5282 else /* ! literal */
5285 emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5288 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5289 lbl = newiTempLabel (NULL);
5290 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5291 emitcode ("cpl", "F0"); /* complement sign flag */
5292 emitcode ("cpl", "a"); /* 2's complement */
5293 emitcode ("inc", "a");
5294 emitcode ("", "!tlabeldef", lbl->key + 100);
5298 /* now the division */
5299 emitcode ("nop", "; workaround for DS80C390 div bug.");
5300 emitcode ("div", "ab");
5302 if (runtimeSign || compiletimeSign)
5304 lbl = newiTempLabel (NULL);
5306 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5307 emitcode ("cpl", "a"); /* lsb 2's complement */
5308 emitcode ("inc", "a");
5309 emitcode ("", "!tlabeldef", lbl->key + 100);
5311 _G.accInUse++; _G.bInUse++;
5312 aopOp (result, ic, TRUE, FALSE);
5313 size = AOP_SIZE (result) - 1;
5317 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5318 then the result will be in b, a */
5319 emitcode ("mov", "b,a"); /* 1 */
5320 /* msb is 0x00 or 0xff depending on the sign */
5323 emitcode ("mov", "c,F0");
5324 emitcode ("subb", "a,acc");
5325 emitcode ("xch", "a,b"); /* 2 */
5327 aopPut (AOP (result), "b", offset++); /* write msb's */
5329 else /* compiletimeSign */
5331 aopPut (AOP (result), "#0xff", offset++); /* write msb's */
5333 aopPut (AOP (result), "a", 0); /* 3: write lsb */
5337 _G.accInUse++; _G.bInUse++;
5338 aopOp(result, ic, TRUE, FALSE);
5339 size = AOP_SIZE (result) - 1;
5341 aopPut (AOP (result), "a", 0);
5343 aopPut (AOP (result), zero, offset++);
5345 _G.accInUse--; _G.bInUse--;
5349 /*-----------------------------------------------------------------*/
5350 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
5351 /*-----------------------------------------------------------------*/
5352 static void genDivTwoByte (operand *left, operand *right,
5353 operand *result, iCode *ic)
5355 sym_link *retype = getSpec(operandType(right));
5356 sym_link *letype = getSpec(operandType(left));
5357 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5360 /* save EA bit in F1 */
5361 lbl = newiTempLabel(NULL);
5362 emitcode ("setb","F1");
5363 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5364 emitcode ("clr","F1");
5365 emitcode("","!tlabeldef",lbl->key+100);
5367 /* load up MA with left */
5369 emitcode("clr","F0");
5370 lbl = newiTempLabel(NULL);
5371 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5372 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5373 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5374 emitcode ("xch", "a,b");
5375 emitcode ("cpl","a");
5376 emitcode ("add", "a,#1");
5377 emitcode ("xch", "a,b");
5378 emitcode ("cpl", "a"); // msb
5379 emitcode ("addc","a,#0");
5380 emitcode ("setb","F0");
5381 emitcode ("","!tlabeldef",lbl->key+100);
5382 emitcode ("mov","ma,b");
5383 emitcode ("mov","ma,a");
5385 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5386 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5389 /* load up MB with right */
5391 if (AOP_TYPE(right) == AOP_LIT) {
5392 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5394 lbl = newiTempLabel(NULL);
5395 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5396 emitcode("setb","F0");
5397 emitcode ("","!tlabeldef",lbl->key+100);
5400 emitcode ("mov","mb,#!constbyte",val & 0xff);
5401 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5403 lbl = newiTempLabel(NULL);
5404 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5405 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5406 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5407 emitcode ("xch", "a,b");
5408 emitcode ("cpl","a");
5409 emitcode ("add", "a,#1");
5410 emitcode ("xch", "a,b");
5411 emitcode ("cpl", "a"); // msb
5412 emitcode ("addc", "a,#0");
5413 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5414 emitcode ("setb","F0");
5415 emitcode ("","!tlabeldef",lbl->key+100);
5416 emitcode ("mov","mb,b");
5417 emitcode ("mov","mb,a");
5420 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5421 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5424 /* wait for multiplication to finish */
5425 lbl = newiTempLabel(NULL);
5426 emitcode("","!tlabeldef", lbl->key+100);
5427 emitcode("mov","a,mcnt1");
5428 emitcode("anl","a,#!constbyte",0x80);
5429 emitcode("jnz","!tlabel",lbl->key+100);
5431 freeAsmop (left, NULL, ic, TRUE);
5432 freeAsmop (right, NULL, ic,TRUE);
5433 aopOp(result, ic, TRUE, FALSE);
5435 /* if unsigned then simple */
5437 aopPut(AOP(result),"ma",1);
5438 aopPut(AOP(result),"ma",0);
5440 emitcode("push","ma");
5442 /* negate result if needed */
5443 lbl = newiTempLabel(NULL);
5444 emitcode("jnb","F0,!tlabel",lbl->key+100);
5445 emitcode("cpl","a");
5446 emitcode("add","a,#1");
5447 emitcode("","!tlabeldef", lbl->key+100);
5448 aopPut(AOP(result),"a",0);
5449 emitcode("pop","acc");
5450 lbl = newiTempLabel(NULL);
5451 emitcode("jnb","F0,!tlabel",lbl->key+100);
5452 emitcode("cpl","a");
5453 emitcode("addc","a,#0");
5454 emitcode("","!tlabeldef", lbl->key+100);
5455 aopPut(AOP(result),"a",1);
5457 freeAsmop (result, NULL, ic, TRUE);
5458 /* restore EA bit in F1 */
5459 lbl = newiTempLabel(NULL);
5460 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5461 emitcode ("setb","EA");
5462 emitcode("","!tlabeldef",lbl->key+100);
5466 /*-----------------------------------------------------------------*/
5467 /* genDiv - generates code for division */
5468 /*-----------------------------------------------------------------*/
5472 operand *left = IC_LEFT (ic);
5473 operand *right = IC_RIGHT (ic);
5474 operand *result = IC_RESULT (ic);
5476 D (emitcode (";", "genDiv "););
5478 /* assign the amsops */
5481 /* special cases first */
5483 if (AOP_TYPE (left) == AOP_CRY &&
5484 AOP_TYPE (right) == AOP_CRY)
5486 genDivbits (left, right, result, ic);
5490 /* if both are of size == 1 */
5491 if (AOP_SIZE (left) == 1 &&
5492 AOP_SIZE (right) == 1)
5494 genDivOneByte (left, right, result, ic);
5498 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5499 /* use the ds390 ARITHMETIC accel UNIT */
5500 genDivTwoByte (left, right, result, ic);
5503 /* should have been converted to function call */
5506 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5507 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5508 freeAsmop (result, NULL, ic, TRUE);
5511 /*-----------------------------------------------------------------*/
5512 /* genModbits :- modulus of bits */
5513 /*-----------------------------------------------------------------*/
5515 genModbits (operand * left,
5523 /* the result must be bit */
5524 LOAD_AB_FOR_DIV (left, right, l);
5525 emitcode ("div", "ab");
5526 emitcode ("mov", "a,b");
5527 emitcode ("rrc", "a");
5528 aopOp(result, ic, TRUE, FALSE);
5529 aopPut (AOP (result), "c", 0);
5532 /*-----------------------------------------------------------------*/
5533 /* genModOneByte : 8 bit modulus */
5534 /*-----------------------------------------------------------------*/
5536 genModOneByte (operand * left,
5541 bool lUnsigned, rUnsigned;
5542 bool runtimeSign, compiletimeSign;
5548 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5549 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5551 /* signed or unsigned */
5552 if (lUnsigned && rUnsigned)
5554 /* unsigned is easy */
5555 LOAD_AB_FOR_DIV (left, right, l);
5556 emitcode ("div", "ab");
5557 aopOp (result, ic, TRUE, FALSE);
5558 aopPut (AOP (result), "b", 0);
5560 for (size = AOP_SIZE (result) - 1; size--;)
5561 aopPut (AOP (result), zero, offset++);
5565 /* signed is a little bit more difficult */
5567 /* now sign adjust for both left & right */
5569 /* modulus: sign of the right operand has no influence on the result! */
5570 if (AOP_TYPE(right) == AOP_LIT)
5572 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5574 if (!rUnsigned && val < 0)
5575 emitcode ("mov", "b,#0x%02x", -val);
5577 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5579 else /* ! literal */
5582 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5585 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5586 lbl = newiTempLabel (NULL);
5587 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5588 emitcode ("cpl", "a"); /* 2's complement */
5589 emitcode ("inc", "a");
5590 emitcode ("", "!tlabeldef", lbl->key + 100);
5591 emitcode ("mov", "b,a");
5595 /* let's see what's needed: */
5596 /* apply negative sign during runtime */
5597 runtimeSign = FALSE;
5598 /* negative sign from literals */
5599 compiletimeSign = FALSE;
5601 /* sign adjust left side */
5602 if (AOP_TYPE(left) == AOP_LIT)
5604 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5606 if (!lUnsigned && val < 0)
5608 compiletimeSign = TRUE; /* set sign flag */
5609 emitcode ("mov", "a,#0x%02x", -val);
5612 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5614 else /* ! literal */
5616 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5621 emitcode ("clr", "F0"); /* clear sign flag */
5623 lbl = newiTempLabel (NULL);
5624 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5625 emitcode ("setb", "F0"); /* set sign flag */
5626 emitcode ("cpl", "a"); /* 2's complement */
5627 emitcode ("inc", "a");
5628 emitcode ("", "!tlabeldef", lbl->key + 100);
5632 /* now the modulus */
5633 emitcode ("nop", "; workaround for DS80C390 div bug.");
5634 emitcode ("div", "ab");
5636 if (runtimeSign || compiletimeSign)
5638 emitcode ("mov", "a,b");
5639 lbl = newiTempLabel (NULL);
5641 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5642 emitcode ("cpl", "a"); /* lsb 2's complement */
5643 emitcode ("inc", "a");
5644 emitcode ("", "!tlabeldef", lbl->key + 100);
5646 _G.accInUse++; _G.bInUse++;
5647 aopOp (result, ic, TRUE, FALSE);
5648 size = AOP_SIZE (result) - 1;
5652 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5653 then the result will be in b, a */
5654 emitcode ("mov", "b,a"); /* 1 */
5655 /* msb is 0x00 or 0xff depending on the sign */
5658 emitcode ("mov", "c,F0");
5659 emitcode ("subb", "a,acc");
5660 emitcode ("xch", "a,b"); /* 2 */
5662 aopPut (AOP (result), "b", offset++); /* write msb's */
5664 else /* compiletimeSign */
5666 aopPut (AOP (result), "#0xff", offset++); /* write msb's */
5668 aopPut (AOP (result), "a", 0); /* 3: write lsb */
5672 _G.accInUse++; _G.bInUse++;
5673 aopOp(result, ic, TRUE, FALSE);
5674 size = AOP_SIZE (result) - 1;
5676 aopPut (AOP (result), "b", 0);
5678 aopPut (AOP (result), zero, offset++);
5680 _G.accInUse--; _G.bInUse--;
5684 /*-----------------------------------------------------------------*/
5685 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
5686 /*-----------------------------------------------------------------*/
5687 static void genModTwoByte (operand *left, operand *right,
5688 operand *result, iCode *ic)
5690 sym_link *retype = getSpec(operandType(right));
5691 sym_link *letype = getSpec(operandType(left));
5692 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5695 /* load up MA with left */
5696 /* save EA bit in F1 */
5697 lbl = newiTempLabel(NULL);
5698 emitcode ("setb","F1");
5699 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5700 emitcode ("clr","F1");
5701 emitcode("","!tlabeldef",lbl->key+100);
5704 lbl = newiTempLabel(NULL);
5705 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5706 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5707 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5708 emitcode ("xch", "a,b");
5709 emitcode ("cpl","a");
5710 emitcode ("add", "a,#1");
5711 emitcode ("xch", "a,b");
5712 emitcode ("cpl", "a"); // msb
5713 emitcode ("addc","a,#0");
5714 emitcode ("","!tlabeldef",lbl->key+100);
5715 emitcode ("mov","ma,b");
5716 emitcode ("mov","ma,a");
5718 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5719 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5722 /* load up MB with right */
5724 if (AOP_TYPE(right) == AOP_LIT) {
5725 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5729 emitcode ("mov","mb,#!constbyte",val & 0xff);
5730 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5732 lbl = newiTempLabel(NULL);
5733 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5734 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5735 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5736 emitcode ("xch", "a,b");
5737 emitcode ("cpl","a");
5738 emitcode ("add", "a,#1");
5739 emitcode ("xch", "a,b");
5740 emitcode ("cpl", "a"); // msb
5741 emitcode ("addc", "a,#0");
5742 emitcode ("","!tlabeldef",lbl->key+100);
5743 emitcode ("mov","mb,b");
5744 emitcode ("mov","mb,a");
5747 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5748 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5751 /* wait for multiplication to finish */
5752 lbl = newiTempLabel(NULL);
5753 emitcode("","!tlabeldef", lbl->key+100);
5754 emitcode("mov","a,mcnt1");
5755 emitcode("anl","a,#!constbyte",0x80);
5756 emitcode("jnz","!tlabel",lbl->key+100);
5758 freeAsmop (left, NULL, ic, TRUE);
5759 freeAsmop (right, NULL, ic,TRUE);
5760 aopOp(result, ic, TRUE, FALSE);
5762 aopPut(AOP(result),"mb",1);
5763 aopPut(AOP(result),"mb",0);
5764 freeAsmop (result, NULL, ic, TRUE);
5766 /* restore EA bit in F1 */
5767 lbl = newiTempLabel(NULL);
5768 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5769 emitcode ("setb","EA");
5770 emitcode("","!tlabeldef",lbl->key+100);
5774 /*-----------------------------------------------------------------*/
5775 /* genMod - generates code for division */
5776 /*-----------------------------------------------------------------*/
5780 operand *left = IC_LEFT (ic);
5781 operand *right = IC_RIGHT (ic);
5782 operand *result = IC_RESULT (ic);
5784 D (emitcode (";", "genMod "); );
5786 /* assign the amsops */
5789 /* special cases first */
5791 if (AOP_TYPE (left) == AOP_CRY &&
5792 AOP_TYPE (right) == AOP_CRY)
5794 genModbits (left, right, result, ic);
5798 /* if both are of size == 1 */
5799 if (AOP_SIZE (left) == 1 &&
5800 AOP_SIZE (right) == 1)
5802 genModOneByte (left, right, result, ic);
5806 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5807 /* use the ds390 ARITHMETIC accel UNIT */
5808 genModTwoByte (left, right, result, ic);
5812 /* should have been converted to function call */
5816 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5817 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5818 freeAsmop (result, NULL, ic, TRUE);
5821 /*-----------------------------------------------------------------*/
5822 /* genIfxJump :- will create a jump depending on the ifx */
5823 /*-----------------------------------------------------------------*/
5825 genIfxJump (iCode * ic, char *jval)
5828 symbol *tlbl = newiTempLabel (NULL);
5831 D (emitcode (";", "genIfxJump"););
5833 /* if true label then we jump if condition
5837 jlbl = IC_TRUE (ic);
5838 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5839 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5843 /* false label is present */
5844 jlbl = IC_FALSE (ic);
5845 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5846 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5848 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5849 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5851 emitcode (inst, "!tlabel", tlbl->key + 100);
5852 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5853 emitcode ("", "!tlabeldef", tlbl->key + 100);
5855 /* mark the icode as generated */
5859 /*-----------------------------------------------------------------*/
5860 /* genCmp :- greater or less than comparison */
5861 /*-----------------------------------------------------------------*/
5863 genCmp (operand * left, operand * right,
5864 iCode * ic, iCode * ifx, int sign)
5866 int size, offset = 0;
5867 unsigned long lit = 0L;
5870 D (emitcode (";", "genCmp"););
5872 result = IC_RESULT (ic);
5874 /* if left & right are bit variables */
5875 if (AOP_TYPE (left) == AOP_CRY &&
5876 AOP_TYPE (right) == AOP_CRY)
5878 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5879 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5883 /* subtract right from left if at the
5884 end the carry flag is set then we know that
5885 left is greater than right */
5886 size = max (AOP_SIZE (left), AOP_SIZE (right));
5888 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5889 if ((size == 1) && !sign
5890 && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5892 symbol *lbl = newiTempLabel (NULL);
5893 emitcode ("cjne", "%s,%s,!tlabel",
5894 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5895 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5897 emitcode ("", "!tlabeldef", lbl->key + 100);
5901 if (AOP_TYPE (right) == AOP_LIT)
5903 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5904 /* optimize if(x < 0) or if(x >= 0) */
5913 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5915 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5916 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5918 aopOp (result, ic, FALSE, FALSE);
5920 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5922 freeAsmop (result, NULL, ic, TRUE);
5923 genIfxJump (ifx, "acc.7");
5928 emitcode ("rlc", "a");
5930 goto release_freedLR;
5938 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5939 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5940 // emitcode (";", "genCmp #2");
5941 if (sign && (size == 0))
5943 // emitcode (";", "genCmp #3");
5944 emitcode ("xrl", "a,#!constbyte",0x80);
5945 if (AOP_TYPE (right) == AOP_LIT)
5947 unsigned long lit = (unsigned long)
5948 floatFromVal (AOP (right)->aopu.aop_lit);
5949 // emitcode (";", "genCmp #3.1");
5950 emitcode ("subb", "a,#!constbyte",
5951 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5955 // emitcode (";", "genCmp #3.2");
5957 MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5958 saveAccWarn = DEFAULT_ACC_WARNING;
5959 emitcode ("xrl", "b,#!constbyte",0x80);
5960 emitcode ("subb", "a,b");
5967 // emitcode (";", "genCmp #4");
5969 s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5970 saveAccWarn = DEFAULT_ACC_WARNING;
5972 emitcode ("subb", "a,%s", s);
5979 /* Don't need the left & right operands any more; do need the result. */
5980 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5981 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5983 aopOp (result, ic, FALSE, FALSE);
5987 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5993 /* if the result is used in the next
5994 ifx conditional branch then generate
5995 code a little differently */
5998 genIfxJump (ifx, "c");
6004 /* leave the result in acc */
6006 freeAsmop (result, NULL, ic, TRUE);
6009 /*-----------------------------------------------------------------*/
6010 /* genCmpGt :- greater than comparison */
6011 /*-----------------------------------------------------------------*/
6013 genCmpGt (iCode * ic, iCode * ifx)
6015 operand *left, *right;
6016 sym_link *letype, *retype;
6019 D (emitcode (";", "genCmpGt ");
6022 left = IC_LEFT (ic);
6023 right = IC_RIGHT (ic);
6025 letype = getSpec (operandType (left));
6026 retype = getSpec (operandType (right));
6027 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6029 /* assign the left & right amsops */
6032 genCmp (right, left, ic, ifx, sign);
6035 /*-----------------------------------------------------------------*/
6036 /* genCmpLt - less than comparisons */
6037 /*-----------------------------------------------------------------*/
6039 genCmpLt (iCode * ic, iCode * ifx)
6041 operand *left, *right;
6042 sym_link *letype, *retype;
6045 D (emitcode (";", "genCmpLt "););
6047 left = IC_LEFT (ic);
6048 right = IC_RIGHT (ic);
6050 letype = getSpec (operandType (left));
6051 retype = getSpec (operandType (right));
6052 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6054 /* assign the left & right amsops */
6057 genCmp (left, right, ic, ifx, sign);
6060 /*-----------------------------------------------------------------*/
6061 /* gencjneshort - compare and jump if not equal */
6062 /*-----------------------------------------------------------------*/
6064 gencjneshort (operand * left, operand * right, symbol * lbl)
6066 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6068 unsigned long lit = 0L;
6070 D (emitcode (";", "gencjneshort");
6073 /* if the left side is a literal or
6074 if the right is in a pointer register and left
6076 if ((AOP_TYPE (left) == AOP_LIT) ||
6077 (AOP_TYPE (left) == AOP_IMMD) ||
6078 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6085 if (AOP_TYPE (right) == AOP_LIT)
6086 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6088 if (opIsGptr (left) || opIsGptr (right))
6090 /* We are comparing a generic pointer to something.
6091 * Exclude the generic type byte from the comparison.
6094 D (emitcode (";", "cjneshort: generic ptr special case."););
6098 /* if the right side is a literal then anything goes */
6099 if (AOP_TYPE (right) == AOP_LIT &&
6100 AOP_TYPE (left) != AOP_DIR)
6104 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6105 emitcode ("cjne", "a,%s,!tlabel",
6106 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
6112 /* if the right side is in a register or in direct space or
6113 if the left is a pointer register & right is not */
6114 else if (AOP_TYPE (right) == AOP_REG ||
6115 AOP_TYPE (right) == AOP_DIR ||
6116 AOP_TYPE (right) == AOP_LIT ||
6117 AOP_TYPE (right) == AOP_IMMD ||
6118 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6119 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6123 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6124 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6125 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6126 emitcode ("jnz", "!tlabel", lbl->key + 100);
6128 emitcode ("cjne", "a,%s,!tlabel",
6129 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
6136 /* right is a pointer reg need both a & b */
6139 MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6140 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6141 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
6147 /*-----------------------------------------------------------------*/
6148 /* gencjne - compare and jump if not equal */
6149 /*-----------------------------------------------------------------*/
6151 gencjne (operand * left, operand * right, symbol * lbl)
6153 symbol *tlbl = newiTempLabel (NULL);
6155 D (emitcode (";", "gencjne");
6158 gencjneshort (left, right, lbl);
6160 emitcode ("mov", "a,%s", one);
6161 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
6162 emitcode ("", "!tlabeldef", lbl->key + 100);
6163 emitcode ("clr", "a");
6164 emitcode ("", "!tlabeldef", tlbl->key + 100);
6167 /*-----------------------------------------------------------------*/
6168 /* genCmpEq - generates code for equal to */
6169 /*-----------------------------------------------------------------*/
6171 genCmpEq (iCode * ic, iCode * ifx)
6173 operand *left, *right, *result;
6175 D (emitcode (";", "genCmpEq ");
6179 AOP_SET_LOCALS (ic);
6181 /* if literal, literal on the right or
6182 if the right is in a pointer register and left
6184 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6185 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6187 operand *t = IC_RIGHT (ic);
6188 IC_RIGHT (ic) = IC_LEFT (ic);
6192 if (ifx && /* !AOP_SIZE(result) */
6193 OP_SYMBOL (result) &&
6194 OP_SYMBOL (result)->regType == REG_CND)
6197 /* if they are both bit variables */
6198 if (AOP_TYPE (left) == AOP_CRY &&
6199 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6201 if (AOP_TYPE (right) == AOP_LIT)
6203 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6206 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6207 emitcode ("cpl", "c");
6211 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6215 emitcode ("clr", "c");
6217 /* AOP_TYPE(right) == AOP_CRY */
6221 symbol *lbl = newiTempLabel (NULL);
6222 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6223 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6224 emitcode ("cpl", "c");
6225 emitcode ("", "!tlabeldef", (lbl->key + 100));
6227 /* if true label then we jump if condition
6229 tlbl = newiTempLabel (NULL);
6232 emitcode ("jnc", "!tlabel", tlbl->key + 100);
6233 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6237 emitcode ("jc", "!tlabel", tlbl->key + 100);
6238 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6240 emitcode ("", "!tlabeldef", tlbl->key + 100);
6244 tlbl = newiTempLabel (NULL);
6245 gencjneshort (left, right, tlbl);
6248 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6249 emitcode ("", "!tlabeldef", tlbl->key + 100);
6253 symbol *lbl = newiTempLabel (NULL);
6254 emitcode ("sjmp", "!tlabel", lbl->key + 100);
6255 emitcode ("", "!tlabeldef", tlbl->key + 100);
6256 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6257 emitcode ("", "!tlabeldef", lbl->key + 100);
6260 /* mark the icode as generated */
6263 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6264 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6268 /* if they are both bit variables */
6269 if (AOP_TYPE (left) == AOP_CRY &&
6270 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6272 if (AOP_TYPE (right) == AOP_LIT)
6274 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6277 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6278 emitcode ("cpl", "c");
6282 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6286 emitcode ("clr", "c");
6288 /* AOP_TYPE(right) == AOP_CRY */
6292 symbol *lbl = newiTempLabel (NULL);
6293 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6294 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6295 emitcode ("cpl", "c");
6296 emitcode ("", "!tlabeldef", (lbl->key + 100));
6299 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6300 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6302 aopOp (result, ic, TRUE, FALSE);
6305 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6312 genIfxJump (ifx, "c");
6315 /* if the result is used in an arithmetic operation
6316 then put the result in place */
6321 gencjne (left, right, newiTempLabel (NULL));
6323 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6324 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6326 aopOp (result, ic, TRUE, FALSE);
6328 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6330 aopPut (AOP (result), "a", 0);
6335 genIfxJump (ifx, "a");
6338 /* if the result is used in an arithmetic operation
6339 then put the result in place */
6340 if (AOP_TYPE (result) != AOP_CRY)
6342 /* leave the result in acc */
6346 freeAsmop (result, NULL, ic, TRUE);
6349 /*-----------------------------------------------------------------*/
6350 /* ifxForOp - returns the icode containing the ifx for operand */
6351 /*-----------------------------------------------------------------*/
6353 ifxForOp (operand * op, iCode * ic)
6355 /* if true symbol then needs to be assigned */
6356 if (IS_TRUE_SYMOP (op))
6359 /* if this has register type condition and
6360 the next instruction is ifx with the same operand
6361 and live to of the operand is upto the ifx only then */
6363 ic->next->op == IFX &&
6364 IC_COND (ic->next)->key == op->key &&
6365 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6370 /*-----------------------------------------------------------------*/
6371 /* hasInc - operand is incremented before any other use */
6372 /*-----------------------------------------------------------------*/
6374 hasInc (operand *op, iCode *ic, int osize)
6376 sym_link *type = operandType(op);
6377 sym_link *retype = getSpec (type);
6378 iCode *lic = ic->next;
6381 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6382 if (!IS_SYMOP(op)) return NULL;
6384 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6385 if (IS_AGGREGATE(type->next)) return NULL;
6386 if (osize != (isize = getSize(type->next))) return NULL;
6389 /* if operand of the form op = op + <sizeof *op> */
6390 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6391 isOperandEqual(IC_RESULT(lic),op) &&
6392 isOperandLiteral(IC_RIGHT(lic)) &&
6393 operandLitValue(IC_RIGHT(lic)) == isize) {
6396 /* if the operand used or deffed */
6397 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
6400 /* if GOTO or IFX */
6401 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6407 /*-----------------------------------------------------------------*/
6408 /* genAndOp - for && operation */
6409 /*-----------------------------------------------------------------*/
6411 genAndOp (iCode * ic)
6413 operand *left, *right, *result;
6416 D (emitcode (";", "genAndOp "););
6418 /* note here that && operations that are in an
6419 if statement are taken away by backPatchLabels
6420 only those used in arthmetic operations remain */
6422 AOP_SET_LOCALS (ic);
6424 /* if both are bit variables */
6425 if (AOP_TYPE (left) == AOP_CRY &&
6426 AOP_TYPE (right) == AOP_CRY)
6428 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6429 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6430 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6431 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6433 aopOp (result,ic,FALSE, FALSE);
6438 tlbl = newiTempLabel (NULL);
6440 emitcode ("jz", "!tlabel", tlbl->key + 100);
6442 emitcode ("", "!tlabeldef", tlbl->key + 100);
6443 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6444 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6446 aopOp (result,ic,FALSE, FALSE);
6449 freeAsmop (result, NULL, ic, TRUE);
6453 /*-----------------------------------------------------------------*/
6454 /* genOrOp - for || operation */
6455 /*-----------------------------------------------------------------*/
6457 genOrOp (iCode * ic)
6459 operand *left, *right, *result;
6462 D (emitcode (";", "genOrOp "););
6464 /* note here that || operations that are in an
6465 if statement are taken away by backPatchLabels
6466 only those used in arthmetic operations remain */
6468 AOP_SET_LOCALS (ic);
6470 /* if both are bit variables */
6471 if (AOP_TYPE (left) == AOP_CRY &&
6472 AOP_TYPE (right) == AOP_CRY)
6474 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6475 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6476 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6477 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6479 aopOp (result,ic,FALSE, FALSE);
6485 tlbl = newiTempLabel (NULL);
6487 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6489 emitcode ("", "!tlabeldef", tlbl->key + 100);
6490 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6491 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6493 aopOp (result,ic,FALSE, FALSE);
6498 freeAsmop (result, NULL, ic, TRUE);
6501 /*-----------------------------------------------------------------*/
6502 /* isLiteralBit - test if lit == 2^n */
6503 /*-----------------------------------------------------------------*/
6505 isLiteralBit (unsigned long lit)
6507 unsigned long pw[32] =
6508 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6509 0x100L, 0x200L, 0x400L, 0x800L,
6510 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6511 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6512 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6513 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6514 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6517 for (idx = 0; idx < 32; idx++)
6523 /*-----------------------------------------------------------------*/
6524 /* continueIfTrue - */
6525 /*-----------------------------------------------------------------*/
6527 continueIfTrue (iCode * ic)
6530 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6534 /*-----------------------------------------------------------------*/
6536 /*-----------------------------------------------------------------*/
6538 jumpIfTrue (iCode * ic)
6541 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6545 /*-----------------------------------------------------------------*/
6546 /* jmpTrueOrFalse - */
6547 /*-----------------------------------------------------------------*/
6549 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6551 // ugly but optimized by peephole
6554 symbol *nlbl = newiTempLabel (NULL);
6555 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6556 emitcode ("", "!tlabeldef", tlbl->key + 100);
6557 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6558 emitcode ("", "!tlabeldef", nlbl->key + 100);
6562 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6563 emitcode ("", "!tlabeldef", tlbl->key + 100);
6568 // Generate code to perform a bit-wise logic operation
6569 // on two operands in far space (assumed to already have been
6570 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6571 // in far space. This requires pushing the result on the stack
6572 // then popping it into the result.
6574 genFarFarLogicOp(iCode *ic, char *logicOp)
6576 int size, resultSize, compSize;
6580 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6581 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
6582 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6584 _startLazyDPSEvaluation();
6585 for (size = compSize; (size--); offset++)
6587 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6588 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6589 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6591 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6592 emitcode ("push", "acc");
6594 _endLazyDPSEvaluation();
6596 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6597 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6598 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6600 resultSize = AOP_SIZE(IC_RESULT(ic));
6602 ADJUST_PUSHED_RESULT(compSize, resultSize);
6604 _startLazyDPSEvaluation();
6607 emitcode ("pop", "acc");
6608 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6610 _endLazyDPSEvaluation();
6611 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6615 /*-----------------------------------------------------------------*/
6616 /* genAnd - code for and */
6617 /*-----------------------------------------------------------------*/
6619 genAnd (iCode * ic, iCode * ifx)
6621 operand *left, *right, *result;
6622 int size, offset = 0;
6623 unsigned long lit = 0L;
6628 D (emitcode (";", "genAnd "););
6630 AOP_OP_3_NOFATAL (ic, pushResult);
6631 AOP_SET_LOCALS (ic);
6635 genFarFarLogicOp(ic, "anl");
6640 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6642 AOP_TYPE (left), AOP_TYPE (right));
6643 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6645 AOP_SIZE (left), AOP_SIZE (right));
6648 /* if left is a literal & right is not then exchange them */
6649 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6650 #ifdef LOGIC_OPS_BROKEN
6651 || AOP_NEEDSACC (left)
6655 operand *tmp = right;
6660 /* if result = right then exchange left and right */
6661 if (sameRegs (AOP (result), AOP (right)))
6663 operand *tmp = right;
6668 /* if right is bit then exchange them */
6669 if (AOP_TYPE (right) == AOP_CRY &&
6670 AOP_TYPE (left) != AOP_CRY)
6672 operand *tmp = right;
6676 if (AOP_TYPE (right) == AOP_LIT)
6677 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6679 size = AOP_SIZE (result);
6682 // result = bit & yy;
6683 if (AOP_TYPE (left) == AOP_CRY)
6685 // c = bit & literal;
6686 if (AOP_TYPE (right) == AOP_LIT)
6690 if (size && sameRegs (AOP (result), AOP (left)))
6693 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6698 if (size && (AOP_TYPE (result) == AOP_CRY))
6700 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6703 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6708 emitcode ("clr", "c");
6713 if (AOP_TYPE (right) == AOP_CRY)
6716 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6717 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6722 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6724 emitcode ("rrc", "a");
6725 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6733 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6734 genIfxJump (ifx, "c");
6738 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6739 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6740 if ((AOP_TYPE (right) == AOP_LIT) &&
6741 (AOP_TYPE (result) == AOP_CRY) &&
6742 (AOP_TYPE (left) != AOP_CRY))
6744 int posbit = isLiteralBit (lit);
6749 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6752 emitcode ("mov", "c,acc.%d", posbit & 0x07);
6758 SNPRINTF (buff, sizeof(buff),
6759 "acc.%d", posbit & 0x07);
6760 genIfxJump (ifx, buff);
6764 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6771 symbol *tlbl = newiTempLabel (NULL);
6772 int sizel = AOP_SIZE (left);
6774 emitcode ("setb", "c");
6777 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6779 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6781 if ((posbit = isLiteralBit (bytelit)) != 0)
6782 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6785 if (bytelit != 0x0FFL)
6786 emitcode ("anl", "a,%s",
6787 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6788 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6793 // bit = left & literal
6796 emitcode ("clr", "c");
6797 emitcode ("", "!tlabeldef", tlbl->key + 100);
6799 // if(left & literal)
6803 jmpTrueOrFalse (ifx, tlbl);
6805 emitcode ("", "!tlabeldef", tlbl->key + 100);
6813 /* if left is same as result */
6814 if (sameRegs (AOP (result), AOP (left)))
6816 for (; size--; offset++)
6818 if (AOP_TYPE (right) == AOP_LIT)
6820 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6821 if (bytelit == 0x0FF)
6823 /* dummy read of volatile operand */
6824 if (isOperandVolatile (left, FALSE))
6825 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6829 else if (bytelit == 0)
6831 aopPut (AOP (result), zero, offset);
6833 else if (IS_AOP_PREG (result))
6835 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6836 emitcode ("anl", "a,%s",
6837 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6838 aopPut (AOP (result), "a", offset);
6841 emitcode ("anl", "%s,%s",
6842 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6843 aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6847 if (AOP_TYPE (left) == AOP_ACC)
6848 emitcode ("anl", "a,%s",
6849 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6852 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6853 if (IS_AOP_PREG (result))
6855 emitcode ("anl", "a,%s",
6856 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6857 aopPut (AOP (result), "a", offset);
6860 emitcode ("anl", "%s,a",
6861 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6868 // left & result in different registers
6869 if (AOP_TYPE (result) == AOP_CRY)
6872 // if(size), result in bit
6873 // if(!size && ifx), conditional oper: if(left & right)
6874 symbol *tlbl = newiTempLabel (NULL);
6875 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6877 emitcode ("setb", "c");
6880 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6881 emitcode ("anl", "a,%s",
6882 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6884 if (AOP_TYPE(left)==AOP_ACC) {
6885 emitcode("mov", "b,a");
6886 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6887 emitcode("anl", "a,b");
6889 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6890 emitcode ("anl", "a,%s",
6891 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6894 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6900 emitcode ("", "!tlabeldef", tlbl->key + 100);
6904 jmpTrueOrFalse (ifx, tlbl);
6906 emitcode ("", "!tlabeldef", tlbl->key + 100);
6910 for (; (size--); offset++)
6913 // result = left & right
6914 if (AOP_TYPE (right) == AOP_LIT)
6916 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6917 if (bytelit == 0x0FF)
6919 aopPut (AOP (result),
6920 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6924 else if (bytelit == 0)
6926 /* dummy read of volatile operand */
6927 if (isOperandVolatile (left, FALSE))
6928 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6929 aopPut (AOP (result), zero, offset);
6932 D (emitcode (";", "better literal AND."););
6933 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6934 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6935 FALSE, FALSE, DP2_RESULT_REG));
6940 // faster than result <- left, anl result,right
6941 // and better if result is SFR
6942 if (AOP_TYPE (left) == AOP_ACC)
6944 emitcode ("anl", "a,%s",
6945 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6949 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6950 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6952 emitcode("mov", "b,a");
6956 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6957 emitcode ("anl", "a,%s", rOp);
6960 aopPut (AOP (result), "a", offset);
6966 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6967 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6968 freeAsmop (result, NULL, ic, TRUE);
6972 /*-----------------------------------------------------------------*/
6973 /* genOr - code for or */
6974 /*-----------------------------------------------------------------*/
6976 genOr (iCode * ic, iCode * ifx)
6978 operand *left, *right, *result;
6979 int size, offset = 0;
6980 unsigned long lit = 0L;
6984 D (emitcode (";", "genOr "););
6986 AOP_OP_3_NOFATAL (ic, pushResult);
6987 AOP_SET_LOCALS (ic);
6991 genFarFarLogicOp(ic, "orl");
6997 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6999 AOP_TYPE (left), AOP_TYPE (right));
7000 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7002 AOP_SIZE (left), AOP_SIZE (right));
7005 /* if left is a literal & right is not then exchange them */
7006 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7007 #ifdef LOGIC_OPS_BROKEN
7008 || AOP_NEEDSACC (left) // I think this is a net loss now.
7012 operand *tmp = right;
7017 /* if result = right then exchange them */
7018 if (sameRegs (AOP (result), AOP (right)))
7020 operand *tmp = right;
7025 /* if right is bit then exchange them */
7026 if (AOP_TYPE (right) == AOP_CRY &&
7027 AOP_TYPE (left) != AOP_CRY)
7029 operand *tmp = right;
7033 if (AOP_TYPE (right) == AOP_LIT)
7034 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7036 size = AOP_SIZE (result);
7040 if (AOP_TYPE (left) == AOP_CRY)
7042 if (AOP_TYPE (right) == AOP_LIT)
7044 // c = bit & literal;
7047 // lit != 0 => result = 1
7048 if (AOP_TYPE (result) == AOP_CRY)
7051 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7053 continueIfTrue (ifx);
7056 emitcode ("setb", "c");
7060 // lit == 0 => result = left
7061 if (size && sameRegs (AOP (result), AOP (left)))
7063 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7068 if (AOP_TYPE (right) == AOP_CRY)
7071 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7072 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7077 symbol *tlbl = newiTempLabel (NULL);
7078 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7079 emitcode ("setb", "c");
7080 emitcode ("jb", "%s,!tlabel",
7081 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7083 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7084 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7086 jmpTrueOrFalse (ifx, tlbl);
7092 emitcode ("", "!tlabeldef", tlbl->key + 100);
7101 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7102 genIfxJump (ifx, "c");
7106 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7107 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7108 if ((AOP_TYPE (right) == AOP_LIT) &&
7109 (AOP_TYPE (result) == AOP_CRY) &&
7110 (AOP_TYPE (left) != AOP_CRY))
7116 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7118 continueIfTrue (ifx);
7123 // lit = 0, result = boolean(left)
7125 emitcode ("setb", "c");
7129 symbol *tlbl = newiTempLabel (NULL);
7130 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7132 emitcode ("", "!tlabeldef", tlbl->key + 100);
7136 genIfxJump (ifx, "a");
7144 /* if left is same as result */
7145 if (sameRegs (AOP (result), AOP (left)))
7147 for (; size--; offset++)
7149 if (AOP_TYPE (right) == AOP_LIT)
7151 bytelit = (int)((lit >> (offset * 8)) & 0x0FFL);
7152 if (bytelit == 0x00L)
7154 /* dummy read of volatile operand */
7155 if (isOperandVolatile (left, FALSE))
7156 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7160 else if (bytelit == 0x0FF)
7162 aopPut (AOP (result), "#0xFF", offset);
7164 else if (IS_AOP_PREG (left))
7166 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7167 emitcode ("orl", "a,%s",
7168 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7169 aopPut (AOP (result), "a", offset);
7173 emitcode ("orl", "%s,%s",
7174 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7175 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7180 if (AOP_TYPE (left) == AOP_ACC)
7182 emitcode ("orl", "a,%s",
7183 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7187 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7188 if (IS_AOP_PREG (left))
7190 emitcode ("orl", "a,%s",
7191 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7192 aopPut (AOP (result), "a", offset);
7196 emitcode ("orl", "%s,a",
7197 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7205 // left & result in different registers
7206 if (AOP_TYPE (result) == AOP_CRY)
7209 // if(size), result in bit
7210 // if(!size && ifx), conditional oper: if(left | right)
7211 symbol *tlbl = newiTempLabel (NULL);
7212 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7214 emitcode ("setb", "c");
7217 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7218 emitcode ("orl", "a,%s",
7219 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7221 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7222 emitcode ("orl", "a,%s",
7223 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
7225 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7231 emitcode ("", "!tlabeldef", tlbl->key + 100);
7235 jmpTrueOrFalse (ifx, tlbl);
7237 emitcode ("", "!tlabeldef", tlbl->key + 100);
7241 _startLazyDPSEvaluation();
7242 for (; (size--); offset++)
7245 // result = left & right
7246 if (AOP_TYPE (right) == AOP_LIT)
7248 bytelit = (int)((lit >> (offset * 8)) & 0x0FFL);
7249 if (bytelit == 0x00L)
7251 aopPut (AOP (result),
7252 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7256 else if (bytelit == 0x0FF)
7258 /* dummy read of volatile operand */
7259 if (isOperandVolatile (left, FALSE))
7260 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7261 aopPut (AOP (result), "#0xFF", offset);
7264 D (emitcode (";", "better literal OR."););
7265 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7266 emitcode ("orl", "a, %s",
7267 aopGet (AOP (right), offset,
7268 FALSE, FALSE, DP2_RESULT_REG));
7273 // faster than result <- left, anl result,right
7274 // and better if result is SFR
7275 if (AOP_TYPE (left) == AOP_ACC)
7277 emitcode ("orl", "a,%s",
7278 aopGet (AOP (right), offset,
7279 FALSE, FALSE, DP2_RESULT_REG));
7283 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7285 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7287 emitcode("mov", "b,a");
7291 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7292 emitcode ("orl", "a,%s", rOp);
7295 aopPut (AOP (result), "a", offset);
7297 _endLazyDPSEvaluation();
7302 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7303 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7304 freeAsmop (result, NULL, ic, TRUE);
7307 /*-----------------------------------------------------------------*/
7308 /* genXor - code for xclusive or */
7309 /*-----------------------------------------------------------------*/
7311 genXor (iCode * ic, iCode * ifx)
7313 operand *left, *right, *result;
7314 int size, offset = 0;
7315 unsigned long lit = 0L;
7319 D (emitcode (";", "genXor "););
7321 AOP_OP_3_NOFATAL (ic, pushResult);
7322 AOP_SET_LOCALS (ic);
7326 genFarFarLogicOp(ic, "xrl");
7331 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7333 AOP_TYPE (left), AOP_TYPE (right));
7334 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7336 AOP_SIZE (left), AOP_SIZE (right));
7339 /* if left is a literal & right is not ||
7340 if left needs acc & right does not */
7341 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7342 #ifdef LOGIC_OPS_BROKEN
7343 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
7347 operand *tmp = right;
7352 /* if result = right then exchange them */
7353 if (sameRegs (AOP (result), AOP (right)))
7355 operand *tmp = right;
7360 /* if right is bit then exchange them */
7361 if (AOP_TYPE (right) == AOP_CRY &&
7362 AOP_TYPE (left) != AOP_CRY)
7364 operand *tmp = right;
7368 if (AOP_TYPE (right) == AOP_LIT)
7369 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7371 size = AOP_SIZE (result);
7375 if (AOP_TYPE (left) == AOP_CRY)
7377 if (AOP_TYPE (right) == AOP_LIT)
7379 // c = bit & literal;
7382 // lit>>1 != 0 => result = 1
7383 if (AOP_TYPE (result) == AOP_CRY)
7386 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7388 continueIfTrue (ifx);
7391 emitcode ("setb", "c");
7398 // lit == 0, result = left
7399 if (size && sameRegs (AOP (result), AOP (left)))
7401 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7405 // lit == 1, result = not(left)
7406 if (size && sameRegs (AOP (result), AOP (left)))
7408 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7413 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7414 emitcode ("cpl", "c");
7423 symbol *tlbl = newiTempLabel (NULL);
7424 if (AOP_TYPE (right) == AOP_CRY)
7427 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7431 int sizer = AOP_SIZE (right);
7433 // if val>>1 != 0, result = 1
7434 emitcode ("setb", "c");
7437 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
7439 // test the msb of the lsb
7440 emitcode ("anl", "a,#!constbyte",0xfe);
7441 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7445 emitcode ("rrc", "a");
7447 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7448 emitcode ("cpl", "c");
7449 emitcode ("", "!tlabeldef", (tlbl->key + 100));
7456 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7457 genIfxJump (ifx, "c");
7461 /* if left is same as result */
7462 if (sameRegs (AOP (result), AOP (left)))
7464 for (; size--; offset++)
7466 if (AOP_TYPE (right) == AOP_LIT)
7468 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7469 if (bytelit == 0x00L)
7471 /* dummy read of volatile operand */
7472 if (isOperandVolatile (left, FALSE))
7473 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7477 else if (IS_AOP_PREG (left))
7479 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7480 emitcode ("xrl", "a,%s",
7481 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7482 aopPut (AOP (result), "a", offset);
7486 emitcode ("xrl", "%s,%s",
7487 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7488 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7493 if (AOP_TYPE (left) == AOP_ACC)
7494 emitcode ("xrl", "a,%s",
7495 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7498 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7499 if (IS_AOP_PREG (left))
7501 emitcode ("xrl", "a,%s",
7502 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7503 aopPut (AOP (result), "a", offset);
7506 emitcode ("xrl", "%s,a",
7507 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7514 // left & result in different registers
7515 if (AOP_TYPE (result) == AOP_CRY)
7518 // if(size), result in bit
7519 // if(!size && ifx), conditional oper: if(left ^ right)
7520 symbol *tlbl = newiTempLabel (NULL);
7521 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7524 emitcode ("setb", "c");
7527 if ((AOP_TYPE (right) == AOP_LIT) &&
7528 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7530 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7534 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7535 emitcode ("xrl", "a,%s",
7536 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7538 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7539 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7541 emitcode("mov", "b,a");
7545 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7546 emitcode ("xrl", "a,%s", rOp);
7549 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7555 emitcode ("", "!tlabeldef", tlbl->key + 100);
7559 jmpTrueOrFalse (ifx, tlbl);
7563 for (; (size--); offset++)
7566 // result = left & right
7567 if (AOP_TYPE (right) == AOP_LIT)
7569 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7571 aopPut (AOP (result),
7572 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7576 D (emitcode (";", "better literal XOR."););
7577 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7578 emitcode ("xrl", "a, %s",
7579 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7583 // faster than result <- left, anl result,right
7584 // and better if result is SFR
7585 if (AOP_TYPE (left) == AOP_ACC)
7587 emitcode ("xrl", "a,%s",
7588 aopGet (AOP (right), offset,
7589 FALSE, FALSE, DP2_RESULT_REG));
7593 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7594 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7596 emitcode("mov", "b,a");
7600 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7601 emitcode ("xrl", "a,%s", rOp);
7604 aopPut (AOP (result), "a", offset);
7611 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7612 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7613 freeAsmop (result, NULL, ic, TRUE);
7616 /*-----------------------------------------------------------------*/
7617 /* genInline - write the inline code out */
7618 /*-----------------------------------------------------------------*/
7620 genInline (iCode * ic)
7622 char *buffer, *bp, *bp1;
7624 D (emitcode (";", "genInline "); );
7626 _G.inLine += (!options.asmpeep);
7628 buffer = Safe_strdup(IC_INLINE(ic));
7632 /* emit each line as a code */
7657 /* emitcode("",buffer); */
7658 _G.inLine -= (!options.asmpeep);
7661 /*-----------------------------------------------------------------*/
7662 /* genRRC - rotate right with carry */
7663 /*-----------------------------------------------------------------*/
7667 operand *left, *result;
7670 D (emitcode (";", "genRRC "););
7672 /* rotate right with carry */
7673 left = IC_LEFT (ic);
7674 result = IC_RESULT (ic);
7675 aopOp (left, ic, FALSE, FALSE);
7676 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7678 /* move it to the result */
7679 size = AOP_SIZE (result);
7683 _startLazyDPSEvaluation ();
7686 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7687 emitcode ("rrc", "a");
7688 if (AOP_SIZE (result) > 1)
7689 aopPut (AOP (result), "a", offset--);
7691 _endLazyDPSEvaluation ();
7693 /* now we need to put the carry into the
7694 highest order byte of the result */
7695 if (AOP_SIZE (result) > 1)
7697 MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7699 emitcode ("mov", "acc.7,c");
7700 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7701 freeAsmop (left, NULL, ic, TRUE);
7702 freeAsmop (result, NULL, ic, TRUE);
7705 /*-----------------------------------------------------------------*/
7706 /* genRLC - generate code for rotate left with carry */
7707 /*-----------------------------------------------------------------*/
7711 operand *left, *result;
7715 D (emitcode (";", "genRLC "););
7717 /* rotate right with carry */
7718 left = IC_LEFT (ic);
7719 result = IC_RESULT (ic);
7720 aopOp (left, ic, FALSE, FALSE);
7721 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7723 /* move it to the result */
7724 size = AOP_SIZE (result);
7728 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7730 emitcode ("add", "a,acc");
7731 if (AOP_SIZE (result) > 1)
7733 aopPut (AOP (result), "a", offset++);
7736 _startLazyDPSEvaluation ();
7739 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7741 emitcode ("rlc", "a");
7742 if (AOP_SIZE (result) > 1)
7743 aopPut (AOP (result), "a", offset++);
7745 _endLazyDPSEvaluation ();
7747 /* now we need to put the carry into the
7748 highest order byte of the result */
7749 if (AOP_SIZE (result) > 1)
7751 l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7754 emitcode ("mov", "acc.0,c");
7755 aopPut (AOP (result), "a", 0);
7756 freeAsmop (left, NULL, ic, TRUE);
7757 freeAsmop (result, NULL, ic, TRUE);
7760 /*-----------------------------------------------------------------*/
7761 /* genGetHbit - generates code get highest order bit */
7762 /*-----------------------------------------------------------------*/
7764 genGetHbit (iCode * ic)
7766 operand *left, *result;
7767 left = IC_LEFT (ic);
7768 result = IC_RESULT (ic);
7769 aopOp (left, ic, FALSE, FALSE);
7770 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7772 D (emitcode (";", "genGetHbit "););
7774 /* get the highest order byte into a */
7775 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7776 if (AOP_TYPE (result) == AOP_CRY)
7778 emitcode ("rlc", "a");
7783 emitcode ("rl", "a");
7784 emitcode ("anl", "a,#1");
7789 freeAsmop (left, NULL, ic, TRUE);
7790 freeAsmop (result, NULL, ic, TRUE);
7793 /*-----------------------------------------------------------------*/
7794 /* genSwap - generates code to swap nibbles or bytes */
7795 /*-----------------------------------------------------------------*/
7797 genSwap (iCode * ic)
7799 operand *left, *result;
7801 D(emitcode ("; genSwap",""));
7803 left = IC_LEFT (ic);
7804 result = IC_RESULT (ic);
7805 aopOp (left, ic, FALSE, FALSE);
7806 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7808 _startLazyDPSEvaluation ();
7809 switch (AOP_SIZE (left))
7811 case 1: /* swap nibbles in byte */
7812 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7813 emitcode ("swap", "a");
7814 aopPut (AOP (result), "a", 0);
7816 case 2: /* swap bytes in word */
7817 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7819 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7820 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7821 aopPut (AOP (result), "a", 1);
7823 else if (operandsEqu (left, result))
7826 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7827 if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
7829 emitcode ("mov", "b,a");
7833 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7834 aopPut (AOP (result), reg, 1);
7839 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7840 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE, NULL), 1);
7844 wassertl(FALSE, "unsupported SWAP operand size");
7846 _endLazyDPSEvaluation ();
7848 freeAsmop (left, NULL, ic, TRUE);
7849 freeAsmop (result, NULL, ic, TRUE);
7852 /*-----------------------------------------------------------------*/
7853 /* AccRol - rotate left accumulator by known count */
7854 /*-----------------------------------------------------------------*/
7856 AccRol (int shCount)
7858 shCount &= 0x0007; // shCount : 0..7
7865 emitcode ("rl", "a");
7868 emitcode ("rl", "a");
7869 emitcode ("rl", "a");
7872 emitcode ("swap", "a");
7873 emitcode ("rr", "a");
7876 emitcode ("swap", "a");
7879 emitcode ("swap", "a");
7880 emitcode ("rl", "a");
7883 emitcode ("rr", "a");
7884 emitcode ("rr", "a");
7887 emitcode ("rr", "a");
7892 /*-----------------------------------------------------------------*/
7893 /* AccLsh - left shift accumulator by known count */
7894 /*-----------------------------------------------------------------*/
7896 AccLsh (int shCount)
7901 emitcode ("add", "a,acc");
7902 else if (shCount == 2)
7904 emitcode ("add", "a,acc");
7905 emitcode ("add", "a,acc");
7909 /* rotate left accumulator */
7911 /* and kill the lower order bits */
7912 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7917 /*-----------------------------------------------------------------*/
7918 /* AccRsh - right shift accumulator by known count */
7919 /*-----------------------------------------------------------------*/
7921 AccRsh (int shCount)
7928 emitcode ("rrc", "a");
7932 /* rotate right accumulator */
7933 AccRol (8 - shCount);
7934 /* and kill the higher order bits */
7935 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7940 #ifdef BETTER_LITERAL_SHIFT
7941 /*-----------------------------------------------------------------*/
7942 /* AccSRsh - signed right shift accumulator by known count */
7943 /*-----------------------------------------------------------------*/
7945 AccSRsh (int shCount)
7952 emitcode ("mov", "c,acc.7");
7953 emitcode ("rrc", "a");
7955 else if (shCount == 2)
7957 emitcode ("mov", "c,acc.7");
7958 emitcode ("rrc", "a");
7959 emitcode ("mov", "c,acc.7");
7960 emitcode ("rrc", "a");
7964 tlbl = newiTempLabel (NULL);
7965 /* rotate right accumulator */
7966 AccRol (8 - shCount);
7967 /* and kill the higher order bits */
7968 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7969 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7970 emitcode ("orl", "a,#!constbyte",
7971 (unsigned char) ~SRMask[shCount]);
7972 emitcode ("", "!tlabeldef", tlbl->key + 100);
7978 #ifdef BETTER_LITERAL_SHIFT
7979 /*-----------------------------------------------------------------*/
7980 /* shiftR1Left2Result - shift right one byte from left to result */
7981 /*-----------------------------------------------------------------*/
7983 shiftR1Left2Result (operand * left, int offl,
7984 operand * result, int offr,
7985 int shCount, int sign)
7987 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7988 /* shift right accumulator */
7993 aopPut (AOP (result), "a", offr);
7997 #ifdef BETTER_LITERAL_SHIFT
7998 /*-----------------------------------------------------------------*/
7999 /* shiftL1Left2Result - shift left one byte from left to result */
8000 /*-----------------------------------------------------------------*/
8002 shiftL1Left2Result (operand * left, int offl,
8003 operand * result, int offr, int shCount)
8005 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8006 /* shift left accumulator */
8008 aopPut (AOP (result), "a", offr);
8012 #ifdef BETTER_LITERAL_SHIFT
8013 /*-----------------------------------------------------------------*/
8014 /* movLeft2Result - move byte from left to result */
8015 /*-----------------------------------------------------------------*/
8017 movLeft2Result (operand * left, int offl,
8018 operand * result, int offr, int sign)
8021 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8023 l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
8025 if (*l == '@' && (IS_AOP_PREG (result)))
8027 emitcode ("mov", "a,%s", l);
8028 aopPut (AOP (result), "a", offr);
8034 aopPut (AOP (result), l, offr);
8038 /* MSB sign in acc.7 ! */
8039 if (getDataSize (left) == offl + 1)
8041 emitcode ("mov", "a,%s", l);
8042 aopPut (AOP (result), "a", offr);
8050 #ifdef BETTER_LITERAL_SHIFT
8051 /*-----------------------------------------------------------------*/
8052 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8053 /*-----------------------------------------------------------------*/
8057 emitcode ("rrc", "a");
8058 emitcode ("xch", "a,%s", x);
8059 emitcode ("rrc", "a");
8060 emitcode ("xch", "a,%s", x);
8064 #ifdef BETTER_LITERAL_SHIFT
8066 /*-----------------------------------------------------------------*/
8067 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8068 /*-----------------------------------------------------------------*/
8072 emitcode ("xch", "a,%s", x);
8073 emitcode ("rlc", "a");
8074 emitcode ("xch", "a,%s", x);
8075 emitcode ("rlc", "a");
8079 #ifdef BETTER_LITERAL_SHIFT
8080 /*-----------------------------------------------------------------*/
8081 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8082 /*-----------------------------------------------------------------*/
8086 emitcode ("xch", "a,%s", x);
8087 emitcode ("add", "a,acc");
8088 emitcode ("xch", "a,%s", x);
8089 emitcode ("rlc", "a");
8093 #ifdef BETTER_LITERAL_SHIFT
8094 /*-----------------------------------------------------------------*/
8095 /* AccAXLsh - left shift a:x by known count (0..7) */
8096 /*-----------------------------------------------------------------*/
8098 AccAXLsh (char *x, int shCount)
8113 case 5: // AAAAABBB:CCCCCDDD
8115 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8117 emitcode ("anl", "a,#!constbyte",
8118 SLMask[shCount]); // BBB00000:CCCCCDDD
8120 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8122 AccRol (shCount); // DDDCCCCC:BBB00000
8124 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8126 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8128 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8130 emitcode ("anl", "a,#!constbyte",
8131 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8133 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8135 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8138 case 6: // AAAAAABB:CCCCCCDD
8139 emitcode ("anl", "a,#!constbyte",
8140 SRMask[shCount]); // 000000BB:CCCCCCDD
8141 emitcode ("mov", "c,acc.0"); // c = B
8142 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8144 AccAXRrl1 (x); // BCCCCCCD:D000000B
8145 AccAXRrl1 (x); // BBCCCCCC:DD000000
8147 emitcode("rrc","a");
8148 emitcode("xch","a,%s", x);
8149 emitcode("rrc","a");
8150 emitcode("mov","c,acc.0"); //<< get correct bit
8151 emitcode("xch","a,%s", x);
8153 emitcode("rrc","a");
8154 emitcode("xch","a,%s", x);
8155 emitcode("rrc","a");
8156 emitcode("xch","a,%s", x);
8159 case 7: // a:x <<= 7
8161 emitcode ("anl", "a,#!constbyte",
8162 SRMask[shCount]); // 0000000B:CCCCCCCD
8164 emitcode ("mov", "c,acc.0"); // c = B
8166 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8168 AccAXRrl1 (x); // BCCCCCCC:D0000000
8177 #ifdef BETTER_LITERAL_SHIFT
8179 /*-----------------------------------------------------------------*/
8180 /* AccAXRsh - right shift a:x known count (0..7) */
8181 /*-----------------------------------------------------------------*/
8183 AccAXRsh (char *x, int shCount)
8191 AccAXRrl1 (x); // 0->a:x
8196 AccAXRrl1 (x); // 0->a:x
8199 AccAXRrl1 (x); // 0->a:x
8204 case 5: // AAAAABBB:CCCCCDDD = a:x
8206 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8208 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8210 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8212 emitcode ("anl", "a,#!constbyte",
8213 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8215 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8217 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8219 emitcode ("anl", "a,#!constbyte",
8220 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8222 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8224 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8226 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8229 case 6: // AABBBBBB:CCDDDDDD
8231 emitcode ("mov", "c,acc.7");
8232 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8234 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8236 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8238 emitcode ("anl", "a,#!constbyte",
8239 SRMask[shCount]); // 000000AA:BBBBBBCC
8242 case 7: // ABBBBBBB:CDDDDDDD
8244 emitcode ("mov", "c,acc.7"); // c = A
8246 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8248 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8250 emitcode ("anl", "a,#!constbyte",
8251 SRMask[shCount]); // 0000000A:BBBBBBBC
8260 #ifdef BETTER_LITERAL_SHIFT
8261 /*-----------------------------------------------------------------*/
8262 /* AccAXRshS - right shift signed a:x known count (0..7) */
8263 /*-----------------------------------------------------------------*/
8265 AccAXRshS (char *x, int shCount)
8273 emitcode ("mov", "c,acc.7");
8274 AccAXRrl1 (x); // s->a:x
8278 emitcode ("mov", "c,acc.7");
8279 AccAXRrl1 (x); // s->a:x
8281 emitcode ("mov", "c,acc.7");
8282 AccAXRrl1 (x); // s->a:x
8287 case 5: // AAAAABBB:CCCCCDDD = a:x
8289 tlbl = newiTempLabel (NULL);
8290 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8292 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8294 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8296 emitcode ("anl", "a,#!constbyte",
8297 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8299 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8301 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8303 emitcode ("anl", "a,#!constbyte",
8304 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8306 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8308 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8310 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8312 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8313 emitcode ("orl", "a,#!constbyte",
8314 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8316 emitcode ("", "!tlabeldef", tlbl->key + 100);
8317 break; // SSSSAAAA:BBBCCCCC
8319 case 6: // AABBBBBB:CCDDDDDD
8321 tlbl = newiTempLabel (NULL);
8322 emitcode ("mov", "c,acc.7");
8323 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8325 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8327 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8329 emitcode ("anl", "a,#!constbyte",
8330 SRMask[shCount]); // 000000AA:BBBBBBCC
8332 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8333 emitcode ("orl", "a,#!constbyte",
8334 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8336 emitcode ("", "!tlabeldef", tlbl->key + 100);
8338 case 7: // ABBBBBBB:CDDDDDDD
8340 tlbl = newiTempLabel (NULL);
8341 emitcode ("mov", "c,acc.7"); // c = A
8343 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8345 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8347 emitcode ("anl", "a,#!constbyte",
8348 SRMask[shCount]); // 0000000A:BBBBBBBC
8350 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8351 emitcode ("orl", "a,#!constbyte",
8352 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8354 emitcode ("", "!tlabeldef", tlbl->key + 100);
8362 #ifdef BETTER_LITERAL_SHIFT
8364 _loadLeftIntoAx(char **lsb,
8370 // Get the initial value from left into a pair of registers.
8371 // MSB must be in A, LSB can be any register.
8373 // If the result is held in registers, it is an optimization
8374 // if the LSB can be held in the register which will hold the,
8375 // result LSB since this saves us from having to copy it into
8376 // the result following AccAXLsh.
8378 // If the result is addressed indirectly, this is not a gain.
8379 if (AOP_NEEDSACC(result))
8383 _startLazyDPSEvaluation();
8384 if (AOP_TYPE(left) == AOP_DPTR2)
8387 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
8388 // get LSB in DP2_RESULT_REG.
8389 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
8390 assert(!strcmp(leftByte, DP2_RESULT_REG));
8394 // get LSB into DP2_RESULT_REG
8395 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
8396 if (strcmp(leftByte, DP2_RESULT_REG))
8399 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
8402 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
8403 assert(strcmp(leftByte, DP2_RESULT_REG));
8406 _endLazyDPSEvaluation();
8407 *lsb = DP2_RESULT_REG;
8411 if (sameRegs (AOP (result), AOP (left)) &&
8412 ((offl + MSB16) == offr))
8414 /* don't crash result[offr] */
8415 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
8416 emitcode ("xch", "a,%s",
8417 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
8421 movLeft2Result (left, offl, result, offr, 0);
8422 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
8424 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
8425 assert(strcmp(*lsb,"a"));
8430 _storeAxResults(char *lsb,
8434 _startLazyDPSEvaluation();
8435 if (AOP_NEEDSACC(result))
8437 /* We have to explicitly update the result LSB.
8439 emitcode("xch","a,%s", lsb);
8440 aopPut(AOP(result), "a", offr);
8441 emitcode("mov","a,%s", lsb);
8443 if (getDataSize (result) > 1)
8445 aopPut (AOP (result), "a", offr + MSB16);
8447 _endLazyDPSEvaluation();
8450 /*-----------------------------------------------------------------*/
8451 /* shiftL2Left2Result - shift left two bytes from left to result */
8452 /*-----------------------------------------------------------------*/
8454 shiftL2Left2Result (operand * left, int offl,
8455 operand * result, int offr, int shCount)
8459 _loadLeftIntoAx(&lsb, left, result, offl, offr);
8461 AccAXLsh (lsb, shCount);
8463 _storeAxResults(lsb, result, offr);
8467 #ifdef BETTER_LITERAL_SHIFT
8468 /*-----------------------------------------------------------------*/
8469 /* shiftR2Left2Result - shift right two bytes from left to result */
8470 /*-----------------------------------------------------------------*/
8472 shiftR2Left2Result (operand * left, int offl,
8473 operand * result, int offr,
8474 int shCount, int sign)
8478 _loadLeftIntoAx(&lsb, left, result, offl, offr);
8480 /* a:x >> shCount (x = lsb(result)) */
8483 AccAXRshS(lsb, shCount);
8487 AccAXRsh(lsb, shCount);
8490 _storeAxResults(lsb, result, offr);
8494 /*-----------------------------------------------------------------*/
8495 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8496 /*-----------------------------------------------------------------*/
8498 shiftLLeftOrResult (operand * left, int offl,
8499 operand * result, int offr, int shCount)
8501 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8502 /* shift left accumulator */
8504 /* or with result */
8505 emitcode ("orl", "a,%s",
8506 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8507 /* back to result */
8508 aopPut (AOP (result), "a", offr);
8513 /*-----------------------------------------------------------------*/
8514 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8515 /*-----------------------------------------------------------------*/
8517 shiftRLeftOrResult (operand * left, int offl,
8518 operand * result, int offr, int shCount)
8520 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8521 /* shift right accumulator */
8523 /* or with result */
8524 emitcode ("orl", "a,%s",
8525 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8526 /* back to result */
8527 aopPut (AOP (result), "a", offr);
8531 #ifdef BETTER_LITERAL_SHIFT
8532 /*-----------------------------------------------------------------*/
8533 /* genlshOne - left shift a one byte quantity by known count */
8534 /*-----------------------------------------------------------------*/
8536 genlshOne (operand * result, operand * left, int shCount)
8538 D (emitcode (";", "genlshOne "););
8539 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8543 #ifdef BETTER_LITERAL_SHIFT
8544 /*-----------------------------------------------------------------*/
8545 /* genlshTwo - left shift two bytes by known amount != 0 */
8546 /*-----------------------------------------------------------------*/
8548 genlshTwo (operand * result, operand * left, int shCount)
8552 D (emitcode (";", "genlshTwo "););
8554 size = getDataSize (result);
8556 /* if shCount >= 8 */
8561 _startLazyDPSEvaluation();
8567 _endLazyDPSEvaluation();
8568 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8569 aopPut (AOP (result), zero, LSB);
8573 movLeft2Result (left, LSB, result, MSB16, 0);
8574 aopPut (AOP (result), zero, LSB);
8575 _endLazyDPSEvaluation();
8580 aopPut (AOP (result), zero, LSB);
8581 _endLazyDPSEvaluation();
8585 /* 1 <= shCount <= 7 */
8590 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8594 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8602 /*-----------------------------------------------------------------*/
8603 /* shiftLLong - shift left one long from left to result */
8604 /* offl = LSB or MSB16 */
8605 /*-----------------------------------------------------------------*/
8607 shiftLLong (operand * left, operand * result, int offr)
8610 int size = AOP_SIZE (result);
8612 if (size >= LSB + offr)
8614 l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8616 emitcode ("add", "a,acc");
8617 if (sameRegs (AOP (left), AOP (result)) &&
8618 size >= MSB16 + offr && offr != LSB)
8619 emitcode ("xch", "a,%s",
8620 aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8622 aopPut (AOP (result), "a", LSB + offr);
8625 if (size >= MSB16 + offr)
8627 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8629 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8631 emitcode ("rlc", "a");
8632 if (sameRegs (AOP (left), AOP (result)) &&
8633 size >= MSB24 + offr && offr != LSB)
8634 emitcode ("xch", "a,%s",
8635 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8637 aopPut (AOP (result), "a", MSB16 + offr);
8640 if (size >= MSB24 + offr)
8642 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8644 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8646 emitcode ("rlc", "a");
8647 if (sameRegs (AOP (left), AOP (result)) &&
8648 size >= MSB32 + offr && offr != LSB)
8649 emitcode ("xch", "a,%s",
8650 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8652 aopPut (AOP (result), "a", MSB24 + offr);
8655 if (size > MSB32 + offr)
8657 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8659 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8661 emitcode ("rlc", "a");
8662 aopPut (AOP (result), "a", MSB32 + offr);
8665 aopPut (AOP (result), zero, LSB);
8671 /*-----------------------------------------------------------------*/
8672 /* genlshFour - shift four byte by a known amount != 0 */
8673 /*-----------------------------------------------------------------*/
8675 genlshFour (operand * result, operand * left, int shCount)
8679 D (emitcode (";", "genlshFour ");
8682 size = AOP_SIZE (result);
8684 /* if shifting more that 3 bytes */
8689 /* lowest order of left goes to the highest
8690 order of the destination */
8691 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8693 movLeft2Result (left, LSB, result, MSB32, 0);
8694 aopPut (AOP (result), zero, LSB);
8695 aopPut (AOP (result), zero, MSB16);
8696 aopPut (AOP (result), zero, MSB24);
8700 /* more than two bytes */
8701 else if (shCount >= 16)
8703 /* lower order two bytes goes to higher order two bytes */
8705 /* if some more remaining */
8707 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8710 movLeft2Result (left, MSB16, result, MSB32, 0);
8711 movLeft2Result (left, LSB, result, MSB24, 0);
8713 aopPut (AOP (result), zero, MSB16);
8714 aopPut (AOP (result), zero, LSB);
8718 /* if more than 1 byte */
8719 else if (shCount >= 8)
8721 /* lower order three bytes goes to higher order three bytes */
8726 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8728 movLeft2Result (left, LSB, result, MSB16, 0);
8734 movLeft2Result (left, MSB24, result, MSB32, 0);
8735 movLeft2Result (left, MSB16, result, MSB24, 0);
8736 movLeft2Result (left, LSB, result, MSB16, 0);
8737 aopPut (AOP (result), zero, LSB);
8739 else if (shCount == 1)
8740 shiftLLong (left, result, MSB16);
8743 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8744 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8745 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8746 aopPut (AOP (result), zero, LSB);
8751 /* 1 <= shCount <= 7 */
8752 else if (shCount <= 2)
8754 shiftLLong (left, result, LSB);
8756 shiftLLong (result, result, LSB);
8758 /* 3 <= shCount <= 7, optimize */
8761 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8762 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8763 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8768 #ifdef BETTER_LITERAL_SHIFT
8769 /*-----------------------------------------------------------------*/
8770 /* genLeftShiftLiteral - left shifting by known count */
8771 /*-----------------------------------------------------------------*/
8773 genLeftShiftLiteral (operand * left,
8778 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8781 size = getSize (operandType (result));
8783 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8785 /* We only handle certain easy cases so far. */
8787 && (shCount < (size * 8))
8791 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8795 freeAsmop (right, NULL, ic, TRUE);
8797 aopOp(left, ic, FALSE, FALSE);
8798 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8801 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8803 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8804 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8806 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8809 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8811 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8812 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8814 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8820 emitcode ("; shift left ", "result %d, left %d", size,
8824 /* I suppose that the left size >= result size */
8827 _startLazyDPSEvaluation();
8830 movLeft2Result (left, size, result, size, 0);
8832 _endLazyDPSEvaluation();
8834 else if (shCount >= (size * 8))
8836 _startLazyDPSEvaluation();
8839 aopPut (AOP (result), zero, size);
8841 _endLazyDPSEvaluation();
8848 genlshOne (result, left, shCount);
8852 genlshTwo (result, left, shCount);
8856 genlshFour (result, left, shCount);
8860 fprintf(stderr, "*** ack! mystery literal shift!\n");
8864 freeAsmop (left, NULL, ic, TRUE);
8865 freeAsmop (result, NULL, ic, TRUE);
8870 /*-----------------------------------------------------------------*/
8871 /* genLeftShift - generates code for left shifting */
8872 /*-----------------------------------------------------------------*/
8874 genLeftShift (iCode * ic)
8876 operand *left, *right, *result;
8879 symbol *tlbl, *tlbl1;
8881 D (emitcode (";", "genLeftShift "););
8883 right = IC_RIGHT (ic);
8884 left = IC_LEFT (ic);
8885 result = IC_RESULT (ic);
8887 aopOp (right, ic, FALSE, FALSE);
8890 #ifdef BETTER_LITERAL_SHIFT
8891 /* if the shift count is known then do it
8892 as efficiently as possible */
8893 if (AOP_TYPE (right) == AOP_LIT)
8895 if (genLeftShiftLiteral (left, right, result, ic))
8902 /* shift count is unknown then we have to form
8903 a loop get the loop count in B : Note: we take
8904 only the lower order byte since shifting
8905 more that 32 bits make no sense anyway, ( the
8906 largest size of an object can be only 32 bits ) */
8908 if (AOP_TYPE (right) == AOP_LIT)
8910 /* Really should be handled by genLeftShiftLiteral,
8911 * but since I'm too lazy to fix that today, at least we can make
8912 * some small improvement.
8914 emitcode("mov", "b,#!constbyte",
8915 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8919 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8920 emitcode ("inc", "b");
8922 freeAsmop (right, NULL, ic, TRUE);
8923 aopOp (left, ic, FALSE, FALSE);
8924 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8926 /* now move the left to the result if they are not the
8928 if (!sameRegs (AOP (left), AOP (result)) &&
8929 AOP_SIZE (result) > 1)
8932 size = AOP_SIZE (result);
8934 _startLazyDPSEvaluation ();
8937 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8938 if (*l == '@' && (IS_AOP_PREG (result)))
8941 emitcode ("mov", "a,%s", l);
8942 aopPut (AOP (result), "a", offset);
8945 aopPut (AOP (result), l, offset);
8948 _endLazyDPSEvaluation ();
8951 tlbl = newiTempLabel (NULL);
8952 size = AOP_SIZE (result);
8954 tlbl1 = newiTempLabel (NULL);
8956 /* if it is only one byte then */
8959 symbol *tlbl1 = newiTempLabel (NULL);
8961 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8962 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8963 emitcode ("", "!tlabeldef", tlbl->key + 100);
8964 emitcode ("add", "a,acc");
8965 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8966 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8967 aopPut (AOP (result), "a", 0);
8971 reAdjustPreg (AOP (result));
8973 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8974 emitcode ("", "!tlabeldef", tlbl->key + 100);
8975 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8976 emitcode ("add", "a,acc");
8977 aopPut (AOP (result), "a", offset++);
8978 _startLazyDPSEvaluation ();
8981 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8982 emitcode ("rlc", "a");
8983 aopPut (AOP (result), "a", offset++);
8985 _endLazyDPSEvaluation ();
8986 reAdjustPreg (AOP (result));
8988 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8989 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8991 freeAsmop (left, NULL, ic, TRUE);
8992 freeAsmop (result, NULL, ic, TRUE);
8995 #ifdef BETTER_LITERAL_SHIFT
8996 /*-----------------------------------------------------------------*/
8997 /* genrshOne - right shift a one byte quantity by known count */
8998 /*-----------------------------------------------------------------*/
9000 genrshOne (operand * result, operand * left,
9001 int shCount, int sign)
9003 D (emitcode (";", "genrshOne"););
9004 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9008 #ifdef BETTER_LITERAL_SHIFT
9009 /*-----------------------------------------------------------------*/
9010 /* genrshTwo - right shift two bytes by known amount != 0 */
9011 /*-----------------------------------------------------------------*/
9013 genrshTwo (operand * result, operand * left,
9014 int shCount, int sign)
9016 D (emitcode (";", "genrshTwo"););
9018 /* if shCount >= 8 */
9022 _startLazyDPSEvaluation();
9025 shiftR1Left2Result (left, MSB16, result, LSB,
9030 movLeft2Result (left, MSB16, result, LSB, sign);
9032 addSign (result, MSB16, sign);
9033 _endLazyDPSEvaluation();
9036 /* 1 <= shCount <= 7 */
9039 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9044 /*-----------------------------------------------------------------*/
9045 /* shiftRLong - shift right one long from left to result */
9046 /* offl = LSB or MSB16 */
9047 /*-----------------------------------------------------------------*/
9049 shiftRLong (operand * left, int offl,
9050 operand * result, int sign)
9052 int isSameRegs=sameRegs(AOP(left),AOP(result));
9054 if (isSameRegs && offl>1) {
9055 // we are in big trouble, but this shouldn't happen
9056 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9059 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
9064 emitcode ("rlc", "a");
9065 emitcode ("subb", "a,acc");
9066 emitcode ("xch", "a,%s",
9067 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
9069 aopPut (AOP(result), zero, MSB32);
9074 emitcode ("clr", "c");
9076 emitcode ("mov", "c,acc.7");
9079 emitcode ("rrc", "a");
9081 if (isSameRegs && offl==MSB16) {
9083 "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
9085 aopPut (AOP (result), "a", MSB32);
9086 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
9089 emitcode ("rrc", "a");
9090 if (isSameRegs && offl==1) {
9091 emitcode ("xch", "a,%s",
9092 aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
9094 aopPut (AOP (result), "a", MSB24);
9095 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
9097 emitcode ("rrc", "a");
9098 aopPut (AOP (result), "a", MSB16 - offl);
9102 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
9103 emitcode ("rrc", "a");
9104 aopPut (AOP (result), "a", LSB);
9108 /*-----------------------------------------------------------------*/
9109 /* genrshFour - shift four byte by a known amount != 0 */
9110 /*-----------------------------------------------------------------*/
9112 genrshFour (operand * result, operand * left,
9113 int shCount, int sign)
9115 D (emitcode (";", "genrshFour"););
9117 /* if shifting more that 3 bytes */
9121 _startLazyDPSEvaluation();
9123 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9125 movLeft2Result (left, MSB32, result, LSB, sign);
9126 addSign (result, MSB16, sign);
9127 _endLazyDPSEvaluation();
9129 else if (shCount >= 16)
9132 _startLazyDPSEvaluation();
9134 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9137 movLeft2Result (left, MSB24, result, LSB, 0);
9138 movLeft2Result (left, MSB32, result, MSB16, sign);
9140 addSign (result, MSB24, sign);
9141 _endLazyDPSEvaluation();
9143 else if (shCount >= 8)
9146 _startLazyDPSEvaluation();
9149 shiftRLong (left, MSB16, result, sign);
9151 else if (shCount == 0)
9153 movLeft2Result (left, MSB16, result, LSB, 0);
9154 movLeft2Result (left, MSB24, result, MSB16, 0);
9155 movLeft2Result (left, MSB32, result, MSB24, sign);
9156 addSign (result, MSB32, sign);
9160 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9161 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9162 /* the last shift is signed */
9163 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9164 addSign (result, MSB32, sign);
9166 _endLazyDPSEvaluation();
9170 /* 1 <= shCount <= 7 */
9173 shiftRLong (left, LSB, result, sign);
9175 shiftRLong (result, LSB, result, sign);
9179 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9180 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9181 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9186 #ifdef BETTER_LITERAL_SHIFT
9187 /*-----------------------------------------------------------------*/
9188 /* genRightShiftLiteral - right shifting by known count */
9189 /*-----------------------------------------------------------------*/
9191 genRightShiftLiteral (operand * left,
9197 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9200 size = getSize (operandType (result));
9202 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
9204 /* We only handle certain easy cases so far. */
9206 && (shCount < (size * 8))
9211 D(emitcode (";", "genRightShiftLiteral wimping out"););
9215 freeAsmop (right, NULL, ic, TRUE);
9217 aopOp (left, ic, FALSE, FALSE);
9218 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9221 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9225 /* test the LEFT size !!! */
9227 /* I suppose that the left size >= result size */
9230 size = getDataSize (result);
9231 _startLazyDPSEvaluation();
9234 movLeft2Result (left, size, result, size, 0);
9236 _endLazyDPSEvaluation();
9238 else if (shCount >= (size * 8))
9242 /* get sign in acc.7 */
9243 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
9245 addSign (result, LSB, sign);
9252 genrshOne (result, left, shCount, sign);
9256 genrshTwo (result, left, shCount, sign);
9260 genrshFour (result, left, shCount, sign);
9267 freeAsmop (left, NULL, ic, TRUE);
9268 freeAsmop (result, NULL, ic, TRUE);
9274 /*-----------------------------------------------------------------*/
9275 /* genSignedRightShift - right shift of signed number */
9276 /*-----------------------------------------------------------------*/
9278 genSignedRightShift (iCode * ic)
9280 operand *right, *left, *result;
9283 symbol *tlbl, *tlbl1;
9285 D (emitcode (";", "genSignedRightShift "););
9287 /* we do it the hard way put the shift count in b
9288 and loop thru preserving the sign */
9290 right = IC_RIGHT (ic);
9291 left = IC_LEFT (ic);
9292 result = IC_RESULT (ic);
9294 aopOp (right, ic, FALSE, FALSE);
9296 #ifdef BETTER_LITERAL_SHIFT
9297 if (AOP_TYPE (right) == AOP_LIT)
9299 if (genRightShiftLiteral (left, right, result, ic, 1))
9305 /* shift count is unknown then we have to form
9306 a loop get the loop count in B : Note: we take
9307 only the lower order byte since shifting
9308 more that 32 bits make no sense anyway, ( the
9309 largest size of an object can be only 32 bits ) */
9311 if (AOP_TYPE (right) == AOP_LIT)
9313 /* Really should be handled by genRightShiftLiteral,
9314 * but since I'm too lazy to fix that today, at least we can make
9315 * some small improvement.
9317 emitcode("mov", "b,#!constbyte",
9318 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9322 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9323 emitcode ("inc", "b");
9325 freeAsmop (right, NULL, ic, TRUE);
9326 aopOp (left, ic, FALSE, FALSE);
9327 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9329 /* now move the left to the result if they are not the
9331 if (!sameRegs (AOP (left), AOP (result)) &&
9332 AOP_SIZE (result) > 1)
9335 size = AOP_SIZE (result);
9337 _startLazyDPSEvaluation ();
9340 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9341 if (*l == '@' && IS_AOP_PREG (result))
9344 emitcode ("mov", "a,%s", l);
9345 aopPut (AOP (result), "a", offset);
9348 aopPut (AOP (result), l, offset);
9351 _endLazyDPSEvaluation ();
9354 /* mov the highest order bit to OVR */
9355 tlbl = newiTempLabel (NULL);
9356 tlbl1 = newiTempLabel (NULL);
9358 size = AOP_SIZE (result);
9360 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
9361 emitcode ("rlc", "a");
9362 emitcode ("mov", "ov,c");
9363 /* if it is only one byte then */
9366 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9367 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9368 emitcode ("", "!tlabeldef", tlbl->key + 100);
9369 emitcode ("mov", "c,ov");
9370 emitcode ("rrc", "a");
9371 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9372 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9373 aopPut (AOP (result), "a", 0);
9377 reAdjustPreg (AOP (result));
9378 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9379 emitcode ("", "!tlabeldef", tlbl->key + 100);
9380 emitcode ("mov", "c,ov");
9381 _startLazyDPSEvaluation ();
9384 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9385 emitcode ("rrc", "a");
9386 aopPut (AOP (result), "a", offset--);
9388 _endLazyDPSEvaluation ();
9389 reAdjustPreg (AOP (result));
9390 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9391 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9394 freeAsmop (left, NULL, ic, TRUE);
9395 freeAsmop (result, NULL, ic, TRUE);
9398 /*-----------------------------------------------------------------*/
9399 /* genRightShift - generate code for right shifting */
9400 /*-----------------------------------------------------------------*/
9402 genRightShift (iCode * ic)
9404 operand *right, *left, *result;
9408 symbol *tlbl, *tlbl1;
9410 D (emitcode (";", "genRightShift "););
9412 /* if signed then we do it the hard way preserve the
9413 sign bit moving it inwards */
9414 letype = getSpec (operandType (IC_LEFT (ic)));
9416 if (!SPEC_USIGN (letype))
9418 genSignedRightShift (ic);
9422 /* signed & unsigned types are treated the same : i.e. the
9423 signed is NOT propagated inwards : quoting from the
9424 ANSI - standard : "for E1 >> E2, is equivalent to division
9425 by 2**E2 if unsigned or if it has a non-negative value,
9426 otherwise the result is implementation defined ", MY definition
9427 is that the sign does not get propagated */
9429 right = IC_RIGHT (ic);
9430 left = IC_LEFT (ic);
9431 result = IC_RESULT (ic);
9433 aopOp (right, ic, FALSE, FALSE);
9435 #ifdef BETTER_LITERAL_SHIFT
9436 /* if the shift count is known then do it
9437 as efficiently as possible */
9438 if (AOP_TYPE (right) == AOP_LIT)
9440 if (genRightShiftLiteral (left, right, result, ic, 0))
9447 /* shift count is unknown then we have to form
9448 a loop get the loop count in B : Note: we take
9449 only the lower order byte since shifting
9450 more that 32 bits make no sense anyway, ( the
9451 largest size of an object can be only 32 bits ) */
9453 if (AOP_TYPE (right) == AOP_LIT)
9455 /* Really should be handled by genRightShiftLiteral,
9456 * but since I'm too lazy to fix that today, at least we can make
9457 * some small improvement.
9459 emitcode("mov", "b,#!constbyte",
9460 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9464 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9465 emitcode ("inc", "b");
9467 freeAsmop (right, NULL, ic, TRUE);
9468 aopOp (left, ic, FALSE, FALSE);
9469 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9471 /* now move the left to the result if they are not the
9473 if (!sameRegs (AOP (left), AOP (result)) &&
9474 AOP_SIZE (result) > 1)
9477 size = AOP_SIZE (result);
9479 _startLazyDPSEvaluation ();
9482 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9483 if (*l == '@' && IS_AOP_PREG (result))
9486 emitcode ("mov", "a,%s", l);
9487 aopPut (AOP (result), "a", offset);
9490 aopPut (AOP (result), l, offset);
9493 _endLazyDPSEvaluation ();
9496 tlbl = newiTempLabel (NULL);
9497 tlbl1 = newiTempLabel (NULL);
9498 size = AOP_SIZE (result);
9501 /* if it is only one byte then */
9504 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9505 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9506 emitcode ("", "!tlabeldef", tlbl->key + 100);
9508 emitcode ("rrc", "a");
9509 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9510 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9511 aopPut (AOP (result), "a", 0);
9515 reAdjustPreg (AOP (result));
9516 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9517 emitcode ("", "!tlabeldef", tlbl->key + 100);
9519 _startLazyDPSEvaluation ();
9522 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9523 emitcode ("rrc", "a");
9524 aopPut (AOP (result), "a", offset--);
9526 _endLazyDPSEvaluation ();
9527 reAdjustPreg (AOP (result));
9529 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9530 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9533 freeAsmop (left, NULL, ic, TRUE);
9534 freeAsmop (result, NULL, ic, TRUE);
9538 /*-----------------------------------------------------------------*/
9539 /* emitPtrByteGet - emits code to get a byte into A through a */
9540 /* pointer register (R0, R1, or DPTR). The */
9541 /* original value of A can be preserved in B. */
9542 /*-----------------------------------------------------------------*/
9544 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9551 emitcode ("mov", "b,a");
9552 emitcode ("mov", "a,@%s", rname);
9557 emitcode ("mov", "b,a");
9558 emitcode ("movx", "a,@%s", rname);
9563 emitcode ("mov", "b,a");
9564 emitcode ("movx", "a,@dptr");
9569 emitcode ("mov", "b,a");
9570 emitcode ("clr", "a");
9571 emitcode ("movc", "a,@a+dptr");
9577 emitcode ("push", "b");
9578 emitcode ("push", "acc");
9580 emitcode ("lcall", "__gptrget");
9582 emitcode ("pop", "b");
9587 /*-----------------------------------------------------------------*/
9588 /* emitPtrByteSet - emits code to set a byte from src through a */
9589 /* pointer register (R0, R1, or DPTR). */
9590 /*-----------------------------------------------------------------*/
9592 emitPtrByteSet (char *rname, int p_type, char *src)
9601 emitcode ("mov", "@%s,a", rname);
9604 emitcode ("mov", "@%s,%s", rname, src);
9609 emitcode ("movx", "@%s,a", rname);
9614 emitcode ("movx", "@dptr,a");
9619 emitcode ("lcall", "__gptrput");
9624 /*-----------------------------------------------------------------*/
9625 /* genUnpackBits - generates code for unpacking bits */
9626 /*-----------------------------------------------------------------*/
9628 genUnpackBits (operand * result, char *rname, int ptype)
9630 int offset = 0; /* result byte offset */
9631 int rsize; /* result size */
9632 int rlen = 0; /* remaining bitfield length */
9633 sym_link *etype; /* bitfield type information */
9634 int blen; /* bitfield length */
9635 int bstr; /* bitfield starting bit within byte */
9637 D(emitcode ("; genUnpackBits",""));
9639 etype = getSpec (operandType (result));
9640 rsize = getSize (operandType (result));
9641 blen = SPEC_BLEN (etype);
9642 bstr = SPEC_BSTR (etype);
9644 /* If the bitfield length is less than a byte */
9647 emitPtrByteGet (rname, ptype, FALSE);
9649 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9650 aopPut (AOP (result), "a", offset++);
9654 /* Bit field did not fit in a byte. Copy all
9655 but the partial byte at the end. */
9656 for (rlen=blen;rlen>=8;rlen-=8)
9658 emitPtrByteGet (rname, ptype, FALSE);
9659 aopPut (AOP (result), "a", offset++);
9661 emitcode ("inc", "%s", rname);
9664 /* Handle the partial byte at the end */
9667 emitPtrByteGet (rname, ptype, FALSE);
9668 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9669 aopPut (AOP (result), "a", offset++);
9677 aopPut (AOP (result), zero, offset++);
9682 /*-----------------------------------------------------------------*/
9683 /* genDataPointerGet - generates code when ptr offset is known */
9684 /*-----------------------------------------------------------------*/
9686 genDataPointerGet (operand * left,
9692 int size, offset = 0;
9693 aopOp (result, ic, TRUE, FALSE);
9695 /* get the string representation of the name */
9696 l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9697 size = AOP_SIZE (result);
9698 _startLazyDPSEvaluation ();
9703 SNPRINTF (buff, sizeof(buff),
9704 "(%s + %d)", l + 1, offset);
9708 SNPRINTF (buff, sizeof(buff),
9711 aopPut (AOP (result), buff, offset++);
9713 _endLazyDPSEvaluation ();
9715 freeAsmop (left, NULL, ic, TRUE);
9716 freeAsmop (result, NULL, ic, TRUE);
9719 /*-----------------------------------------------------------------*/
9720 /* genNearPointerGet - emitcode for near pointer fetch */
9721 /*-----------------------------------------------------------------*/
9723 genNearPointerGet (operand * left,
9731 sym_link *rtype, *retype, *letype;
9732 sym_link *ltype = operandType (left);
9735 rtype = operandType (result);
9736 retype = getSpec (rtype);
9737 letype = getSpec (ltype);
9739 aopOp (left, ic, FALSE, FALSE);
9741 /* if left is rematerialisable and
9742 result is not bitfield variable type and
9743 the left is pointer to data space i.e
9744 lower 128 bytes of space */
9745 if (AOP_TYPE (left) == AOP_IMMD &&
9746 !IS_BITFIELD (retype) &&
9747 !IS_BITFIELD (letype) &&
9748 DCL_TYPE (ltype) == POINTER)
9750 genDataPointerGet (left, result, ic);
9754 /* if the value is already in a pointer register
9755 then don't need anything more */
9756 if (!AOP_INPREG (AOP (left)))
9758 /* otherwise get a free pointer register */
9760 preg = getFreePtr (ic, &aop, FALSE);
9761 emitcode ("mov", "%s,%s",
9763 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9767 rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9769 freeAsmop (left, NULL, ic, TRUE);
9770 aopOp (result, ic, FALSE, FALSE);
9772 /* if bitfield then unpack the bits */
9773 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9774 genUnpackBits (result, rname, POINTER);
9777 /* we have can just get the values */
9778 int size = AOP_SIZE (result);
9783 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9786 emitcode ("mov", "a,@%s", rname);
9787 aopPut (AOP (result), "a", offset);
9791 SNPRINTF (buff, sizeof(buff), "@%s", rname);
9792 aopPut (AOP (result), buff, offset);
9797 emitcode ("inc", "%s", rname);
9802 /* now some housekeeping stuff */
9805 /* we had to allocate for this iCode */
9806 if (pi) { /* post increment present */
9807 aopPut(AOP ( left ),rname,0);
9809 freeAsmop (NULL, aop, ic, TRUE);
9813 /* we did not allocate which means left
9814 already in a pointer register, then
9815 if size > 0 && this could be used again
9816 we have to point it back to where it
9818 if (AOP_SIZE (result) > 1 &&
9819 !OP_SYMBOL (left)->remat &&
9820 (OP_SYMBOL (left)->liveTo > ic->seq ||
9824 int size = AOP_SIZE (result) - 1;
9826 emitcode ("dec", "%s", rname);
9831 freeAsmop (result, NULL, ic, TRUE);
9832 if (pi) pi->generated = 1;
9835 /*-----------------------------------------------------------------*/
9836 /* genPagedPointerGet - emitcode for paged pointer fetch */
9837 /*-----------------------------------------------------------------*/
9839 genPagedPointerGet (operand * left,
9847 sym_link *rtype, *retype, *letype;
9849 rtype = operandType (result);
9850 retype = getSpec (rtype);
9851 letype = getSpec (operandType (left));
9852 aopOp (left, ic, FALSE, FALSE);
9854 /* if the value is already in a pointer register
9855 then don't need anything more */
9856 if (!AOP_INPREG (AOP (left)))
9858 /* otherwise get a free pointer register */
9860 preg = getFreePtr (ic, &aop, FALSE);
9861 emitcode ("mov", "%s,%s",
9863 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9867 rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9869 freeAsmop (left, NULL, ic, TRUE);
9870 aopOp (result, ic, FALSE, FALSE);
9872 /* if bitfield then unpack the bits */
9873 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9874 genUnpackBits (result, rname, PPOINTER);
9877 /* we have can just get the values */
9878 int size = AOP_SIZE (result);
9884 emitcode ("movx", "a,@%s", rname);
9885 aopPut (AOP (result), "a", offset);
9890 emitcode ("inc", "%s", rname);
9894 /* now some housekeeping stuff */
9897 /* we had to allocate for this iCode */
9898 if (pi) aopPut ( AOP (left), rname, 0);
9899 freeAsmop (NULL, aop, ic, TRUE);
9903 /* we did not allocate which means left
9904 already in a pointer register, then
9905 if size > 0 && this could be used again
9906 we have to point it back to where it
9908 if (AOP_SIZE (result) > 1 &&
9909 !OP_SYMBOL (left)->remat &&
9910 (OP_SYMBOL (left)->liveTo > ic->seq ||
9914 int size = AOP_SIZE (result) - 1;
9916 emitcode ("dec", "%s", rname);
9921 freeAsmop (result, NULL, ic, TRUE);
9922 if (pi) pi->generated = 1;
9925 /*-----------------------------------------------------------------*/
9926 /* genFarPointerGet - gget value from far space */
9927 /*-----------------------------------------------------------------*/
9929 genFarPointerGet (operand * left,
9930 operand * result, iCode * ic, iCode *pi)
9932 int size, offset, dopi=1;
9933 sym_link *retype = getSpec (operandType (result));
9934 sym_link *letype = getSpec (operandType (left));
9935 D (emitcode (";", "genFarPointerGet"););
9937 aopOp (left, ic, FALSE, FALSE);
9939 /* if the operand is already in dptr
9940 then we do nothing else we move the value to dptr */
9941 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9943 /* if this is remateriazable */
9944 if (AOP_TYPE (left) == AOP_IMMD)
9946 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9950 /* we need to get it byte by byte */
9951 _startLazyDPSEvaluation ();
9952 if (AOP_TYPE (left) != AOP_DPTR)
9954 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9955 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9956 if (options.model == MODEL_FLAT24)
9957 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9961 /* We need to generate a load to DPTR indirect through DPTR. */
9962 D (emitcode (";", "genFarPointerGet -- indirection special case."););
9963 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9964 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9965 if (options.model == MODEL_FLAT24)
9966 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9967 emitcode ("pop", "dph");
9968 emitcode ("pop", "dpl");
9971 _endLazyDPSEvaluation ();
9974 /* so dptr know contains the address */
9975 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9977 /* if bit then unpack */
9978 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9979 if (AOP_INDPTRn(left)) {
9980 genSetDPTR(AOP(left)->aopu.dptr);
9982 genUnpackBits (result, "dptr", FPOINTER);
9983 if (AOP_INDPTRn(left)) {
9988 size = AOP_SIZE (result);
9991 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9993 genSetDPTR(AOP(left)->aopu.dptr);
9994 emitcode ("movx", "a,@dptr");
9995 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9996 emitcode ("inc", "dptr");
9998 aopPut (AOP (result), "a", offset++);
10001 _startLazyDPSEvaluation ();
10003 if (AOP_INDPTRn(left)) {
10004 genSetDPTR(AOP(left)->aopu.dptr);
10010 emitcode ("movx", "a,@dptr");
10011 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10012 emitcode ("inc", "dptr");
10014 aopPut (AOP (result), "a", offset++);
10016 _endLazyDPSEvaluation ();
10019 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10020 if (!AOP_INDPTRn(left)) {
10021 _startLazyDPSEvaluation ();
10022 aopPut ( AOP (left), "dpl", 0);
10023 aopPut ( AOP (left), "dph", 1);
10024 if (options.model == MODEL_FLAT24)
10025 aopPut ( AOP (left), "dpx", 2);
10026 _endLazyDPSEvaluation ();
10029 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
10030 AOP_SIZE(result) > 1 &&
10032 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
10034 size = AOP_SIZE (result) - 1;
10035 if (AOP_INDPTRn(left)) {
10036 genSetDPTR(AOP(left)->aopu.dptr);
10038 while (size--) emitcode ("lcall","__decdptr");
10039 if (AOP_INDPTRn(left)) {
10044 freeAsmop (left, NULL, ic, TRUE);
10045 freeAsmop (result, NULL, ic, TRUE);
10048 /*-----------------------------------------------------------------*/
10049 /* genCodePointerGet - get value from code space */
10050 /*-----------------------------------------------------------------*/
10052 genCodePointerGet (operand * left,
10053 operand * result, iCode * ic, iCode *pi)
10055 int size, offset, dopi=1;
10056 sym_link *retype = getSpec (operandType (result));
10058 aopOp (left, ic, FALSE, FALSE);
10060 /* if the operand is already in dptr
10061 then we do nothing else we move the value to dptr */
10062 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
10064 /* if this is remateriazable */
10065 if (AOP_TYPE (left) == AOP_IMMD)
10067 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10070 { /* we need to get it byte by byte */
10071 _startLazyDPSEvaluation ();
10072 if (AOP_TYPE (left) != AOP_DPTR)
10074 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10075 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10076 if (options.model == MODEL_FLAT24)
10077 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10081 /* We need to generate a load to DPTR indirect through DPTR. */
10082 D (emitcode (";", "gencodePointerGet -- indirection special case."););
10083 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
10084 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
10085 if (options.model == MODEL_FLAT24)
10086 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10087 emitcode ("pop", "dph");
10088 emitcode ("pop", "dpl");
10091 _endLazyDPSEvaluation ();
10094 /* so dptr know contains the address */
10095 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10097 /* if bit then unpack */
10098 if (IS_BITFIELD (retype)) {
10099 if (AOP_INDPTRn(left)) {
10100 genSetDPTR(AOP(left)->aopu.dptr);
10102 genUnpackBits (result, "dptr", CPOINTER);
10103 if (AOP_INDPTRn(left)) {
10108 size = AOP_SIZE (result);
10110 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10112 genSetDPTR(AOP(left)->aopu.dptr);
10113 emitcode ("clr", "a");
10114 emitcode ("movc", "a,@a+dptr");
10115 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10116 emitcode ("inc", "dptr");
10118 aopPut (AOP (result), "a", offset++);
10121 _startLazyDPSEvaluation ();
10124 if (AOP_INDPTRn(left)) {
10125 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");
10135 aopPut (AOP (result), "a", offset++);
10137 _endLazyDPSEvaluation ();
10140 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10141 if (!AOP_INDPTRn(left)) {
10142 _startLazyDPSEvaluation ();
10144 aopPut ( AOP (left), "dpl", 0);
10145 aopPut ( AOP (left), "dph", 1);
10146 if (options.model == MODEL_FLAT24)
10147 aopPut ( AOP (left), "dpx", 2);
10149 _endLazyDPSEvaluation ();
10152 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
10153 AOP_SIZE(result) > 1 &&
10154 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10156 size = AOP_SIZE (result) - 1;
10157 if (AOP_INDPTRn(left)) {
10158 genSetDPTR(AOP(left)->aopu.dptr);
10160 while (size--) emitcode ("lcall","__decdptr");
10161 if (AOP_INDPTRn(left)) {
10166 freeAsmop (left, NULL, ic, TRUE);
10167 freeAsmop (result, NULL, ic, TRUE);
10170 /*-----------------------------------------------------------------*/
10171 /* genGenPointerGet - gget value from generic pointer space */
10172 /*-----------------------------------------------------------------*/
10174 genGenPointerGet (operand * left,
10175 operand * result, iCode * ic, iCode * pi)
10178 sym_link *retype = getSpec (operandType (result));
10179 sym_link *letype = getSpec (operandType (left));
10181 D (emitcode (";", "genGenPointerGet "); );
10183 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
10185 /* if the operand is already in dptr
10186 then we do nothing else we move the value to dptr */
10187 if (AOP_TYPE (left) != AOP_STR)
10189 /* if this is rematerializable */
10190 if (AOP_TYPE (left) == AOP_IMMD)
10192 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10193 if (AOP(left)->aopu.aop_immd.from_cast_remat)
10195 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
10199 emitcode ("mov", "b,#%d", pointerCode (retype));
10203 { /* we need to get it byte by byte */
10204 _startLazyDPSEvaluation ();
10205 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
10206 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
10207 if (options.model == MODEL_FLAT24) {
10208 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10209 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
10211 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10213 _endLazyDPSEvaluation ();
10217 /* so dptr-b now contains the address */
10219 aopOp (result, ic, FALSE, TRUE);
10222 /* if bit then unpack */
10223 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10225 genUnpackBits (result, "dptr", GPOINTER);
10229 size = AOP_SIZE (result);
10236 // Get two bytes at a time, results in _AP & A.
10237 // dptr will be incremented ONCE by __gptrgetWord.
10239 // Note: any change here must be coordinated
10240 // with the implementation of __gptrgetWord
10241 // in device/lib/_gptrget.c
10242 emitcode ("lcall", "__gptrgetWord");
10243 aopPut (AOP (result), DP2_RESULT_REG, offset++);
10244 aopPut (AOP (result), "a", offset++);
10249 // Only one byte to get.
10250 emitcode ("lcall", "__gptrget");
10251 aopPut (AOP (result), "a", offset++);
10254 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
10256 emitcode ("inc", "dptr");
10261 if (pi && AOP_TYPE (left) != AOP_IMMD) {
10262 _startLazyDPSEvaluation ();
10264 aopPut ( AOP (left), "dpl", 0);
10265 aopPut ( AOP (left), "dph", 1);
10266 if (options.model == MODEL_FLAT24) {
10267 aopPut ( AOP (left), "dpx", 2);
10268 aopPut ( AOP (left), "b", 3);
10269 } else aopPut ( AOP (left), "b", 2);
10271 _endLazyDPSEvaluation ();
10274 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
10275 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10277 size = AOP_SIZE (result) - 1;
10278 while (size--) emitcode ("lcall","__decdptr");
10281 freeAsmop (left, NULL, ic, TRUE);
10282 freeAsmop (result, NULL, ic, TRUE);
10285 /*-----------------------------------------------------------------*/
10286 /* genPointerGet - generate code for pointer get */
10287 /*-----------------------------------------------------------------*/
10289 genPointerGet (iCode * ic, iCode *pi)
10291 operand *left, *result;
10292 sym_link *type, *etype;
10295 D (emitcode (";", "genPointerGet ");
10298 left = IC_LEFT (ic);
10299 result = IC_RESULT (ic);
10301 /* depending on the type of pointer we need to
10302 move it to the correct pointer register */
10303 type = operandType (left);
10304 etype = getSpec (type);
10305 /* if left is of type of pointer then it is simple */
10306 if (IS_PTR (type) && !IS_FUNC (type->next))
10307 p_type = DCL_TYPE (type);
10310 /* we have to go by the storage class */
10311 p_type = PTR_TYPE (SPEC_OCLS (etype));
10313 /* special case when cast remat */
10314 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10315 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10317 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10318 type = operandType (left);
10319 p_type = DCL_TYPE (type);
10321 /* now that we have the pointer type we assign
10322 the pointer values */
10328 genNearPointerGet (left, result, ic, pi);
10332 genPagedPointerGet (left, result, ic, pi);
10336 genFarPointerGet (left, result, ic, pi);
10340 genCodePointerGet (left, result, ic, pi);
10344 genGenPointerGet (left, result, ic, pi);
10350 /*-----------------------------------------------------------------*/
10351 /* genPackBits - generates code for packed bit storage */
10352 /*-----------------------------------------------------------------*/
10354 genPackBits (sym_link * etype,
10356 char *rname, int p_type)
10358 int offset = 0; /* source byte offset */
10359 int rlen = 0; /* remaining bitfield length */
10360 int blen; /* bitfield length */
10361 int bstr; /* bitfield starting bit within byte */
10362 int litval; /* source literal value (if AOP_LIT) */
10363 unsigned char mask; /* bitmask within current byte */
10365 D(emitcode ("; genPackBits",""));
10367 blen = SPEC_BLEN (etype);
10368 bstr = SPEC_BSTR (etype);
10370 /* If the bitfield length is less than a byte */
10373 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10374 (unsigned char) (0xFF >> (8 - bstr)));
10376 if (AOP_TYPE (right) == AOP_LIT)
10378 /* Case with a bitfield length <8 and literal source
10380 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10382 litval &= (~mask) & 0xff;
10383 emitPtrByteGet (rname, p_type, FALSE);
10384 if ((mask|litval)!=0xff)
10385 emitcode ("anl","a,#!constbyte", mask);
10387 emitcode ("orl","a,#!constbyte", litval);
10391 if ((blen==1) && (p_type!=GPOINTER))
10393 /* Case with a bitfield length == 1 and no generic pointer
10395 if (AOP_TYPE (right) == AOP_CRY)
10396 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10399 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10400 emitcode ("rrc","a");
10402 emitPtrByteGet (rname, p_type, FALSE);
10403 emitcode ("mov","acc.%d,c",bstr);
10407 /* Case with a bitfield length < 8 and arbitrary source
10409 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10410 /* shift and mask source value */
10412 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10414 /* transfer A to B and get next byte */
10415 emitPtrByteGet (rname, p_type, TRUE);
10417 emitcode ("anl", "a,#!constbyte", mask);
10418 emitcode ("orl", "a,b");
10419 if (p_type == GPOINTER)
10420 emitcode ("pop", "b");
10424 emitPtrByteSet (rname, p_type, "a");
10428 /* Bit length is greater than 7 bits. In this case, copy */
10429 /* all except the partial byte at the end */
10430 for (rlen=blen;rlen>=8;rlen-=8)
10432 emitPtrByteSet (rname, p_type,
10433 aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
10435 emitcode ("inc", "%s", rname);
10438 /* If there was a partial byte at the end */
10441 mask = (((unsigned char) -1 << rlen) & 0xff);
10443 if (AOP_TYPE (right) == AOP_LIT)
10445 /* Case with partial byte and literal source
10447 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10448 litval >>= (blen-rlen);
10449 litval &= (~mask) & 0xff;
10450 emitPtrByteGet (rname, p_type, FALSE);
10451 if ((mask|litval)!=0xff)
10452 emitcode ("anl","a,#!constbyte", mask);
10454 emitcode ("orl","a,#!constbyte", litval);
10458 /* Case with partial byte and arbitrary source
10460 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10461 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10463 /* transfer A to B and get next byte */
10464 emitPtrByteGet (rname, p_type, TRUE);
10466 emitcode ("anl", "a,#!constbyte", mask);
10467 emitcode ("orl", "a,b");
10468 if (p_type == GPOINTER)
10469 emitcode ("pop", "b");
10471 emitPtrByteSet (rname, p_type, "a");
10477 /*-----------------------------------------------------------------*/
10478 /* genDataPointerSet - remat pointer to data space */
10479 /*-----------------------------------------------------------------*/
10481 genDataPointerSet (operand * right,
10485 int size, offset = 0;
10486 char *l, buff[256];
10488 aopOp (right, ic, FALSE, FALSE);
10490 l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
10491 size = AOP_SIZE (right);
10496 SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
10500 SNPRINTF (buff, sizeof(buff), "%s", l + 1);
10503 emitcode ("mov", "%s,%s", buff,
10504 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10507 freeAsmop (right, NULL, ic, TRUE);
10508 freeAsmop (result, NULL, ic, TRUE);
10511 /*-----------------------------------------------------------------*/
10512 /* genNearPointerSet - emitcode for near pointer put */
10513 /*-----------------------------------------------------------------*/
10515 genNearPointerSet (operand * right,
10522 sym_link *retype, *letype;
10523 sym_link *ptype = operandType (result);
10525 retype = getSpec (operandType (right));
10526 letype = getSpec (ptype);
10528 aopOp (result, ic, FALSE, FALSE);
10530 /* if the result is rematerializable &
10531 in data space & not a bit variable */
10532 if (AOP_TYPE (result) == AOP_IMMD &&
10533 DCL_TYPE (ptype) == POINTER &&
10534 !IS_BITVAR (retype) &&
10535 !IS_BITVAR (letype))
10537 genDataPointerSet (right, result, ic);
10541 /* if the value is already in a pointer register
10542 then don't need anything more */
10543 if (!AOP_INPREG (AOP (result)))
10545 /* otherwise get a free pointer register */
10548 aop = newAsmop (0);
10549 preg = getFreePtr (ic, &aop, FALSE);
10550 emitcode ("mov", "%s,%s",
10552 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10553 rname = preg->name;
10556 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10558 aopOp (right, ic, FALSE, FALSE);
10560 /* if bitfield then unpack the bits */
10561 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10562 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10565 /* we have can just get the values */
10566 int size = AOP_SIZE (right);
10571 l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10575 emitcode ("mov", "@%s,a", rname);
10578 emitcode ("mov", "@%s,%s", rname, l);
10580 emitcode ("inc", "%s", rname);
10585 /* now some housekeeping stuff */
10588 /* we had to allocate for this iCode */
10589 if (pi) aopPut (AOP (result),rname,0);
10590 freeAsmop (NULL, aop, ic, TRUE);
10594 /* we did not allocate which means left
10595 already in a pointer register, then
10596 if size > 0 && this could be used again
10597 we have to point it back to where it
10599 if (AOP_SIZE (right) > 1 &&
10600 !OP_SYMBOL (result)->remat &&
10601 (OP_SYMBOL (result)->liveTo > ic->seq ||
10605 int size = AOP_SIZE (right) - 1;
10607 emitcode ("dec", "%s", rname);
10612 if (pi) pi->generated = 1;
10613 freeAsmop (result, NULL, ic, TRUE);
10614 freeAsmop (right, NULL, ic, TRUE);
10619 /*-----------------------------------------------------------------*/
10620 /* genPagedPointerSet - emitcode for Paged pointer put */
10621 /*-----------------------------------------------------------------*/
10623 genPagedPointerSet (operand * right,
10630 sym_link *retype, *letype;
10632 retype = getSpec (operandType (right));
10633 letype = getSpec (operandType (result));
10635 aopOp (result, ic, FALSE, FALSE);
10637 /* if the value is already in a pointer register
10638 then don't need anything more */
10639 if (!AOP_INPREG (AOP (result)))
10641 /* otherwise get a free pointer register */
10644 aop = newAsmop (0);
10645 preg = getFreePtr (ic, &aop, FALSE);
10646 emitcode ("mov", "%s,%s",
10648 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10649 rname = preg->name;
10652 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10654 aopOp (right, ic, FALSE, FALSE);
10656 /* if bitfield then unpack the bits */
10657 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10658 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10661 /* we have can just get the values */
10662 int size = AOP_SIZE (right);
10667 MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10669 emitcode ("movx", "@%s,a", rname);
10672 emitcode ("inc", "%s", rname);
10678 /* now some housekeeping stuff */
10681 if (pi) aopPut (AOP (result),rname,0);
10682 /* we had to allocate for this iCode */
10683 freeAsmop (NULL, aop, ic, TRUE);
10687 /* we did not allocate which means left
10688 already in a pointer register, then
10689 if size > 0 && this could be used again
10690 we have to point it back to where it
10692 if (AOP_SIZE (right) > 1 &&
10693 !OP_SYMBOL (result)->remat &&
10694 (OP_SYMBOL (result)->liveTo > ic->seq ||
10698 int size = AOP_SIZE (right) - 1;
10700 emitcode ("dec", "%s", rname);
10705 if (pi) pi->generated = 1;
10706 freeAsmop (result, NULL, ic, TRUE);
10707 freeAsmop (right, NULL, ic, TRUE);
10712 /*-----------------------------------------------------------------*/
10713 /* genFarPointerSet - set value from far space */
10714 /*-----------------------------------------------------------------*/
10716 genFarPointerSet (operand * right,
10717 operand * result, iCode * ic, iCode *pi)
10719 int size, offset, dopi=1;
10720 sym_link *retype = getSpec (operandType (right));
10721 sym_link *letype = getSpec (operandType (result));
10723 aopOp (result, ic, FALSE, FALSE);
10725 /* if the operand is already in dptr
10726 then we do nothing else we move the value to dptr */
10727 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10729 /* if this is remateriazable */
10730 if (AOP_TYPE (result) == AOP_IMMD)
10731 emitcode ("mov", "dptr,%s",
10732 aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10735 /* we need to get it byte by byte */
10736 _startLazyDPSEvaluation ();
10737 if (AOP_TYPE (result) != AOP_DPTR)
10739 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10740 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10741 if (options.model == MODEL_FLAT24)
10742 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10746 /* We need to generate a load to DPTR indirect through DPTR. */
10747 D (emitcode (";", "genFarPointerSet -- indirection special case."););
10749 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10750 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10751 if (options.model == MODEL_FLAT24)
10752 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10753 emitcode ("pop", "dph");
10754 emitcode ("pop", "dpl");
10757 _endLazyDPSEvaluation ();
10760 /* so dptr know contains the address */
10761 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10763 /* if bit then unpack */
10764 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10765 if (AOP_INDPTRn(result)) {
10766 genSetDPTR(AOP(result)->aopu.dptr);
10768 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10769 if (AOP_INDPTRn(result)) {
10773 size = AOP_SIZE (right);
10775 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10777 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10779 genSetDPTR(AOP(result)->aopu.dptr);
10780 emitcode ("movx", "@dptr,a");
10781 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10782 emitcode ("inc", "dptr");
10786 _startLazyDPSEvaluation ();
10788 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10790 if (AOP_INDPTRn(result)) {
10791 genSetDPTR(AOP(result)->aopu.dptr);
10797 emitcode ("movx", "@dptr,a");
10798 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10799 emitcode ("inc", "dptr");
10801 _endLazyDPSEvaluation ();
10805 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10806 if (!AOP_INDPTRn(result)) {
10807 _startLazyDPSEvaluation ();
10809 aopPut (AOP(result),"dpl",0);
10810 aopPut (AOP(result),"dph",1);
10811 if (options.model == MODEL_FLAT24)
10812 aopPut (AOP(result),"dpx",2);
10814 _endLazyDPSEvaluation ();
10817 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10818 AOP_SIZE(right) > 1 &&
10819 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10821 size = AOP_SIZE (right) - 1;
10822 if (AOP_INDPTRn(result)) {
10823 genSetDPTR(AOP(result)->aopu.dptr);
10825 while (size--) emitcode ("lcall","__decdptr");
10826 if (AOP_INDPTRn(result)) {
10830 freeAsmop (result, NULL, ic, TRUE);
10831 freeAsmop (right, NULL, ic, TRUE);
10834 /*-----------------------------------------------------------------*/
10835 /* genGenPointerSet - set value from generic pointer space */
10836 /*-----------------------------------------------------------------*/
10838 genGenPointerSet (operand * right,
10839 operand * result, iCode * ic, iCode *pi)
10842 sym_link *retype = getSpec (operandType (right));
10843 sym_link *letype = getSpec (operandType (result));
10845 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10847 /* if the operand is already in dptr
10848 then we do nothing else we move the value to dptr */
10849 if (AOP_TYPE (result) != AOP_STR)
10851 _startLazyDPSEvaluation ();
10852 /* if this is remateriazable */
10853 if (AOP_TYPE (result) == AOP_IMMD)
10855 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10856 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10858 MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10863 "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10867 { /* we need to get it byte by byte */
10868 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10869 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10870 if (options.model == MODEL_FLAT24) {
10871 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10872 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10874 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10877 _endLazyDPSEvaluation ();
10879 /* so dptr + b now contains the address */
10881 aopOp (right, ic, FALSE, TRUE);
10885 /* if bit then unpack */
10886 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10888 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10892 size = AOP_SIZE (right);
10895 _startLazyDPSEvaluation ();
10900 // Set two bytes at a time, passed in _AP & A.
10901 // dptr will be incremented ONCE by __gptrputWord.
10903 // Note: any change here must be coordinated
10904 // with the implementation of __gptrputWord
10905 // in device/lib/_gptrput.c
10906 emitcode("mov", "_ap, %s",
10907 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10908 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10912 emitcode ("lcall", "__gptrputWord");
10917 // Only one byte to put.
10918 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10922 emitcode ("lcall", "__gptrput");
10925 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10927 emitcode ("inc", "dptr");
10930 _endLazyDPSEvaluation ();
10933 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10934 _startLazyDPSEvaluation ();
10936 aopPut (AOP(result),"dpl",0);
10937 aopPut (AOP(result),"dph",1);
10938 if (options.model == MODEL_FLAT24) {
10939 aopPut (AOP(result),"dpx",2);
10940 aopPut (AOP(result),"b",3);
10942 aopPut (AOP(result),"b",2);
10944 _endLazyDPSEvaluation ();
10947 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10948 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10950 size = AOP_SIZE (right) - 1;
10951 while (size--) emitcode ("lcall","__decdptr");
10953 freeAsmop (result, NULL, ic, TRUE);
10954 freeAsmop (right, NULL, ic, TRUE);
10957 /*-----------------------------------------------------------------*/
10958 /* genPointerSet - stores the value into a pointer location */
10959 /*-----------------------------------------------------------------*/
10961 genPointerSet (iCode * ic, iCode *pi)
10963 operand *right, *result;
10964 sym_link *type, *etype;
10967 D (emitcode (";", "genPointerSet "););
10969 right = IC_RIGHT (ic);
10970 result = IC_RESULT (ic);
10972 /* depending on the type of pointer we need to
10973 move it to the correct pointer register */
10974 type = operandType (result);
10975 etype = getSpec (type);
10976 /* if left is of type of pointer then it is simple */
10977 if (IS_PTR (type) && !IS_FUNC (type->next))
10979 p_type = DCL_TYPE (type);
10983 /* we have to go by the storage class */
10984 p_type = PTR_TYPE (SPEC_OCLS (etype));
10986 /* special case when cast remat */
10987 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10988 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10989 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10990 type = operandType (result);
10991 p_type = DCL_TYPE (type);
10994 /* now that we have the pointer type we assign
10995 the pointer values */
11001 genNearPointerSet (right, result, ic, pi);
11005 genPagedPointerSet (right, result, ic, pi);
11009 genFarPointerSet (right, result, ic, pi);
11013 genGenPointerSet (right, result, ic, pi);
11017 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11018 "genPointerSet: illegal pointer type");
11023 /*-----------------------------------------------------------------*/
11024 /* genIfx - generate code for Ifx statement */
11025 /*-----------------------------------------------------------------*/
11027 genIfx (iCode * ic, iCode * popIc)
11029 operand *cond = IC_COND (ic);
11032 D (emitcode (";", "genIfx "););
11034 aopOp (cond, ic, FALSE, FALSE);
11036 /* get the value into acc */
11037 if (AOP_TYPE (cond) != AOP_CRY)
11046 /* the result is now in the accumulator */
11047 freeAsmop (cond, NULL, ic, TRUE);
11049 /* if there was something to be popped then do it */
11053 /* if the condition is a bit variable */
11054 if (isbit && IS_ITEMP (cond) &&
11057 genIfxJump (ic, SPIL_LOC (cond)->rname);
11059 else if (isbit && !IS_ITEMP (cond))
11061 genIfxJump (ic, OP_SYMBOL (cond)->rname);
11065 genIfxJump (ic, "a");
11071 /*-----------------------------------------------------------------*/
11072 /* genAddrOf - generates code for address of */
11073 /*-----------------------------------------------------------------*/
11075 genAddrOf (iCode * ic)
11077 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11080 D (emitcode (";", "genAddrOf ");
11083 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11085 /* if the operand is on the stack then we
11086 need to get the stack offset of this
11088 if (sym->onStack) {
11090 /* if 10 bit stack */
11091 if (options.stack10bit) {
11095 tsprintf(buff, sizeof(buff),
11096 "#!constbyte",(options.stack_loc >> 16) & 0xff);
11097 /* if it has an offset then we need to compute it */
11098 /* emitcode ("subb", "a,#!constbyte", */
11099 /* -((sym->stack < 0) ? */
11100 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11101 /* ((short) sym->stack)) & 0xff); */
11102 /* emitcode ("mov","b,a"); */
11103 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
11104 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11105 /* ((short) sym->stack)) >> 8) & 0xff); */
11107 emitcode ("mov", "a,_bpx");
11108 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
11109 ((char) (sym->stack - _G.nRegsSaved)) :
11110 ((char) sym->stack )) & 0xff);
11111 emitcode ("mov", "b,a");
11112 emitcode ("mov", "a,_bpx+1");
11114 offset = (((sym->stack < 0) ?
11115 ((short) (sym->stack - _G.nRegsSaved)) :
11116 ((short) sym->stack )) >> 8) & 0xff;
11118 emitcode ("addc","a,#!constbyte", offset);
11120 aopPut (AOP (IC_RESULT (ic)), "b", 0);
11121 aopPut (AOP (IC_RESULT (ic)), "a", 1);
11122 aopPut (AOP (IC_RESULT (ic)), buff, 2);
11124 /* we can just move _bp */
11125 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
11126 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
11127 aopPut (AOP (IC_RESULT (ic)), buff, 2);
11130 /* if it has an offset then we need to compute it */
11132 emitcode ("mov", "a,_bp");
11133 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
11134 aopPut (AOP (IC_RESULT (ic)), "a", 0);
11136 /* we can just move _bp */
11137 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
11139 /* fill the result with zero */
11140 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11143 if (options.stack10bit && size < (FPTRSIZE - 1)) {
11145 "*** warning: pointer to stack var truncated.\n");
11150 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
11156 /* object not on stack then we need the name */
11157 size = AOP_SIZE (IC_RESULT (ic));
11162 char s[SDCC_NAME_MAX];
11166 tsprintf(s, sizeof(s), "#!his",sym->rname);
11169 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
11172 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
11174 default: /* should not need this (just in case) */
11175 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
11182 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11185 aopPut (AOP (IC_RESULT (ic)), s, offset++);
11189 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11193 #if 0 // obsolete, and buggy for != xdata
11194 /*-----------------------------------------------------------------*/
11195 /* genArrayInit - generates code for address of */
11196 /*-----------------------------------------------------------------*/
11198 genArrayInit (iCode * ic)
11200 literalList *iLoop;
11202 int elementSize = 0, eIndex;
11203 unsigned val, lastVal;
11205 operand *left=IC_LEFT(ic);
11207 D (emitcode (";", "genArrayInit "););
11209 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
11211 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
11213 // Load immediate value into DPTR.
11214 emitcode("mov", "dptr, %s",
11215 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
11217 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
11220 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11221 "Unexpected operand to genArrayInit.\n");
11224 // a regression because of SDCCcse.c:1.52
11225 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
11226 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
11227 if (options.model == MODEL_FLAT24)
11228 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
11232 type = operandType(IC_LEFT(ic));
11234 if (type && type->next)
11236 elementSize = getSize(type->next);
11240 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11241 "can't determine element size in genArrayInit.\n");
11245 iLoop = IC_ARRAYILIST(ic);
11250 bool firstpass = TRUE;
11252 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
11253 iLoop->count, (int)iLoop->literalValue, elementSize);
11259 symbol *tlbl = NULL;
11261 count = ix > 256 ? 256 : ix;
11265 tlbl = newiTempLabel (NULL);
11266 if (firstpass || (count & 0xff))
11268 emitcode("mov", "b, #!constbyte", count & 0xff);
11271 emitcode ("", "!tlabeldef", tlbl->key + 100);
11276 for (eIndex = 0; eIndex < elementSize; eIndex++)
11278 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
11279 if (val != lastVal)
11281 emitcode("mov", "a, #!constbyte", val);
11285 emitcode("movx", "@dptr, a");
11286 emitcode("inc", "dptr");
11291 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
11297 iLoop = iLoop->next;
11300 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
11304 /*-----------------------------------------------------------------*/
11305 /* genFarFarAssign - assignment when both are in far space */
11306 /*-----------------------------------------------------------------*/
11308 genFarFarAssign (operand * result, operand * right, iCode * ic)
11310 int size = AOP_SIZE (right);
11312 symbol *rSym = NULL;
11316 /* quick & easy case. */
11317 D(emitcode(";","genFarFarAssign (1 byte case)"););
11318 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
11319 freeAsmop (right, NULL, ic, FALSE);
11320 /* now assign DPTR to result */
11322 aopOp(result, ic, FALSE, FALSE);
11324 aopPut(AOP(result), "a", 0);
11325 freeAsmop(result, NULL, ic, FALSE);
11329 /* See if we've got an underlying symbol to abuse. */
11330 if (IS_SYMOP(result) && OP_SYMBOL(result))
11332 if (IS_TRUE_SYMOP(result))
11334 rSym = OP_SYMBOL(result);
11336 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
11338 rSym = OP_SYMBOL(result)->usl.spillLoc;
11342 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
11344 /* We can use the '390 auto-toggle feature to good effect here. */
11346 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
11347 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11348 emitcode ("mov", "dptr,#%s", rSym->rname);
11349 /* DP2 = result, DP1 = right, DP1 is current. */
11352 emitcode("movx", "a,@dptr");
11353 emitcode("movx", "@dptr,a");
11356 emitcode("inc", "dptr");
11357 emitcode("inc", "dptr");
11360 emitcode("mov", "dps,#0");
11361 freeAsmop (right, NULL, ic, FALSE);
11363 some alternative code for processors without auto-toggle
11364 no time to test now, so later well put in...kpb
11365 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
11366 emitcode("mov", "dps,#1"); /* Select DPTR2. */
11367 emitcode ("mov", "dptr,#%s", rSym->rname);
11368 /* DP2 = result, DP1 = right, DP1 is current. */
11372 emitcode("movx", "a,@dptr");
11374 emitcode("inc", "dptr");
11375 emitcode("inc", "dps");
11376 emitcode("movx", "@dptr,a");
11378 emitcode("inc", "dptr");
11379 emitcode("inc", "dps");
11381 emitcode("mov", "dps,#0");
11382 freeAsmop (right, NULL, ic, FALSE);
11387 D (emitcode (";", "genFarFarAssign"););
11388 aopOp (result, ic, TRUE, TRUE);
11390 _startLazyDPSEvaluation ();
11394 aopPut (AOP (result),
11395 aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
11398 _endLazyDPSEvaluation ();
11399 freeAsmop (result, NULL, ic, FALSE);
11400 freeAsmop (right, NULL, ic, FALSE);
11404 /*-----------------------------------------------------------------*/
11405 /* genAssign - generate code for assignment */
11406 /*-----------------------------------------------------------------*/
11408 genAssign (iCode * ic)
11410 operand *result, *right;
11412 unsigned long lit = 0L;
11414 D (emitcode (";", "genAssign ");
11417 result = IC_RESULT (ic);
11418 right = IC_RIGHT (ic);
11420 /* if they are the same */
11421 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11424 aopOp (right, ic, FALSE, FALSE);
11426 emitcode (";", "genAssign: resultIsFar = %s",
11427 isOperandInFarSpace (result) ?
11430 /* special case both in far space */
11431 if ((AOP_TYPE (right) == AOP_DPTR ||
11432 AOP_TYPE (right) == AOP_DPTR2) &&
11433 /* IS_TRUE_SYMOP(result) && */
11434 isOperandInFarSpace (result))
11436 genFarFarAssign (result, right, ic);
11440 aopOp (result, ic, TRUE, FALSE);
11442 /* if they are the same registers */
11443 if (sameRegs (AOP (right), AOP (result)))
11446 /* if the result is a bit */
11447 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
11449 /* if the right size is a literal then
11450 we know what the value is */
11451 if (AOP_TYPE (right) == AOP_LIT)
11453 if (((int) operandLitValue (right)))
11454 aopPut (AOP (result), one, 0);
11456 aopPut (AOP (result), zero, 0);
11460 /* the right is also a bit variable */
11461 if (AOP_TYPE (right) == AOP_CRY)
11463 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11464 aopPut (AOP (result), "c", 0);
11468 /* we need to or */
11470 aopPut (AOP (result), "a", 0);
11474 /* bit variables done */
11476 size = AOP_SIZE (result);
11478 if (AOP_TYPE (right) == AOP_LIT)
11479 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11482 (AOP_TYPE (result) != AOP_REG) &&
11483 (AOP_TYPE (right) == AOP_LIT) &&
11484 !IS_FLOAT (operandType (right)))
11486 _startLazyDPSEvaluation ();
11487 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
11489 aopPut (AOP (result),
11490 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11495 /* And now fill the rest with zeros. */
11498 emitcode ("clr", "a");
11502 aopPut (AOP (result), "a", offset++);
11504 _endLazyDPSEvaluation ();
11508 _startLazyDPSEvaluation ();
11511 aopPut (AOP (result),
11512 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11516 _endLazyDPSEvaluation ();
11520 freeAsmop (right, NULL, ic, FALSE);
11521 freeAsmop (result, NULL, ic, TRUE);
11524 /*-----------------------------------------------------------------*/
11525 /* genJumpTab - generates code for jump table */
11526 /*-----------------------------------------------------------------*/
11528 genJumpTab (iCode * ic)
11533 D (emitcode (";", "genJumpTab ");
11536 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11537 /* get the condition into accumulator */
11538 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11540 /* multiply by four! */
11541 emitcode ("add", "a,acc");
11542 emitcode ("add", "a,acc");
11543 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11545 jtab = newiTempLabel (NULL);
11546 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11547 emitcode ("jmp", "@a+dptr");
11548 emitcode ("", "!tlabeldef", jtab->key + 100);
11549 /* now generate the jump labels */
11550 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11551 jtab = setNextItem (IC_JTLABELS (ic)))
11552 emitcode ("ljmp", "!tlabel", jtab->key + 100);
11556 /*-----------------------------------------------------------------*/
11557 /* genCast - gen code for casting */
11558 /*-----------------------------------------------------------------*/
11560 genCast (iCode * ic)
11562 operand *result = IC_RESULT (ic);
11563 sym_link *ctype = operandType (IC_LEFT (ic));
11564 sym_link *rtype = operandType (IC_RIGHT (ic));
11565 operand *right = IC_RIGHT (ic);
11568 D (emitcode (";", "genCast "););
11570 /* if they are equivalent then do nothing */
11571 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11574 aopOp (right, ic, FALSE, AOP_IS_STR (result));
11575 aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
11577 /* if the result is a bit */
11578 if (IS_BITVAR (OP_SYMBOL (result)->type)
11579 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11581 /* if the right size is a literal then
11582 we know what the value is */
11583 if (AOP_TYPE (right) == AOP_LIT)
11585 if (((int) operandLitValue (right)))
11586 aopPut (AOP (result), one, 0);
11588 aopPut (AOP (result), zero, 0);
11593 /* the right is also a bit variable */
11594 if (AOP_TYPE (right) == AOP_CRY)
11596 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11597 aopPut (AOP (result), "c", 0);
11601 /* we need to or */
11603 aopPut (AOP (result), "a", 0);
11607 /* if they are the same size : or less */
11608 if (AOP_SIZE (result) <= AOP_SIZE (right))
11611 /* if they are in the same place */
11612 if (sameRegs (AOP (right), AOP (result)))
11615 /* if they in different places then copy */
11616 size = AOP_SIZE (result);
11618 _startLazyDPSEvaluation ();
11621 aopPut (AOP (result),
11622 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11626 _endLazyDPSEvaluation ();
11631 /* if the result is of type pointer */
11632 if (IS_PTR (ctype))
11636 sym_link *type = operandType (right);
11638 /* pointer to generic pointer */
11639 if (IS_GENPTR (ctype))
11643 p_type = DCL_TYPE (type);
11647 #if OLD_CAST_BEHAVIOR
11648 /* KV: we are converting a non-pointer type to
11649 * a generic pointer. This (ifdef'd out) code
11650 * says that the resulting generic pointer
11651 * should have the same class as the storage
11652 * location of the non-pointer variable.
11654 * For example, converting an int (which happens
11655 * to be stored in DATA space) to a pointer results
11656 * in a DATA generic pointer; if the original int
11657 * in XDATA space, so will be the resulting pointer.
11659 * I don't like that behavior, and thus this change:
11660 * all such conversions will be forced to XDATA and
11661 * throw a warning. If you want some non-XDATA
11662 * type, or you want to suppress the warning, you
11663 * must go through an intermediate cast, like so:
11665 * char _generic *gp = (char _xdata *)(intVar);
11667 sym_link *etype = getSpec (type);
11669 /* we have to go by the storage class */
11670 if (SPEC_OCLS (etype) != generic)
11672 p_type = PTR_TYPE (SPEC_OCLS (etype));
11677 /* Converting unknown class (i.e. register variable)
11678 * to generic pointer. This is not good, but
11679 * we'll make a guess (and throw a warning).
11682 werror (W_INT_TO_GEN_PTR_CAST);
11686 /* the first two bytes are known */
11687 size = GPTRSIZE - 1;
11689 _startLazyDPSEvaluation ();
11692 aopPut (AOP (result),
11693 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11697 _endLazyDPSEvaluation ();
11699 /* the last byte depending on type */
11701 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11706 // pointerTypeToGPByte will have bitched.
11710 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11711 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11716 /* just copy the pointers */
11717 size = AOP_SIZE (result);
11719 _startLazyDPSEvaluation ();
11722 aopPut (AOP (result),
11723 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11727 _endLazyDPSEvaluation ();
11731 /* so we now know that the size of destination is greater
11732 than the size of the source */
11733 /* we move to result for the size of source */
11734 size = AOP_SIZE (right);
11736 _startLazyDPSEvaluation ();
11739 aopPut (AOP (result),
11740 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11744 _endLazyDPSEvaluation ();
11746 /* now depending on the sign of the source && destination */
11747 size = AOP_SIZE (result) - AOP_SIZE (right);
11748 /* if unsigned or not an integral type */
11749 /* also, if the source is a bit, we don't need to sign extend, because
11750 * it can't possibly have set the sign bit.
11752 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11756 aopPut (AOP (result), zero, offset++);
11761 /* we need to extend the sign :{ */
11762 MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11763 FALSE, FALSE, NULL));
11764 emitcode ("rlc", "a");
11765 emitcode ("subb", "a,acc");
11767 aopPut (AOP (result), "a", offset++);
11770 /* we are done hurray !!!! */
11773 freeAsmop (right, NULL, ic, TRUE);
11774 freeAsmop (result, NULL, ic, TRUE);
11778 /*-----------------------------------------------------------------*/
11779 /* genDjnz - generate decrement & jump if not zero instrucion */
11780 /*-----------------------------------------------------------------*/
11782 genDjnz (iCode * ic, iCode * ifx)
11784 symbol *lbl, *lbl1;
11788 /* if the if condition has a false label
11789 then we cannot save */
11790 if (IC_FALSE (ifx))
11793 /* if the minus is not of the form
11795 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11796 !IS_OP_LITERAL (IC_RIGHT (ic)))
11799 if (operandLitValue (IC_RIGHT (ic)) != 1)
11802 /* if the size of this greater than one then no
11804 if (getSize (operandType (IC_RESULT (ic))) > 1)
11807 /* otherwise we can save BIG */
11808 D(emitcode(";", "genDjnz"););
11810 lbl = newiTempLabel (NULL);
11811 lbl1 = newiTempLabel (NULL);
11813 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11815 if (AOP_NEEDSACC(IC_RESULT(ic)))
11817 /* If the result is accessed indirectly via
11818 * the accumulator, we must explicitly write
11819 * it back after the decrement.
11821 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11823 if (strcmp(rByte, "a"))
11825 /* Something is hopelessly wrong */
11826 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11827 __FILE__, __LINE__);
11828 /* We can just give up; the generated code will be inefficient,
11829 * but what the hey.
11831 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11834 emitcode ("dec", "%s", rByte);
11835 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11836 emitcode ("jnz", "!tlabel", lbl->key + 100);
11838 else if (IS_AOP_PREG (IC_RESULT (ic)))
11840 emitcode ("dec", "%s",
11841 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11842 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11843 emitcode ("jnz", "!tlabel", lbl->key + 100);
11847 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11850 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11851 emitcode ("", "!tlabeldef", lbl->key + 100);
11852 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11853 emitcode ("", "!tlabeldef", lbl1->key + 100);
11855 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11856 ifx->generated = 1;
11860 /*-----------------------------------------------------------------*/
11861 /* genReceive - generate code for a receive iCode */
11862 /*-----------------------------------------------------------------*/
11864 genReceive (iCode * ic)
11866 int size = getSize (operandType (IC_RESULT (ic)));
11870 D (emitcode (";", "genReceive "););
11872 if (ic->argreg == 1)
11874 /* first parameter */
11875 if (AOP_IS_STR(IC_RESULT(ic)))
11877 /* Nothing to do: it's already in the proper place. */
11884 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11885 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11886 IS_TRUE_SYMOP (IC_RESULT (ic)));
11889 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11892 /* Sanity checking... */
11893 if (AOP_USESDPTR(IC_RESULT(ic)))
11895 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11896 "genReceive got unexpected DPTR.");
11898 assignResultValue (IC_RESULT (ic));
11903 /* second receive onwards */
11904 /* this gets a little tricky since unused recevies will be
11905 eliminated, we have saved the reg in the type field . and
11906 we use that to figure out which register to use */
11907 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11908 rb1off = ic->argreg;
11911 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11914 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11917 /*-----------------------------------------------------------------*/
11918 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11919 /*-----------------------------------------------------------------*/
11920 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11922 operand *from , *to , *count;
11927 /* we know it has to be 3 parameters */
11928 assert (nparms == 3);
11930 rsave = newBitVect(16);
11931 /* save DPTR if it needs to be saved */
11932 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11933 if (bitVectBitValue(ic->rMask,i))
11934 rsave = bitVectSetBit(rsave,i);
11936 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11937 ds390_rUmaskForOp (IC_RESULT(ic))));
11944 aopOp (from, ic->next, FALSE, FALSE);
11946 /* get from into DPTR1 */
11947 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11948 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11949 if (options.model == MODEL_FLAT24) {
11950 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11953 freeAsmop (from, NULL, ic, FALSE);
11954 aopOp (to, ic, FALSE, FALSE);
11955 /* get "to" into DPTR */
11956 /* if the operand is already in dptr
11957 then we do nothing else we move the value to dptr */
11958 if (AOP_TYPE (to) != AOP_STR) {
11959 /* if already in DPTR then we need to push */
11960 if (AOP_TYPE(to) == AOP_DPTR) {
11961 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11962 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11963 if (options.model == MODEL_FLAT24)
11964 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11965 emitcode ("pop", "dph");
11966 emitcode ("pop", "dpl");
11968 _startLazyDPSEvaluation ();
11969 /* if this is remateriazable */
11970 if (AOP_TYPE (to) == AOP_IMMD) {
11971 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11972 } else { /* we need to get it byte by byte */
11973 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11974 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11975 if (options.model == MODEL_FLAT24) {
11976 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11979 _endLazyDPSEvaluation ();
11982 freeAsmop (to, NULL, ic, FALSE);
11983 _G.dptrInUse = _G.dptr1InUse = 1;
11984 aopOp (count, ic->next->next, FALSE,FALSE);
11985 lbl =newiTempLabel(NULL);
11987 /* now for the actual copy */
11988 if (AOP_TYPE(count) == AOP_LIT &&
11989 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11990 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11992 emitcode ("lcall","__bi_memcpyc2x_s");
11994 emitcode ("lcall","__bi_memcpyx2x_s");
11996 freeAsmop (count, NULL, ic, FALSE);
11998 symbol *lbl1 = newiTempLabel(NULL);
12000 emitcode (";"," Auto increment but no djnz");
12001 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12002 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12003 freeAsmop (count, NULL, ic, FALSE);
12004 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12005 emitcode ("","!tlabeldef",lbl->key+100);
12007 emitcode ("clr","a");
12008 emitcode ("movc", "a,@a+dptr");
12010 emitcode ("movx", "a,@dptr");
12011 emitcode ("movx", "@dptr,a");
12012 emitcode ("inc", "dptr");
12013 emitcode ("inc", "dptr");
12014 emitcode ("mov","a,b");
12015 emitcode ("orl","a,_ap");
12016 emitcode ("jz","!tlabel",lbl1->key+100);
12017 emitcode ("mov","a,_ap");
12018 emitcode ("add","a,#!constbyte",0xFF);
12019 emitcode ("mov","_ap,a");
12020 emitcode ("mov","a,b");
12021 emitcode ("addc","a,#!constbyte",0xFF);
12022 emitcode ("mov","b,a");
12023 emitcode ("sjmp","!tlabel",lbl->key+100);
12024 emitcode ("","!tlabeldef",lbl1->key+100);
12026 emitcode ("mov", "dps,#0");
12027 _G.dptrInUse = _G.dptr1InUse = 0;
12028 unsavermask(rsave);
12032 /*-----------------------------------------------------------------*/
12033 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
12034 /*-----------------------------------------------------------------*/
12035 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
12037 operand *from , *to , *count;
12042 /* we know it has to be 3 parameters */
12043 assert (nparms == 3);
12045 rsave = newBitVect(16);
12046 /* save DPTR if it needs to be saved */
12047 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12048 if (bitVectBitValue(ic->rMask,i))
12049 rsave = bitVectSetBit(rsave,i);
12051 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12052 ds390_rUmaskForOp (IC_RESULT(ic))));
12059 aopOp (from, ic->next, FALSE, FALSE);
12061 /* get from into DPTR1 */
12062 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12063 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12064 if (options.model == MODEL_FLAT24) {
12065 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12068 freeAsmop (from, NULL, ic, FALSE);
12069 aopOp (to, ic, FALSE, FALSE);
12070 /* get "to" into DPTR */
12071 /* if the operand is already in dptr
12072 then we do nothing else we move the value to dptr */
12073 if (AOP_TYPE (to) != AOP_STR) {
12074 /* if already in DPTR then we need to push */
12075 if (AOP_TYPE(to) == AOP_DPTR) {
12076 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12077 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12078 if (options.model == MODEL_FLAT24)
12079 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12080 emitcode ("pop", "dph");
12081 emitcode ("pop", "dpl");
12083 _startLazyDPSEvaluation ();
12084 /* if this is remateriazable */
12085 if (AOP_TYPE (to) == AOP_IMMD) {
12086 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12087 } else { /* we need to get it byte by byte */
12088 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12089 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12090 if (options.model == MODEL_FLAT24) {
12091 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12094 _endLazyDPSEvaluation ();
12097 freeAsmop (to, NULL, ic, FALSE);
12098 _G.dptrInUse = _G.dptr1InUse = 1;
12099 aopOp (count, ic->next->next, FALSE,FALSE);
12100 lbl =newiTempLabel(NULL);
12101 lbl2 =newiTempLabel(NULL);
12103 /* now for the actual compare */
12104 if (AOP_TYPE(count) == AOP_LIT &&
12105 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12106 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12108 emitcode("lcall","__bi_memcmpc2x_s");
12110 emitcode("lcall","__bi_memcmpx2x_s");
12111 freeAsmop (count, NULL, ic, FALSE);
12112 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12113 aopPut(AOP(IC_RESULT(ic)),"a",0);
12114 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12116 symbol *lbl1 = newiTempLabel(NULL);
12118 emitcode("push","ar0");
12119 emitcode (";"," Auto increment but no djnz");
12120 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12121 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12122 freeAsmop (count, NULL, ic, FALSE);
12123 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12124 emitcode ("","!tlabeldef",lbl->key+100);
12126 emitcode ("clr","a");
12127 emitcode ("movc", "a,@a+dptr");
12129 emitcode ("movx", "a,@dptr");
12130 emitcode ("mov","r0,a");
12131 emitcode ("movx", "a,@dptr");
12132 emitcode ("clr","c");
12133 emitcode ("subb","a,r0");
12134 emitcode ("jnz","!tlabel",lbl2->key+100);
12135 emitcode ("inc", "dptr");
12136 emitcode ("inc", "dptr");
12137 emitcode ("mov","a,b");
12138 emitcode ("orl","a,_ap");
12139 emitcode ("jz","!tlabel",lbl1->key+100);
12140 emitcode ("mov","a,_ap");
12141 emitcode ("add","a,#!constbyte",0xFF);
12142 emitcode ("mov","_ap,a");
12143 emitcode ("mov","a,b");
12144 emitcode ("addc","a,#!constbyte",0xFF);
12145 emitcode ("mov","b,a");
12146 emitcode ("sjmp","!tlabel",lbl->key+100);
12147 emitcode ("","!tlabeldef",lbl1->key+100);
12148 emitcode ("clr","a");
12149 emitcode ("","!tlabeldef",lbl2->key+100);
12150 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12151 aopPut(AOP(IC_RESULT(ic)),"a",0);
12152 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12153 emitcode("pop","ar0");
12154 emitcode ("mov", "dps,#0");
12156 _G.dptrInUse = _G.dptr1InUse = 0;
12157 unsavermask(rsave);
12161 /*-----------------------------------------------------------------*/
12162 /* genInp - gen code for __builtin_inp read data from a mem mapped */
12163 /* port, first parameter output area second parameter pointer to */
12164 /* port third parameter count */
12165 /*-----------------------------------------------------------------*/
12166 static void genInp( iCode *ic, int nparms, operand **parms)
12168 operand *from , *to , *count;
12173 /* we know it has to be 3 parameters */
12174 assert (nparms == 3);
12176 rsave = newBitVect(16);
12177 /* save DPTR if it needs to be saved */
12178 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12179 if (bitVectBitValue(ic->rMask,i))
12180 rsave = bitVectSetBit(rsave,i);
12182 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12183 ds390_rUmaskForOp (IC_RESULT(ic))));
12190 aopOp (from, ic->next, FALSE, FALSE);
12192 /* get from into DPTR1 */
12193 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12194 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12195 if (options.model == MODEL_FLAT24) {
12196 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12199 freeAsmop (from, NULL, ic, FALSE);
12200 aopOp (to, ic, FALSE, FALSE);
12201 /* get "to" into DPTR */
12202 /* if the operand is already in dptr
12203 then we do nothing else we move the value to dptr */
12204 if (AOP_TYPE (to) != AOP_STR) {
12205 /* if already in DPTR then we need to push */
12206 if (AOP_TYPE(to) == AOP_DPTR) {
12207 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12208 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12209 if (options.model == MODEL_FLAT24)
12210 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12211 emitcode ("pop", "dph");
12212 emitcode ("pop", "dpl");
12214 _startLazyDPSEvaluation ();
12215 /* if this is remateriazable */
12216 if (AOP_TYPE (to) == AOP_IMMD) {
12217 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12218 } else { /* we need to get it byte by byte */
12219 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12220 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12221 if (options.model == MODEL_FLAT24) {
12222 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12225 _endLazyDPSEvaluation ();
12228 freeAsmop (to, NULL, ic, FALSE);
12230 _G.dptrInUse = _G.dptr1InUse = 1;
12231 aopOp (count, ic->next->next, FALSE,FALSE);
12232 lbl =newiTempLabel(NULL);
12234 /* now for the actual copy */
12235 if (AOP_TYPE(count) == AOP_LIT &&
12236 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12237 emitcode (";","OH JOY auto increment with djnz (very fast)");
12238 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12239 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12240 freeAsmop (count, NULL, ic, FALSE);
12241 emitcode ("","!tlabeldef",lbl->key+100);
12242 emitcode ("movx", "a,@dptr"); /* read data from port */
12243 emitcode ("dec","dps"); /* switch to DPTR */
12244 emitcode ("movx", "@dptr,a"); /* save into location */
12245 emitcode ("inc", "dptr"); /* point to next area */
12246 emitcode ("inc","dps"); /* switch to DPTR2 */
12247 emitcode ("djnz","b,!tlabel",lbl->key+100);
12249 symbol *lbl1 = newiTempLabel(NULL);
12251 emitcode (";"," Auto increment but no djnz");
12252 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12253 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12254 freeAsmop (count, NULL, ic, FALSE);
12255 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12256 emitcode ("","!tlabeldef",lbl->key+100);
12257 emitcode ("movx", "a,@dptr");
12258 emitcode ("dec","dps"); /* switch to DPTR */
12259 emitcode ("movx", "@dptr,a");
12260 emitcode ("inc", "dptr");
12261 emitcode ("inc","dps"); /* switch to DPTR2 */
12262 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
12263 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
12264 emitcode ("mov","a,b");
12265 emitcode ("orl","a,_ap");
12266 emitcode ("jz","!tlabel",lbl1->key+100);
12267 emitcode ("mov","a,_ap");
12268 emitcode ("add","a,#!constbyte",0xFF);
12269 emitcode ("mov","_ap,a");
12270 emitcode ("mov","a,b");
12271 emitcode ("addc","a,#!constbyte",0xFF);
12272 emitcode ("mov","b,a");
12273 emitcode ("sjmp","!tlabel",lbl->key+100);
12274 emitcode ("","!tlabeldef",lbl1->key+100);
12276 emitcode ("mov", "dps,#0");
12277 _G.dptrInUse = _G.dptr1InUse = 0;
12278 unsavermask(rsave);
12282 /*-----------------------------------------------------------------*/
12283 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
12284 /* port, first parameter output area second parameter pointer to */
12285 /* port third parameter count */
12286 /*-----------------------------------------------------------------*/
12287 static void genOutp( iCode *ic, int nparms, operand **parms)
12289 operand *from , *to , *count;
12294 /* we know it has to be 3 parameters */
12295 assert (nparms == 3);
12297 rsave = newBitVect(16);
12298 /* save DPTR if it needs to be saved */
12299 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12300 if (bitVectBitValue(ic->rMask,i))
12301 rsave = bitVectSetBit(rsave,i);
12303 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12304 ds390_rUmaskForOp (IC_RESULT(ic))));
12311 aopOp (from, ic->next, FALSE, FALSE);
12313 /* get from into DPTR1 */
12314 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12315 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12316 if (options.model == MODEL_FLAT24) {
12317 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12320 freeAsmop (from, NULL, ic, FALSE);
12321 aopOp (to, ic, FALSE, FALSE);
12322 /* get "to" into DPTR */
12323 /* if the operand is already in dptr
12324 then we do nothing else we move the value to dptr */
12325 if (AOP_TYPE (to) != AOP_STR) {
12326 /* if already in DPTR then we need to push */
12327 if (AOP_TYPE(to) == AOP_DPTR) {
12328 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12329 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12330 if (options.model == MODEL_FLAT24)
12331 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12332 emitcode ("pop", "dph");
12333 emitcode ("pop", "dpl");
12335 _startLazyDPSEvaluation ();
12336 /* if this is remateriazable */
12337 if (AOP_TYPE (to) == AOP_IMMD) {
12338 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12339 } else { /* we need to get it byte by byte */
12340 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12341 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12342 if (options.model == MODEL_FLAT24) {
12343 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12346 _endLazyDPSEvaluation ();
12349 freeAsmop (to, NULL, ic, FALSE);
12351 _G.dptrInUse = _G.dptr1InUse = 1;
12352 aopOp (count, ic->next->next, FALSE,FALSE);
12353 lbl =newiTempLabel(NULL);
12355 /* now for the actual copy */
12356 if (AOP_TYPE(count) == AOP_LIT &&
12357 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12358 emitcode (";","OH JOY auto increment with djnz (very fast)");
12359 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12360 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12361 emitcode ("","!tlabeldef",lbl->key+100);
12362 emitcode ("movx", "a,@dptr"); /* read data from port */
12363 emitcode ("inc","dps"); /* switch to DPTR2 */
12364 emitcode ("movx", "@dptr,a"); /* save into location */
12365 emitcode ("inc", "dptr"); /* point to next area */
12366 emitcode ("dec","dps"); /* switch to DPTR */
12367 emitcode ("djnz","b,!tlabel",lbl->key+100);
12368 freeAsmop (count, NULL, ic, FALSE);
12370 symbol *lbl1 = newiTempLabel(NULL);
12372 emitcode (";"," Auto increment but no djnz");
12373 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12374 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12375 freeAsmop (count, NULL, ic, FALSE);
12376 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12377 emitcode ("","!tlabeldef",lbl->key+100);
12378 emitcode ("movx", "a,@dptr");
12379 emitcode ("inc", "dptr");
12380 emitcode ("inc","dps"); /* switch to DPTR2 */
12381 emitcode ("movx", "@dptr,a");
12382 emitcode ("dec","dps"); /* switch to DPTR */
12383 emitcode ("mov","a,b");
12384 emitcode ("orl","a,_ap");
12385 emitcode ("jz","!tlabel",lbl1->key+100);
12386 emitcode ("mov","a,_ap");
12387 emitcode ("add","a,#!constbyte",0xFF);
12388 emitcode ("mov","_ap,a");
12389 emitcode ("mov","a,b");
12390 emitcode ("addc","a,#!constbyte",0xFF);
12391 emitcode ("mov","b,a");
12392 emitcode ("sjmp","!tlabel",lbl->key+100);
12393 emitcode ("","!tlabeldef",lbl1->key+100);
12395 emitcode ("mov", "dps,#0");
12396 _G.dptrInUse = _G.dptr1InUse = 0;
12397 unsavermask(rsave);
12401 /*-----------------------------------------------------------------*/
12402 /* genSwapW - swap lower & high order bytes */
12403 /*-----------------------------------------------------------------*/
12404 static void genSwapW(iCode *ic, int nparms, operand **parms)
12408 assert (nparms==1);
12411 dest=IC_RESULT(ic);
12413 assert(getSize(operandType(src))==2);
12415 aopOp (src, ic, FALSE, FALSE);
12416 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
12418 MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
12420 freeAsmop (src, NULL, ic, FALSE);
12422 aopOp (dest,ic, FALSE, FALSE);
12423 aopPut(AOP(dest),"b",0);
12424 aopPut(AOP(dest),"a",1);
12425 freeAsmop (dest, NULL, ic, FALSE);
12428 /*-----------------------------------------------------------------*/
12429 /* genMemsetX - gencode for memSetX data */
12430 /*-----------------------------------------------------------------*/
12431 static void genMemsetX(iCode *ic, int nparms, operand **parms)
12433 operand *to , *val , *count;
12439 /* we know it has to be 3 parameters */
12440 assert (nparms == 3);
12446 /* save DPTR if it needs to be saved */
12447 rsave = newBitVect(16);
12448 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12449 if (bitVectBitValue(ic->rMask,i))
12450 rsave = bitVectSetBit(rsave,i);
12452 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12453 ds390_rUmaskForOp (IC_RESULT(ic))));
12456 aopOp (to, ic, FALSE, FALSE);
12457 /* get "to" into DPTR */
12458 /* if the operand is already in dptr
12459 then we do nothing else we move the value to dptr */
12460 if (AOP_TYPE (to) != AOP_STR) {
12461 /* if already in DPTR then we need to push */
12462 if (AOP_TYPE(to) == AOP_DPTR) {
12463 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12464 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12465 if (options.model == MODEL_FLAT24)
12466 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12467 emitcode ("pop", "dph");
12468 emitcode ("pop", "dpl");
12470 _startLazyDPSEvaluation ();
12471 /* if this is remateriazable */
12472 if (AOP_TYPE (to) == AOP_IMMD) {
12473 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12474 } else { /* we need to get it byte by byte */
12475 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12476 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12477 if (options.model == MODEL_FLAT24) {
12478 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12481 _endLazyDPSEvaluation ();
12484 freeAsmop (to, NULL, ic, FALSE);
12486 aopOp (val, ic->next->next, FALSE,FALSE);
12487 aopOp (count, ic->next->next, FALSE,FALSE);
12488 lbl =newiTempLabel(NULL);
12489 /* now for the actual copy */
12490 if (AOP_TYPE(count) == AOP_LIT &&
12491 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12492 l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
12493 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12495 emitcode ("","!tlabeldef",lbl->key+100);
12496 emitcode ("movx", "@dptr,a");
12497 emitcode ("inc", "dptr");
12498 emitcode ("djnz","b,!tlabel",lbl->key+100);
12500 symbol *lbl1 = newiTempLabel(NULL);
12502 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12503 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12504 emitcode ("","!tlabeldef",lbl->key+100);
12505 MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
12506 emitcode ("movx", "@dptr,a");
12507 emitcode ("inc", "dptr");
12508 emitcode ("mov","a,b");
12509 emitcode ("orl","a,_ap");
12510 emitcode ("jz","!tlabel",lbl1->key+100);
12511 emitcode ("mov","a,_ap");
12512 emitcode ("add","a,#!constbyte",0xFF);
12513 emitcode ("mov","_ap,a");
12514 emitcode ("mov","a,b");
12515 emitcode ("addc","a,#!constbyte",0xFF);
12516 emitcode ("mov","b,a");
12517 emitcode ("sjmp","!tlabel",lbl->key+100);
12518 emitcode ("","!tlabeldef",lbl1->key+100);
12520 freeAsmop (count, NULL, ic, FALSE);
12521 unsavermask(rsave);
12524 /*-----------------------------------------------------------------*/
12525 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12526 /*-----------------------------------------------------------------*/
12527 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12530 operand *pnum, *result;
12533 assert (nparms==1);
12534 /* save registers that need to be saved */
12535 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12536 ds390_rUmaskForOp (IC_RESULT(ic))));
12539 aopOp (pnum, ic, FALSE, FALSE);
12540 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12541 freeAsmop (pnum, NULL, ic, FALSE);
12542 emitcode ("lcall","NatLib_LoadPrimitive");
12543 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12544 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
12545 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12546 for (i = (size-1) ; i >= 0 ; i-- ) {
12547 emitcode ("push","a%s",javaRet[i]);
12549 for (i=0; i < size ; i++ ) {
12550 emitcode ("pop","a%s",
12551 aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12554 for (i = 0 ; i < size ; i++ ) {
12555 aopPut(AOP(result),javaRet[i],i);
12558 freeAsmop (result, NULL, ic, FALSE);
12559 unsavermask(rsave);
12562 /*-----------------------------------------------------------------*/
12563 /* genNatLibLoadPointer - calls TINI api function to load pointer */
12564 /*-----------------------------------------------------------------*/
12565 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12568 operand *pnum, *result;
12572 assert (nparms==1);
12573 /* save registers that need to be saved */
12574 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12575 ds390_rUmaskForOp (IC_RESULT(ic))));
12578 aopOp (pnum, ic, FALSE, FALSE);
12579 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12580 freeAsmop (pnum, NULL, ic, FALSE);
12581 emitcode ("lcall","NatLib_LoadPointer");
12582 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12583 if (AOP_TYPE(result)!=AOP_STR) {
12584 for (i = 0 ; i < size ; i++ ) {
12585 aopPut(AOP(result),fReturn[i],i);
12588 freeAsmop (result, NULL, ic, FALSE);
12589 unsavermask(rsave);
12592 /*-----------------------------------------------------------------*/
12593 /* genNatLibInstallStateBlock - */
12594 /*-----------------------------------------------------------------*/
12595 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
12596 operand **parms, const char *name)
12599 operand *psb, *handle;
12600 assert (nparms==2);
12602 /* save registers that need to be saved */
12603 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12604 ds390_rUmaskForOp (IC_RESULT(ic))));
12608 /* put pointer to state block into DPTR1 */
12609 aopOp (psb, ic, FALSE, FALSE);
12610 if (AOP_TYPE (psb) == AOP_IMMD) {
12611 emitcode ("mov","dps,#1");
12612 emitcode ("mov", "dptr,%s",
12613 aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12614 emitcode ("mov","dps,#0");
12616 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12617 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12618 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12620 freeAsmop (psb, NULL, ic, FALSE);
12622 /* put libraryID into DPTR */
12623 emitcode ("mov","dptr,#LibraryID");
12625 /* put handle into r3:r2 */
12626 aopOp (handle, ic, FALSE, FALSE);
12627 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12628 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12629 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12630 emitcode ("pop","ar3");
12631 emitcode ("pop","ar2");
12633 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12634 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12636 freeAsmop (psb, NULL, ic, FALSE);
12638 /* make the call */
12639 emitcode ("lcall","NatLib_Install%sStateBlock",name);
12641 /* put return value into place*/
12643 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12645 aopPut(AOP(IC_RESULT(ic)),"a",0);
12646 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12647 unsavermask(rsave);
12650 /*-----------------------------------------------------------------*/
12651 /* genNatLibRemoveStateBlock - */
12652 /*-----------------------------------------------------------------*/
12653 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12659 /* save registers that need to be saved */
12660 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12661 ds390_rUmaskForOp (IC_RESULT(ic))));
12663 /* put libraryID into DPTR */
12664 emitcode ("mov","dptr,#LibraryID");
12665 /* make the call */
12666 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12667 unsavermask(rsave);
12670 /*-----------------------------------------------------------------*/
12671 /* genNatLibGetStateBlock - */
12672 /*-----------------------------------------------------------------*/
12673 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12674 operand **parms,const char *name)
12677 symbol *lbl = newiTempLabel(NULL);
12680 /* save registers that need to be saved */
12681 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12682 ds390_rUmaskForOp (IC_RESULT(ic))));
12684 /* put libraryID into DPTR */
12685 emitcode ("mov","dptr,#LibraryID");
12686 /* make the call */
12687 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12688 emitcode ("jnz","!tlabel",lbl->key+100);
12690 /* put return value into place */
12691 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12692 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12693 emitcode ("push","ar3");
12694 emitcode ("push","ar2");
12695 emitcode ("pop","%s",
12696 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12697 emitcode ("pop","%s",
12698 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12700 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12701 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12703 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12704 emitcode ("","!tlabeldef",lbl->key+100);
12705 unsavermask(rsave);
12708 /*-----------------------------------------------------------------*/
12709 /* genMMMalloc - */
12710 /*-----------------------------------------------------------------*/
12711 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12712 int size, const char *name)
12717 symbol *lbl = newiTempLabel(NULL);
12719 assert (nparms == 1);
12720 /* save registers that need to be saved */
12721 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12722 ds390_rUmaskForOp (IC_RESULT(ic))));
12725 aopOp (bsize,ic,FALSE,FALSE);
12727 /* put the size in R4-R2 */
12728 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12729 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12730 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12732 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12733 emitcode("pop","ar4");
12735 emitcode("pop","ar3");
12736 emitcode("pop","ar2");
12738 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12739 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12741 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12744 freeAsmop (bsize, NULL, ic, FALSE);
12746 /* make the call */
12747 emitcode ("lcall","MM_%s",name);
12748 emitcode ("jz","!tlabel",lbl->key+100);
12749 emitcode ("mov","r2,#!constbyte",0xff);
12750 emitcode ("mov","r3,#!constbyte",0xff);
12751 emitcode ("","!tlabeldef",lbl->key+100);
12752 /* we don't care about the pointer : we just save the handle */
12753 rsym = OP_SYMBOL(IC_RESULT(ic));
12754 if (rsym->liveFrom != rsym->liveTo) {
12755 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12756 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12757 emitcode ("push","ar3");
12758 emitcode ("push","ar2");
12759 emitcode ("pop","%s",
12760 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12761 emitcode ("pop","%s",
12762 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12764 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12765 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12767 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12769 unsavermask(rsave);
12772 /*-----------------------------------------------------------------*/
12774 /*-----------------------------------------------------------------*/
12775 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12780 assert (nparms == 1);
12781 /* save registers that need to be saved */
12782 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12783 ds390_rUmaskForOp (IC_RESULT(ic))));
12786 aopOp (handle,ic,FALSE,FALSE);
12788 /* put the size in R4-R2 */
12789 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12790 emitcode("push","%s",
12791 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12792 emitcode("push","%s",
12793 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12794 emitcode("pop","ar3");
12795 emitcode("pop","ar2");
12797 emitcode ("mov","r2,%s",
12798 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12799 emitcode ("mov","r3,%s",
12800 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12802 freeAsmop (handle, NULL, ic, FALSE);
12804 /* make the call */
12805 emitcode ("lcall","MM_Deref");
12808 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12809 if (rsym->liveFrom != rsym->liveTo) {
12810 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12811 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12812 _startLazyDPSEvaluation ();
12814 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12815 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12816 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12818 _endLazyDPSEvaluation ();
12823 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12824 unsavermask(rsave);
12827 /*-----------------------------------------------------------------*/
12828 /* genMMUnrestrictedPersist - */
12829 /*-----------------------------------------------------------------*/
12830 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12835 assert (nparms == 1);
12836 /* save registers that need to be saved */
12837 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12838 ds390_rUmaskForOp (IC_RESULT(ic))));
12841 aopOp (handle,ic,FALSE,FALSE);
12843 /* put the size in R3-R2 */
12844 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12845 emitcode("push","%s",
12846 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12847 emitcode("push","%s",
12848 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12849 emitcode("pop","ar3");
12850 emitcode("pop","ar2");
12852 emitcode ("mov","r2,%s",
12853 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12854 emitcode ("mov","r3,%s",
12855 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12857 freeAsmop (handle, NULL, ic, FALSE);
12859 /* make the call */
12860 emitcode ("lcall","MM_UnrestrictedPersist");
12863 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12864 if (rsym->liveFrom != rsym->liveTo) {
12865 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12866 aopPut(AOP(IC_RESULT(ic)),"a",0);
12867 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12870 unsavermask(rsave);
12873 /*-----------------------------------------------------------------*/
12874 /* genSystemExecJavaProcess - */
12875 /*-----------------------------------------------------------------*/
12876 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12879 operand *handle, *pp;
12881 assert (nparms==2);
12882 /* save registers that need to be saved */
12883 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12884 ds390_rUmaskForOp (IC_RESULT(ic))));
12889 /* put the handle in R3-R2 */
12890 aopOp (handle,ic,FALSE,FALSE);
12891 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12892 emitcode("push","%s",
12893 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12894 emitcode("push","%s",
12895 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12896 emitcode("pop","ar3");
12897 emitcode("pop","ar2");
12899 emitcode ("mov","r2,%s",
12900 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12901 emitcode ("mov","r3,%s",
12902 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12904 freeAsmop (handle, NULL, ic, FALSE);
12906 /* put pointer in DPTR */
12907 aopOp (pp,ic,FALSE,FALSE);
12908 if (AOP_TYPE(pp) == AOP_IMMD) {
12909 emitcode ("mov", "dptr,%s",
12910 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12911 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12912 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12913 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12914 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12916 freeAsmop (handle, NULL, ic, FALSE);
12918 /* make the call */
12919 emitcode ("lcall","System_ExecJavaProcess");
12921 /* put result in place */
12923 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12924 if (rsym->liveFrom != rsym->liveTo) {
12925 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12926 aopPut(AOP(IC_RESULT(ic)),"a",0);
12927 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12931 unsavermask(rsave);
12934 /*-----------------------------------------------------------------*/
12935 /* genSystemRTCRegisters - */
12936 /*-----------------------------------------------------------------*/
12937 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12943 assert (nparms==1);
12944 /* save registers that need to be saved */
12945 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12946 ds390_rUmaskForOp (IC_RESULT(ic))));
12949 /* put pointer in DPTR */
12950 aopOp (pp,ic,FALSE,FALSE);
12951 if (AOP_TYPE (pp) == AOP_IMMD) {
12952 emitcode ("mov","dps,#1");
12953 emitcode ("mov", "dptr,%s",
12954 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12955 emitcode ("mov","dps,#0");
12957 emitcode ("mov","dpl1,%s",
12958 aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12959 emitcode ("mov","dph1,%s",
12960 aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12961 emitcode ("mov","dpx1,%s",
12962 aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12964 freeAsmop (pp, NULL, ic, FALSE);
12966 /* make the call */
12967 emitcode ("lcall","System_%sRTCRegisters",name);
12969 unsavermask(rsave);
12972 /*-----------------------------------------------------------------*/
12973 /* genSystemThreadSleep - */
12974 /*-----------------------------------------------------------------*/
12975 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12980 assert (nparms==1);
12981 /* save registers that need to be saved */
12982 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12983 ds390_rUmaskForOp (IC_RESULT(ic))));
12986 aopOp(to,ic,FALSE,FALSE);
12987 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12988 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12989 emitcode ("push","%s",
12990 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12991 emitcode ("push","%s",
12992 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12993 emitcode ("push","%s",
12994 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12995 emitcode ("push","%s",
12996 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12997 emitcode ("pop","ar3");
12998 emitcode ("pop","ar2");
12999 emitcode ("pop","ar1");
13000 emitcode ("pop","ar0");
13002 emitcode ("mov","r0,%s",
13003 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
13004 emitcode ("mov","r1,%s",
13005 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
13006 emitcode ("mov","r2,%s",
13007 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
13008 emitcode ("mov","r3,%s",
13009 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
13011 freeAsmop (to, NULL, ic, FALSE);
13013 /* suspend in acc */
13015 aopOp(s,ic,FALSE,FALSE);
13016 emitcode ("mov","a,%s",
13017 aopGet(AOP(s),0,FALSE,TRUE,NULL));
13018 freeAsmop (s, NULL, ic, FALSE);
13020 /* make the call */
13021 emitcode ("lcall","System_%s",name);
13023 unsavermask(rsave);
13026 /*-----------------------------------------------------------------*/
13027 /* genSystemThreadResume - */
13028 /*-----------------------------------------------------------------*/
13029 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
13034 assert (nparms==2);
13035 /* save registers that need to be saved */
13036 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13037 ds390_rUmaskForOp (IC_RESULT(ic))));
13043 aopOp(pid,ic,FALSE,FALSE);
13044 emitcode ("mov","r0,%s",
13045 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13046 freeAsmop (pid, NULL, ic, FALSE);
13049 aopOp(tid,ic,FALSE,FALSE);
13050 emitcode ("mov","a,%s",
13051 aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
13052 freeAsmop (tid, NULL, ic, FALSE);
13054 emitcode ("lcall","System_ThreadResume");
13056 /* put result into place */
13058 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13059 if (rsym->liveFrom != rsym->liveTo) {
13060 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13061 aopPut(AOP(IC_RESULT(ic)),"a",0);
13062 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13065 unsavermask(rsave);
13068 /*-----------------------------------------------------------------*/
13069 /* genSystemProcessResume - */
13070 /*-----------------------------------------------------------------*/
13071 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
13076 assert (nparms==1);
13077 /* save registers that need to be saved */
13078 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13079 ds390_rUmaskForOp (IC_RESULT(ic))));
13084 aopOp(pid,ic,FALSE,FALSE);
13085 emitcode ("mov","a,%s",
13086 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13087 freeAsmop (pid, NULL, ic, FALSE);
13089 emitcode ("lcall","System_ProcessResume");
13091 unsavermask(rsave);
13094 /*-----------------------------------------------------------------*/
13096 /*-----------------------------------------------------------------*/
13097 static void genSystem (iCode *ic,int nparms,char *name)
13099 assert(nparms == 0);
13101 emitcode ("lcall","System_%s",name);
13104 /*-----------------------------------------------------------------*/
13105 /* genSystemPoll - */
13106 /*-----------------------------------------------------------------*/
13107 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
13112 assert (nparms==1);
13113 /* save registers that need to be saved */
13114 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13115 ds390_rUmaskForOp (IC_RESULT(ic))));
13118 aopOp (fp,ic,FALSE,FALSE);
13119 if (AOP_TYPE (fp) == AOP_IMMD) {
13120 emitcode ("mov", "dptr,%s",
13121 aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
13122 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
13123 emitcode ("mov","dpl,%s",
13124 aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
13125 emitcode ("mov","dph,%s",
13126 aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
13127 emitcode ("mov","dpx,%s",
13128 aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
13130 freeAsmop (fp, NULL, ic, FALSE);
13132 emitcode ("lcall","System_%sPoll",name);
13134 /* put result into place */
13136 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13137 if (rsym->liveFrom != rsym->liveTo) {
13138 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13139 aopPut(AOP(IC_RESULT(ic)),"a",0);
13140 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13143 unsavermask(rsave);
13146 /*-----------------------------------------------------------------*/
13147 /* genSystemGetCurrentID - */
13148 /*-----------------------------------------------------------------*/
13149 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
13151 assert (nparms==0);
13153 emitcode ("lcall","System_GetCurrent%sId",name);
13154 /* put result into place */
13156 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13157 if (rsym->liveFrom != rsym->liveTo) {
13158 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13159 aopPut(AOP(IC_RESULT(ic)),"a",0);
13160 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13165 /*-----------------------------------------------------------------*/
13166 /* genDummyRead - generate code for dummy read of volatiles */
13167 /*-----------------------------------------------------------------*/
13169 genDummyRead (iCode * ic)
13174 D(emitcode("; genDummyRead",""));
13176 op = IC_RIGHT (ic);
13177 if (op && IS_SYMOP (op))
13179 aopOp (op, ic, FALSE, FALSE);
13181 /* if the result is a bit */
13182 if (AOP_TYPE (op) == AOP_CRY)
13183 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13186 /* bit variables done */
13188 size = AOP_SIZE (op);
13192 MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13197 freeAsmop (op, NULL, ic, TRUE);
13201 if (op && IS_SYMOP (op))
13203 aopOp (op, ic, FALSE, FALSE);
13205 /* if the result is a bit */
13206 if (AOP_TYPE (op) == AOP_CRY)
13207 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13210 /* bit variables done */
13212 size = AOP_SIZE (op);
13216 MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13221 freeAsmop (op, NULL, ic, TRUE);
13226 /*-----------------------------------------------------------------*/
13227 /* genCritical - generate code for start of a critical sequence */
13228 /*-----------------------------------------------------------------*/
13230 genCritical (iCode *ic)
13232 symbol *tlbl = newiTempLabel (NULL);
13234 D(emitcode("; genCritical",""));
13236 if (IC_RESULT (ic))
13237 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
13239 emitcode ("setb", "c");
13240 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
13241 emitcode ("clr", "c");
13242 emitcode ("", "%05d$:", (tlbl->key + 100));
13244 if (IC_RESULT (ic))
13245 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
13247 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
13249 if (IC_RESULT (ic))
13250 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13253 /*-----------------------------------------------------------------*/
13254 /* genEndCritical - generate code for end of a critical sequence */
13255 /*-----------------------------------------------------------------*/
13257 genEndCritical (iCode *ic)
13259 D(emitcode("; genEndCritical",""));
13263 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
13264 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
13266 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
13267 emitcode ("mov", "ea,c");
13271 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE));
13272 emitcode ("rrc", "a");
13273 emitcode ("mov", "ea,c");
13275 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
13279 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
13280 emitcode ("mov", "ea,c");
13286 /*-----------------------------------------------------------------*/
13287 /* genBuiltIn - calls the appropriate function to generating code */
13288 /* for a built in function */
13289 /*-----------------------------------------------------------------*/
13290 static void genBuiltIn (iCode *ic)
13292 operand *bi_parms[MAX_BUILTIN_ARGS];
13297 /* get all the arguments for a built in function */
13298 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
13300 /* which function is it */
13301 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
13302 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
13303 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
13304 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
13305 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
13306 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
13307 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
13308 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
13309 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
13310 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
13311 genMemsetX(bi_iCode,nbi_parms,bi_parms);
13312 } else if (strcmp(bif->name,"__builtin_inp")==0) {
13313 genInp(bi_iCode,nbi_parms,bi_parms);
13314 } else if (strcmp(bif->name,"__builtin_outp")==0) {
13315 genOutp(bi_iCode,nbi_parms,bi_parms);
13316 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
13317 genSwapW(bi_iCode,nbi_parms,bi_parms);
13318 /* JavaNative builtIns */
13319 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
13320 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
13321 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
13322 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
13323 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
13324 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
13325 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
13326 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
13327 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
13328 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13329 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
13330 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13331 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
13332 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
13333 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
13334 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
13335 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
13336 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13337 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
13338 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13339 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
13340 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
13341 } else if (strcmp(bif->name,"MM_Malloc")==0) {
13342 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
13343 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
13344 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
13345 } else if (strcmp(bif->name,"MM_Free")==0) {
13346 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
13347 } else if (strcmp(bif->name,"MM_Deref")==0) {
13348 genMMDeref(bi_iCode,nbi_parms,bi_parms);
13349 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
13350 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
13351 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
13352 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
13353 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
13354 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
13355 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
13356 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
13357 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
13358 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
13359 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
13360 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
13361 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
13362 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
13363 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
13364 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
13365 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13366 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13367 } else if (strcmp(bif->name,"System_SaveThread")==0) {
13368 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13369 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13370 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13371 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
13372 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
13373 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
13374 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
13375 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
13376 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
13377 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
13378 genSystem(bi_iCode,nbi_parms,"ProcessYield");
13379 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
13380 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
13381 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
13382 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
13383 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
13384 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
13385 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
13386 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
13387 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
13388 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
13390 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
13396 /*-----------------------------------------------------------------*/
13397 /* gen390Code - generate code for Dallas 390 based controllers */
13398 /*-----------------------------------------------------------------*/
13400 gen390Code (iCode * lic)
13405 lineHead = lineCurr = NULL;
13406 dptrn[1][0] = "dpl1";
13407 dptrn[1][1] = "dph1";
13408 dptrn[1][2] = "dpx1";
13410 if (options.model == MODEL_FLAT24) {
13411 fReturnSizeDS390 = 5;
13412 fReturn = fReturn24;
13414 fReturnSizeDS390 = 4;
13415 fReturn = fReturn16;
13416 options.stack10bit=0;
13419 /* print the allocation information */
13420 if (allocInfo && currFunc)
13421 printAllocInfo (currFunc, codeOutFile);
13423 /* if debug information required */
13424 if (options.debug && currFunc)
13426 debugFile->writeFunction (currFunc, lic);
13428 /* stack pointer name */
13429 if (options.useXstack)
13435 for (ic = lic; ic; ic = ic->next)
13437 _G.current_iCode = ic;
13439 if (ic->lineno && cln != ic->lineno)
13443 debugFile->writeCLine (ic);
13445 if (!options.noCcodeInAsm) {
13446 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
13447 printCLine(ic->filename, ic->lineno));
13451 if (options.iCodeInAsm) {
13452 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
13454 /* if the result is marked as
13455 spilt and rematerializable or code for
13456 this has already been generated then
13458 if (resultRemat (ic) || ic->generated)
13461 /* depending on the operation */
13481 /* IPOP happens only when trying to restore a
13482 spilt live range, if there is an ifx statement
13483 following this pop then the if statement might
13484 be using some of the registers being popped which
13485 would destory the contents of the register so
13486 we need to check for this condition and handle it */
13488 ic->next->op == IFX &&
13489 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
13490 genIfx (ic->next, ic);
13508 genEndFunction (ic);
13528 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
13545 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
13549 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
13556 /* note these two are xlated by algebraic equivalence
13557 during parsing SDCC.y */
13558 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13559 "got '>=' or '<=' shouldn't have come here");
13563 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
13575 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
13579 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
13583 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
13607 genRightShift (ic);
13610 case GET_VALUE_AT_ADDRESS:
13611 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13615 if (POINTER_SET (ic))
13616 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13642 if (ic->builtinSEND) genBuiltIn(ic);
13643 else addSet (&_G.sendSet, ic);
13646 case DUMMY_READ_VOLATILE:
13655 genEndCritical (ic);
13662 #if 0 // obsolete, and buggy for != xdata
13674 /* now we are ready to call the
13675 peep hole optimizer */
13676 if (!options.nopeep)
13677 peepHole (&lineHead);
13679 /* now do the actual printing */
13680 printLine (lineHead, codeOutFile);