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 unsigned fReturnSizeDS390 = 5; /* shared with ralloc.c */
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, 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),
167 tvsprintf (lb, sizeof(lb), fmt, ap);
171 while (isspace (*lbp))
178 lineCurr = (lineCurr ?
179 connectLine (lineCurr, newLineNode (lb)) :
180 (lineHead = newLineNode (lb)));
183 lineCurr->isInline = _G.inLine;
184 lineCurr->isDebug = _G.debugLine;
185 lineCurr->ic = _G.current_iCode;
186 lineCurr->aln = ds390newAsmLineNode(_currentDPS);
191 // Move the passed value into A unless it is already there.
196 if (strcmp(s,"a") && strcmp(s,"acc"))
198 emitcode("mov","a,%s",s);
203 // Move the passed value into B unless it is already there.
210 emitcode("mov","b,%s",s);
214 /*-----------------------------------------------------------------*/
215 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
216 /*-----------------------------------------------------------------*/
218 getFreePtr (iCode * ic, asmop ** aopp, bool result)
223 /* the logic: if r0 & r1 used in the instruction
224 then we are in trouble otherwise */
226 /* first check if r0 & r1 are used by this
227 instruction, in which case we are in trouble */
228 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
229 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
234 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
235 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
237 /* if no usage of r0 then return it */
240 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
241 (*aopp)->type = AOP_R0;
243 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
246 /* if no usage of r1 then return it */
249 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
250 (*aopp)->type = AOP_R1;
252 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
255 /* now we know they both have usage */
256 /* if r0 not used in this instruction */
259 /* push it if not already pushed */
262 emitcode ("push", "%s",
263 ds390_regWithIdx (R0_IDX)->dname);
267 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
268 (*aopp)->type = AOP_R0;
270 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
273 /* if r1 not used then */
277 /* push it if not already pushed */
280 emitcode ("push", "%s",
281 ds390_regWithIdx (R1_IDX)->dname);
285 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
286 (*aopp)->type = AOP_R1;
287 return ds390_regWithIdx (R1_IDX);
291 /* I said end of world but not quite end of world yet */
292 /* if this is a result then we can push it on the stack */
295 (*aopp)->type = AOP_STK;
299 /* other wise this is true end of the world */
300 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
301 "getFreePtr should never reach here");
304 return NULL; // notreached, but makes compiler happy.
307 /*-----------------------------------------------------------------*/
308 /* newAsmop - creates a new asmOp */
309 /*-----------------------------------------------------------------*/
311 newAsmop (short type)
315 aop = Safe_calloc (1, sizeof (asmop));
321 /*-----------------------------------------------------------------*/
322 /* genSetDPTR: generate code to select which DPTR is in use (zero */
323 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
324 /* alternate DPTR (DPL1/DPH1/DPX1). */
325 /*-----------------------------------------------------------------*/
330 /* If we are doing lazy evaluation, simply note the desired
331 * change, but don't emit any code yet.
341 emitcode ("mov", "dps,#0");
346 emitcode ("mov", "dps,#1");
350 /*-----------------------------------------------------------------*/
351 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
353 /* Any code that operates on DPTR (NB: not on the individual */
354 /* components, like DPH) *must* call _flushLazyDPS() before using */
355 /* DPTR within a lazy DPS evaluation block. */
357 /* Note that aopPut and aopGet already contain the proper calls to */
358 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
359 /* DPS evaluation block. */
361 /* Also, _flushLazyDPS must be called before any flow control */
362 /* operations that could potentially branch out of the block. */
364 /* Lazy DPS evaluation is simply an optimization (though an */
365 /* important one), so if in doubt, leave it out. */
366 /*-----------------------------------------------------------------*/
368 _startLazyDPSEvaluation (void)
372 #ifdef BETTER_LITERAL_SHIFT
379 /*-----------------------------------------------------------------*/
380 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
381 /* desired one. Call before using DPTR within a lazy DPS evaluation */
383 /*-----------------------------------------------------------------*/
393 if (_desiredDPS != _currentDPS)
397 emitcode ("inc", "dps");
401 emitcode ("dec", "dps");
403 _currentDPS = _desiredDPS;
407 /*-----------------------------------------------------------------*/
408 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
410 /* Forces us back to the safe state (standard DPTR selected). */
411 /*-----------------------------------------------------------------*/
413 _endLazyDPSEvaluation (void)
415 #ifdef BETTER_LITERAL_SHIFT
434 /*-----------------------------------------------------------------*/
435 /* pointerCode - returns the code for a pointer type */
436 /*-----------------------------------------------------------------*/
438 pointerCode (sym_link * etype)
441 return PTR_TYPE (SPEC_OCLS (etype));
445 /*-----------------------------------------------------------------*/
446 /* leftRightUseAcc - returns size of accumulator use by operands */
447 /*-----------------------------------------------------------------*/
449 leftRightUseAcc(iCode *ic)
458 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
459 "null iCode pointer");
466 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
469 size = getSize (OP_SYMBOL (op)->type);
474 else if (ic->op == JUMPTABLE)
477 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
480 size = getSize (OP_SYMBOL (op)->type);
488 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
491 size = getSize (OP_SYMBOL (op)->type);
496 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
499 size = getSize (OP_SYMBOL (op)->type);
511 /*-----------------------------------------------------------------*/
512 /* aopForSym - for a true symbol */
513 /*-----------------------------------------------------------------*/
515 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
518 memmap *space = SPEC_OCLS (sym->etype);
519 int accuse = leftRightUseAcc (ic);
521 /* if already has one */
524 if ((sym->aop->type == AOP_DPTR && useDP2)
525 || (sym->aop->type == AOP_DPTR2 && !useDP2))
531 /* assign depending on the storage class */
532 /* if it is on the stack or indirectly addressable */
533 /* space we need to assign either r0 or r1 to it */
534 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
536 sym->aop = aop = newAsmop (0);
537 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
538 aop->size = getSize (sym->type);
540 /* now assign the address of the variable to
541 the pointer register */
542 if (aop->type != AOP_STK)
547 if (_G.accInUse || accuse)
548 emitcode ("push", "acc");
550 if (_G.bInUse || (accuse>1))
551 emitcode ("push", "b");
553 emitcode ("mov", "a,_bp");
554 emitcode ("add", "a,#!constbyte",
556 ((char) (sym->stack - _G.nRegsSaved)) :
557 ((char) sym->stack)) & 0xff);
558 emitcode ("mov", "%s,a",
559 aop->aopu.aop_ptr->name);
561 if (_G.bInUse || (accuse>1))
562 emitcode ("pop", "b");
564 if (_G.accInUse || accuse)
565 emitcode ("pop", "acc");
568 emitcode ("mov", "%s,#%s",
569 aop->aopu.aop_ptr->name,
571 aop->paged = space->paged;
574 aop->aopu.aop_stk = sym->stack;
578 if (sym->onStack && options.stack10bit)
580 short stack_val = -((sym->stack < 0) ?
581 ((short) (sym->stack - _G.nRegsSaved)) :
582 ((short) sym->stack)) ;
583 if (useDP2 && _G.dptr1InUse) {
584 emitcode ("push","dpl1");
585 emitcode ("push","dph1");
586 emitcode ("push","dpx1");
587 } else if (_G.dptrInUse ) {
588 emitcode ("push","dpl");
589 emitcode ("push","dph");
590 emitcode ("push","dpx");
592 /* It's on the 10 bit stack, which is located in
595 if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
597 if (options.model == MODEL_FLAT24)
599 emitcode ("mov", "dpx1,#!constbyte",
600 (options.stack_loc >> 16) & 0xff);
602 emitcode ("mov", "dph1,_bpx+1");
604 emitcode ("mov", "dpl1,_bpx");
605 emitcode ("mov","dps,#1");
607 if (options.model == MODEL_FLAT24)
609 emitcode ("mov", "dpx,#!constbyte",
610 (options.stack_loc >> 16) & 0xff);
612 emitcode ("mov", "dph,_bpx+1");
613 emitcode ("mov", "dpl,_bpx");
615 stack_val = -stack_val;
616 while (stack_val--) {
617 emitcode ("inc","dptr");
620 emitcode("mov","dps,#0");
623 if (_G.accInUse || accuse)
624 emitcode ("push", "acc");
626 if (_G.bInUse || (accuse>1))
627 emitcode ("push", "b");
629 emitcode ("mov", "a,_bpx");
630 emitcode ("clr","c");
631 emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
632 emitcode ("mov","b,a");
633 emitcode ("mov","a,_bpx+1");
634 emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
636 if (options.model == MODEL_FLAT24)
638 emitcode ("mov", "dpx1,#!constbyte",
639 (options.stack_loc >> 16) & 0xff);
641 emitcode ("mov", "dph1,a");
642 emitcode ("mov", "dpl1,b");
644 if (options.model == MODEL_FLAT24)
646 emitcode ("mov", "dpx,#!constbyte",
647 (options.stack_loc >> 16) & 0xff);
649 emitcode ("mov", "dph,a");
650 emitcode ("mov", "dpl,b");
653 if (_G.bInUse || (accuse>1))
654 emitcode ("pop", "b");
656 if (_G.accInUse || accuse)
657 emitcode ("pop", "acc");
659 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
660 aop->size = getSize (sym->type);
664 /* if in bit space */
665 if (IN_BITSPACE (space))
667 sym->aop = aop = newAsmop (AOP_CRY);
668 aop->aopu.aop_dir = sym->rname;
669 aop->size = getSize (sym->type);
672 /* if it is in direct space */
673 if (IN_DIRSPACE (space))
675 sym->aop = aop = newAsmop (AOP_DIR);
676 aop->aopu.aop_dir = sym->rname;
677 aop->size = getSize (sym->type);
681 /* special case for a function */
682 if (IS_FUNC (sym->type) && !(sym->isitmp))
684 sym->aop = aop = newAsmop (AOP_IMMD);
685 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
686 aop->size = FPTRSIZE;
690 /* only remaining is far space */
691 /* in which case DPTR gets the address */
692 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
697 emitcode ("mov", "dptr,#%s", sym->rname);
702 emitcode ("mov", "dptr,#%s", sym->rname);
704 aop->size = getSize (sym->type);
706 /* if it is in code space */
707 if (IN_CODESPACE (space))
713 /*-----------------------------------------------------------------*/
714 /* aopForRemat - rematerialzes an object */
715 /*-----------------------------------------------------------------*/
717 aopForRemat (symbol * sym)
719 iCode *ic = sym->rematiCode;
720 asmop *aop = newAsmop (AOP_IMMD);
727 val += (int) operandLitValue (IC_RIGHT (ic));
728 else if (ic->op == '-')
729 val -= (int) operandLitValue (IC_RIGHT (ic));
730 else if (IS_CAST_ICODE(ic)) {
731 sym_link *from_type = operandType(IC_RIGHT(ic));
732 aop->aopu.aop_immd.from_cast_remat = 1;
733 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
734 ptr_type = DCL_TYPE(from_type);
735 if (ptr_type == IPOINTER) {
742 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
747 SNPRINTF (buffer, sizeof(buffer),
749 OP_SYMBOL (IC_LEFT (ic))->rname,
750 val >= 0 ? '+' : '-',
751 abs (val) & 0xffffff);
755 if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
757 SNPRINTF(buffer, sizeof(buffer),
758 "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
762 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
766 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
767 /* set immd2 field if required */
768 if (aop->aopu.aop_immd.from_cast_remat)
770 tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
771 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
777 /*-----------------------------------------------------------------*/
778 /* aopHasRegs - returns true if aop has regs between from-to */
779 /*-----------------------------------------------------------------*/
780 static int aopHasRegs(asmop *aop, int from, int to)
784 if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
786 for (; size < aop->size ; size++) {
788 for (reg = from ; reg <= to ; reg++)
789 if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
794 /*-----------------------------------------------------------------*/
795 /* regsInCommon - two operands have some registers in common */
796 /*-----------------------------------------------------------------*/
798 regsInCommon (operand * op1, operand * op2)
803 /* if they have registers in common */
804 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
807 sym1 = OP_SYMBOL (op1);
808 sym2 = OP_SYMBOL (op2);
810 if (sym1->nRegs == 0 || sym2->nRegs == 0)
813 for (i = 0; i < sym1->nRegs; i++)
819 for (j = 0; j < sym2->nRegs; j++)
824 if (sym2->regs[j] == sym1->regs[i])
832 /*-----------------------------------------------------------------*/
833 /* operandsEqu - equivalent */
834 /*-----------------------------------------------------------------*/
836 operandsEqu (operand * op1, operand * op2)
840 /* if they not symbols */
841 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
844 sym1 = OP_SYMBOL (op1);
845 sym2 = OP_SYMBOL (op2);
847 /* if both are itemps & one is spilt
848 and the other is not then false */
849 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
850 sym1->isspilt != sym2->isspilt)
853 /* if they are the same */
857 if (strcmp (sym1->rname, sym2->rname) == 0)
861 /* if left is a tmp & right is not */
862 if (IS_ITEMP (op1) &&
865 (sym1->usl.spillLoc == sym2))
868 if (IS_ITEMP (op2) &&
872 (sym2->usl.spillLoc == sym1))
875 /* are they spilt to the same location */
876 if (IS_ITEMP (op2) &&
880 (sym1->usl.spillLoc == sym2->usl.spillLoc))
886 /*-----------------------------------------------------------------*/
887 /* sameRegs - two asmops have the same registers */
888 /*-----------------------------------------------------------------*/
890 sameRegs (asmop * aop1, asmop * aop2)
896 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
903 if (aop1->type != AOP_REG ||
904 aop2->type != AOP_REG)
907 if (aop1->size != aop2->size)
910 for (i = 0; i < aop1->size; i++)
911 if (aop1->aopu.aop_reg[i] !=
912 aop2->aopu.aop_reg[i])
918 /*-----------------------------------------------------------------*/
919 /* aopOp - allocates an asmop for an operand : */
920 /*-----------------------------------------------------------------*/
922 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
931 /* if this a literal */
932 if (IS_OP_LITERAL (op))
934 op->aop = aop = newAsmop (AOP_LIT);
935 aop->aopu.aop_lit = op->operand.valOperand;
936 aop->size = getSize (operandType (op));
940 /* if already has a asmop then continue */
943 if ((op->aop->type == AOP_DPTR && useDP2)
944 || (op->aop->type == AOP_DPTR2 && !useDP2))
950 /* if the underlying symbol has a aop */
951 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
953 op->aop = OP_SYMBOL (op)->aop;
954 if ((op->aop->type == AOP_DPTR && useDP2)
955 || (op->aop->type == AOP_DPTR2 && !useDP2))
961 /* if this is a true symbol */
962 if (IS_TRUE_SYMOP (op))
964 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
968 /* this is a temporary : this has
974 e) can be a return use only */
976 sym = OP_SYMBOL (op);
979 /* if the type is a conditional */
980 if (sym->regType == REG_CND)
982 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
987 /* if it is spilt then two situations
989 b) has a spill location */
990 if (sym->isspilt || sym->nRegs == 0)
993 /* rematerialize it NOW */
996 sym->aop = op->aop = aop =
998 aop->size = getSize (sym->type);
1005 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
1006 aop->size = getSize (sym->type);
1007 for (i = 0; i < 2; i++)
1008 aop->aopu.aop_str[i] = accUse[i];
1018 /* a AOP_STR uses DPTR, but DPTR is already in use;
1021 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
1024 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1025 aop->size = getSize (sym->type);
1026 for (i = 0; i < (int) fReturnSizeDS390; i++)
1027 aop->aopu.aop_str[i] = fReturn[i];
1031 if (sym->dptr) { /* has been allocated to a DPTRn */
1032 aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
1033 aop->size = getSize (sym->type);
1034 aop->aopu.dptr = sym->dptr;
1038 if (sym->usl.spillLoc)
1040 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1042 /* force a new aop if sizes differ */
1043 sym->usl.spillLoc->aop = NULL;
1045 sym->aop = op->aop = aop =
1046 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
1047 aop->size = getSize (sym->type);
1051 /* else must be a dummy iTemp */
1052 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1053 aop->size = getSize (sym->type);
1057 /* must be in a register */
1058 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1059 aop->size = sym->nRegs;
1060 for (i = 0; i < sym->nRegs; i++)
1061 aop->aopu.aop_reg[i] = sym->regs[i];
1064 /*-----------------------------------------------------------------*/
1065 /* freeAsmop - free up the asmop given to an operand */
1066 /*----------------------------------------------------------------*/
1068 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1085 /* depending on the asmop type only three cases need work AOP_RO
1086 , AOP_R1 && AOP_STK */
1094 emitcode ("pop", "ar0");
1098 bitVectUnSetBit (ic->rUsed, R0_IDX);
1106 emitcode ("pop", "ar1");
1110 bitVectUnSetBit (ic->rUsed, R1_IDX);
1116 int stk = aop->aopu.aop_stk + aop->size;
1117 bitVectUnSetBit (ic->rUsed, R0_IDX);
1118 bitVectUnSetBit (ic->rUsed, R1_IDX);
1120 getFreePtr (ic, &aop, FALSE);
1122 if (options.stack10bit)
1124 /* I'm not sure what to do here yet... */
1127 "*** Warning: probably generating bad code for "
1128 "10 bit stack mode.\n");
1133 emitcode ("mov", "a,_bp");
1134 emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1135 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1139 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1144 emitcode ("pop", "acc");
1145 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1148 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1151 freeAsmop (op, NULL, ic, TRUE);
1154 emitcode ("pop", "ar0");
1160 emitcode ("pop", "ar1");
1165 if (_G.dptr1InUse) {
1166 emitcode ("pop","dpx1");
1167 emitcode ("pop","dph1");
1168 emitcode ("pop","dpl1");
1173 emitcode ("pop","dpx");
1174 emitcode ("pop","dph");
1175 emitcode ("pop","dpl");
1180 /* all other cases just dealloc */
1186 OP_SYMBOL (op)->aop = NULL;
1187 /* if the symbol has a spill */
1189 SPIL_LOC (op)->aop = NULL;
1194 #define DEFAULT_ACC_WARNING 0
1195 static int saveAccWarn = DEFAULT_ACC_WARNING;
1197 /*-------------------------------------------------------------------*/
1198 /* aopGet - for fetching value of the aop */
1200 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1201 /* in the accumulator. Set it to the name of a free register */
1202 /* if acc must be preserved; the register will be used to preserve */
1203 /* acc temporarily and to return the result byte. */
1204 /*-------------------------------------------------------------------*/
1213 /* offset is greater than
1215 if (offset > (aop->size - 1) &&
1216 aop->type != AOP_LIT)
1219 /* depending on type */
1227 /* if we need to increment it */
1228 while (offset > aop->coff)
1230 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1234 while (offset < aop->coff)
1236 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1243 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1244 return (dname ? "acc" : "a");
1246 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1247 return Safe_strdup(buffer);
1250 assert(offset <= 3);
1251 return dptrn[aop->aopu.dptr][offset];
1256 if (aop->type == AOP_DPTR2)
1264 // if (aop->type != AOP_DPTR2)
1266 // if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1267 // emitcode(";", "spanky: saveAcc for DPTR");
1270 emitcode ("xch", "a, %s", saveAcc);
1275 while (offset > aop->coff)
1277 emitcode ("inc", "dptr");
1281 while (offset < aop->coff)
1283 emitcode ("lcall", "__decdptr");
1290 emitcode ("clr", "a");
1291 emitcode ("movc", "a,@a+dptr");
1295 emitcode ("movx", "a,@dptr");
1298 if (aop->type == AOP_DPTR2)
1306 emitcode ("xch", "a, %s", saveAcc);
1307 // if (strcmp(saveAcc, "_ap"))
1309 // emitcode(";", "spiffy: non _ap return from aopGet.");
1314 return (dname ? "acc" : "a");
1317 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1319 SNPRINTF(buffer, sizeof(buffer),
1320 "%s",aop->aopu.aop_immd.aop_immd2);
1324 SNPRINTF(buffer, sizeof(buffer),
1325 "#%s", aop->aopu.aop_immd.aop_immd1);
1331 tsprintf(buffer, sizeof(buffer),
1332 "#!his",aop->aopu.aop_immd.aop_immd1);
1335 tsprintf(buffer, sizeof(buffer),
1336 "#!hihis",aop->aopu.aop_immd.aop_immd1);
1339 tsprintf(buffer, sizeof(buffer),
1340 "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1342 default: /* should not need this (just in case) */
1343 SNPRINTF (buffer, sizeof(buffer),
1345 aop->aopu.aop_immd.aop_immd1,
1351 SNPRINTF (buffer, sizeof(buffer),
1352 "#%s", aop->aopu.aop_immd.aop_immd1);
1354 return Safe_strdup(buffer);
1359 SNPRINTF (buffer, sizeof(buffer),
1366 SNPRINTF(buffer, sizeof(buffer),
1367 "%s", aop->aopu.aop_dir);
1370 return Safe_strdup(buffer);
1374 return aop->aopu.aop_reg[offset]->dname;
1376 return aop->aopu.aop_reg[offset]->name;
1379 emitcode ("clr", "a");
1380 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1381 emitcode ("rlc", "a");
1382 return (dname ? "acc" : "a");
1385 if (!offset && dname)
1387 return aop->aopu.aop_str[offset];
1390 return aopLiteral (aop->aopu.aop_lit, offset);
1394 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1398 return aop->aopu.aop_str[offset];
1402 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1403 "aopget got unsupported aop->type");
1406 return NULL; // not reached, but makes compiler happy.
1408 /*-----------------------------------------------------------------*/
1409 /* aopPut - puts a string for a aop */
1410 /*-----------------------------------------------------------------*/
1412 aopPut (asmop * aop, char *s, int offset)
1414 if (aop->size && offset > (aop->size - 1))
1416 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1417 "aopPut got offset > aop->size");
1421 /* will assign value to value */
1422 /* depending on where it is ofcourse */
1426 MOVA (s); /* read s in case it was volatile */
1432 SNPRINTF (buffer, sizeof(buffer),
1434 aop->aopu.aop_dir, offset);
1438 SNPRINTF (buffer, sizeof(buffer),
1439 "%s", aop->aopu.aop_dir);
1443 if (strcmp (buffer, s))
1445 emitcode ("mov", "%s,%s", buffer, s);
1450 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1451 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1454 strcmp (s, "r0") == 0 ||
1455 strcmp (s, "r1") == 0 ||
1456 strcmp (s, "r2") == 0 ||
1457 strcmp (s, "r3") == 0 ||
1458 strcmp (s, "r4") == 0 ||
1459 strcmp (s, "r5") == 0 ||
1460 strcmp (s, "r6") == 0 ||
1461 strcmp (s, "r7") == 0)
1463 emitcode ("mov", "%s,%s",
1464 aop->aopu.aop_reg[offset]->dname, s);
1468 emitcode ("mov", "%s,%s",
1469 aop->aopu.aop_reg[offset]->name, s);
1475 emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1481 if (aop->type == AOP_DPTR2)
1489 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1490 "aopPut writting to code space");
1494 while (offset > aop->coff)
1497 emitcode ("inc", "dptr");
1500 while (offset < aop->coff)
1503 emitcode ("lcall", "__decdptr");
1508 /* if not in accumulater */
1511 emitcode ("movx", "@dptr,a");
1513 if (aop->type == AOP_DPTR2)
1521 while (offset > aop->coff)
1524 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1526 while (offset < aop->coff)
1529 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1536 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1542 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1544 else if (strcmp (s, "r0") == 0 ||
1545 strcmp (s, "r1") == 0 ||
1546 strcmp (s, "r2") == 0 ||
1547 strcmp (s, "r3") == 0 ||
1548 strcmp (s, "r4") == 0 ||
1549 strcmp (s, "r5") == 0 ||
1550 strcmp (s, "r6") == 0 ||
1551 strcmp (s, "r7") == 0)
1554 SNPRINTF(buff, sizeof(buff),
1556 emitcode ("mov", "@%s,%s",
1557 aop->aopu.aop_ptr->name, buff);
1561 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1566 if (strcmp (s, "a") == 0)
1567 emitcode ("push", "acc");
1571 emitcode ("push", "acc");
1573 emitcode ("push", s);
1579 /* if bit variable */
1580 if (!aop->aopu.aop_dir)
1582 emitcode ("clr", "a");
1583 emitcode ("rlc", "a");
1588 emitcode ("clr", "%s", aop->aopu.aop_dir);
1590 emitcode ("setb", "%s", aop->aopu.aop_dir);
1591 else if (!strcmp (s, "c"))
1592 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1595 if (strcmp (s, "a"))
1600 /* set C, if a >= 1 */
1601 emitcode ("add", "a,#!constbyte",0xff);
1602 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1610 if (strcmp (aop->aopu.aop_str[offset], s))
1611 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1616 if (!offset && (strcmp (s, "acc") == 0))
1619 if (strcmp (aop->aopu.aop_str[offset], s))
1620 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1624 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1625 "aopPut got unsupported aop->type");
1632 /*--------------------------------------------------------------------*/
1633 /* reAdjustPreg - points a register back to where it should (coff==0) */
1634 /*--------------------------------------------------------------------*/
1636 reAdjustPreg (asmop * aop)
1638 if ((aop->coff==0) || (aop->size <= 1)) {
1647 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1651 if (aop->type == AOP_DPTR2)
1658 emitcode ("lcall", "__decdptr");
1661 if (aop->type == AOP_DPTR2)
1671 #define AOP(op) op->aop
1672 #define AOP_TYPE(op) AOP(op)->type
1673 #define AOP_SIZE(op) AOP(op)->size
1674 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1675 AOP_TYPE(x) == AOP_R0))
1677 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1678 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1681 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1682 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1683 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1684 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1685 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1686 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1688 // The following two macros can be used even if the aop has not yet been aopOp'd.
1689 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1690 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1692 /* Workaround for DS80C390 bug: div ab may return bogus results
1693 * if A is accessed in instruction immediately before the div.
1695 * Will be fixed in B4 rev of processor, Dallas claims.
1698 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1699 if (!AOP_NEEDSACC(RIGHT)) \
1701 /* We can load A first, then B, since \
1702 * B (the RIGHT operand) won't clobber A, \
1703 * thus avoiding touching A right before the div. \
1705 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1706 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1708 L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1713 /* Just stuff in a nop after loading A. */ \
1714 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1715 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1717 emitcode("nop", "; workaround for DS80C390 div bug."); \
1721 /*-----------------------------------------------------------------*/
1722 /* opIsGptr: returns non-zero if the passed operand is */
1723 /* a generic pointer type. */
1724 /*-----------------------------------------------------------------*/
1726 opIsGptr (operand * op)
1728 sym_link *type = operandType (op);
1730 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1737 /*-----------------------------------------------------------------*/
1738 /* getDataSize - get the operand data size */
1739 /*-----------------------------------------------------------------*/
1741 getDataSize (operand * op)
1744 size = AOP_SIZE (op);
1745 if (size == GPTRSIZE)
1747 sym_link *type = operandType (op);
1748 if (IS_GENPTR (type))
1750 /* generic pointer; arithmetic operations
1751 * should ignore the high byte (pointer type).
1759 /*-----------------------------------------------------------------*/
1760 /* outAcc - output Acc */
1761 /*-----------------------------------------------------------------*/
1763 outAcc (operand * result)
1766 size = getDataSize (result);
1769 aopPut (AOP (result), "a", 0);
1772 /* unsigned or positive */
1775 aopPut (AOP (result), zero, offset++);
1780 /*-----------------------------------------------------------------*/
1781 /* outBitC - output a bit C */
1782 /*-----------------------------------------------------------------*/
1784 outBitC (operand * result)
1786 /* if the result is bit */
1787 if (AOP_TYPE (result) == AOP_CRY)
1789 aopPut (AOP (result), "c", 0);
1793 emitcode ("clr", "a");
1794 emitcode ("rlc", "a");
1799 /*-----------------------------------------------------------------*/
1800 /* toBoolean - emit code for orl a,operator(sizeop) */
1801 /*-----------------------------------------------------------------*/
1803 toBoolean (operand * oper)
1805 int size = AOP_SIZE (oper) - 1;
1809 /* The generic part of a generic pointer should
1810 * not participate in it's truth value.
1812 * i.e. 0x10000000 is zero.
1814 if (opIsGptr (oper))
1816 D (emitcode (";", "toBoolean: generic ptr special case."););
1820 _startLazyDPSEvaluation ();
1821 if (AOP_NEEDSACC (oper) && size)
1826 emitcode ("push", "b");
1828 MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1832 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1839 emitcode ("orl", "b,%s",
1840 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1844 emitcode ("orl", "a,%s",
1845 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1848 _endLazyDPSEvaluation ();
1852 emitcode ("mov", "a,b");
1855 emitcode ("pop", "b");
1862 /*-----------------------------------------------------------------*/
1863 /* genNot - generate code for ! operation */
1864 /*-----------------------------------------------------------------*/
1870 D (emitcode (";", "genNot "););
1872 /* assign asmOps to operand & result */
1873 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1874 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1876 /* if in bit space then a special case */
1877 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1879 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1880 emitcode ("cpl", "c");
1881 outBitC (IC_RESULT (ic));
1885 toBoolean (IC_LEFT (ic));
1887 tlbl = newiTempLabel (NULL);
1888 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1889 emitcode ("", "!tlabeldef", tlbl->key + 100);
1890 outBitC (IC_RESULT (ic));
1893 /* release the aops */
1894 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1895 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1899 /*-----------------------------------------------------------------*/
1900 /* genCpl - generate code for complement */
1901 /*-----------------------------------------------------------------*/
1909 D (emitcode (";", "genCpl "););
1912 /* assign asmOps to operand & result */
1913 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1914 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1916 /* special case if in bit space */
1917 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1918 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1919 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1920 emitcode ("cpl", "c");
1921 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1924 tlbl=newiTempLabel(NULL);
1925 emitcode ("cjne", "%s,#0x01,%05d$",
1926 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1927 emitcode ("", "%05d$:", tlbl->key+100);
1928 outBitC (IC_RESULT(ic));
1932 size = AOP_SIZE (IC_RESULT (ic));
1933 _startLazyDPSEvaluation ();
1936 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1937 emitcode ("cpl", "a");
1938 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1940 _endLazyDPSEvaluation ();
1944 /* release the aops */
1945 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1946 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1949 /*-----------------------------------------------------------------*/
1950 /* genUminusFloat - unary minus for floating points */
1951 /*-----------------------------------------------------------------*/
1953 genUminusFloat (operand * op, operand * result)
1955 int size, offset = 0;
1957 D(emitcode (";", "genUminusFloat"););
1959 /* for this we just copy and then flip the bit */
1961 _startLazyDPSEvaluation ();
1962 size = AOP_SIZE (op) - 1;
1966 aopPut (AOP (result),
1967 aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1972 MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1974 emitcode ("cpl", "acc.7");
1975 aopPut (AOP (result), "a", offset);
1976 _endLazyDPSEvaluation ();
1979 /*-----------------------------------------------------------------*/
1980 /* genUminus - unary minus code generation */
1981 /*-----------------------------------------------------------------*/
1983 genUminus (iCode * ic)
1988 D (emitcode (";", "genUminus "););
1991 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1992 aopOp (IC_RESULT (ic), ic, TRUE, (AOP_TYPE(IC_LEFT (ic)) == AOP_DPTR));
1994 /* if both in bit space then special
1996 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1997 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2000 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2001 emitcode ("cpl", "c");
2002 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2006 optype = operandType (IC_LEFT (ic));
2008 /* if float then do float stuff */
2009 if (IS_FLOAT (optype))
2011 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2015 /* otherwise subtract from zero */
2016 size = AOP_SIZE (IC_LEFT (ic));
2018 _startLazyDPSEvaluation ();
2021 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
2022 if (!strcmp (l, "a"))
2026 emitcode ("cpl", "a");
2027 emitcode ("addc", "a,#0");
2033 emitcode ("clr", "a");
2034 emitcode ("subb", "a,%s", l);
2036 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2038 _endLazyDPSEvaluation ();
2040 /* if any remaining bytes in the result */
2041 /* we just need to propagate the sign */
2042 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
2044 emitcode ("rlc", "a");
2045 emitcode ("subb", "a,acc");
2047 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2051 /* release the aops */
2052 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2053 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2056 /*-----------------------------------------------------------------*/
2057 /* savermask - saves registers in the mask */
2058 /*-----------------------------------------------------------------*/
2059 static void savermask(bitVect *rs_mask)
2062 if (options.useXstack) {
2063 if (bitVectBitValue (rs_mask, R0_IDX))
2064 emitcode ("mov", "b,r0");
2065 emitcode ("mov", "r0,%s", spname);
2066 for (i = 0; i < ds390_nRegs; i++) {
2067 if (bitVectBitValue (rs_mask, i)) {
2069 emitcode ("mov", "a,b");
2071 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2072 emitcode ("movx", "@r0,a");
2073 emitcode ("inc", "r0");
2076 emitcode ("mov", "%s,r0", spname);
2077 if (bitVectBitValue (rs_mask, R0_IDX))
2078 emitcode ("mov", "r0,b");
2080 for (i = 0; i < ds390_nRegs; i++) {
2081 if (bitVectBitValue (rs_mask, i))
2082 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2087 /*-----------------------------------------------------------------*/
2088 /* saveRegisters - will look for a call and save the registers */
2089 /*-----------------------------------------------------------------*/
2091 saveRegisters (iCode * lic)
2097 for (ic = lic; ic; ic = ic->next)
2098 if (ic->op == CALL || ic->op == PCALL)
2103 fprintf (stderr, "found parameter push with no function call\n");
2107 /* if the registers have been saved already then
2110 || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2113 /* special case if DPTR alive across a function call then must save it
2114 even though callee saves */
2115 if (IS_SYMOP(IC_LEFT(ic)) &&
2116 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2118 rsave = newBitVect(ic->rMask->size);
2119 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2120 if (bitVectBitValue(ic->rMask,i))
2121 rsave = bitVectSetBit(rsave,i);
2123 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2125 /* safe the registers in use at this time but skip the
2126 ones for the result */
2127 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2128 ds390_rUmaskForOp (IC_RESULT(ic)));
2134 /*-----------------------------------------------------------------*/
2135 /* usavermask - restore registers with mask */
2136 /*-----------------------------------------------------------------*/
2137 static void unsavermask(bitVect *rs_mask)
2140 if (options.useXstack) {
2141 emitcode ("mov", "r0,%s", spname);
2142 for (i = ds390_nRegs; i >= 0; i--) {
2143 if (bitVectBitValue (rs_mask, i)) {
2144 emitcode ("dec", "r0");
2145 emitcode ("movx", "a,@r0");
2147 emitcode ("mov", "b,a");
2149 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2152 emitcode ("mov", "%s,r0", spname);
2153 if (bitVectBitValue (rs_mask, R0_IDX))
2154 emitcode ("mov", "r0,b");
2156 for (i = ds390_nRegs; i >= 0; i--) {
2157 if (bitVectBitValue (rs_mask, i))
2158 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2163 /*-----------------------------------------------------------------*/
2164 /* unsaveRegisters - pop the pushed registers */
2165 /*-----------------------------------------------------------------*/
2167 unsaveRegisters (iCode * ic)
2171 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2173 rsave = newBitVect(ic->rMask->size);
2174 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2175 if (bitVectBitValue(ic->rMask,i))
2176 rsave = bitVectSetBit(rsave,i);
2178 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2180 /* restore the registers in use at this time but skip the
2181 ones for the result */
2182 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2183 ds390_rUmaskForOp (IC_RESULT(ic)));
2189 /*-----------------------------------------------------------------*/
2191 /*-----------------------------------------------------------------*/
2193 pushSide (operand * oper, int size)
2196 _startLazyDPSEvaluation ();
2199 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2200 if (AOP_TYPE (oper) != AOP_REG &&
2201 AOP_TYPE (oper) != AOP_DIR &&
2204 emitcode ("mov", "a,%s", l);
2205 emitcode ("push", "acc");
2208 emitcode ("push", "%s", l);
2210 _endLazyDPSEvaluation ();
2213 /*-----------------------------------------------------------------*/
2214 /* assignResultValue - */
2215 /*-----------------------------------------------------------------*/
2217 assignResultValue (operand * oper)
2220 int size = AOP_SIZE (oper);
2221 bool pushedAcc = FALSE;
2223 if (size == fReturnSizeDS390)
2225 /* I don't think this case can ever happen... */
2226 /* ACC is the last part of this. If writing the result
2227 * uses AC, we must preserve it.
2229 if (AOP_NEEDSACC(oper))
2231 emitcode(";", "assignResultValue special case for ACC.");
2232 emitcode("push", "acc");
2239 _startLazyDPSEvaluation ();
2242 aopPut (AOP (oper), fReturn[offset], offset);
2245 _endLazyDPSEvaluation ();
2249 emitcode("pop", "acc");
2250 aopPut(AOP(oper), "a", offset);
2255 /*-----------------------------------------------------------------*/
2256 /* genXpush - pushes onto the external stack */
2257 /*-----------------------------------------------------------------*/
2259 genXpush (iCode * ic)
2261 asmop *aop = newAsmop (0);
2263 int size, offset = 0;
2265 D (emitcode (";", "genXpush ");
2268 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2269 r = getFreePtr (ic, &aop, FALSE);
2272 emitcode ("mov", "%s,_spx", r->name);
2274 size = AOP_SIZE (IC_LEFT (ic));
2275 _startLazyDPSEvaluation ();
2279 MOVA (aopGet (AOP (IC_LEFT (ic)),
2280 offset++, FALSE, FALSE, NULL));
2281 emitcode ("movx", "@%s,a", r->name);
2282 emitcode ("inc", "%s", r->name);
2285 _endLazyDPSEvaluation ();
2288 emitcode ("mov", "_spx,%s", r->name);
2290 freeAsmop (NULL, aop, ic, TRUE);
2291 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2294 /*-----------------------------------------------------------------*/
2295 /* genIpush - generate code for pushing this gets a little complex */
2296 /*-----------------------------------------------------------------*/
2298 genIpush (iCode * ic)
2300 int size, offset = 0;
2303 D (emitcode (";", "genIpush ");
2306 /* if this is not a parm push : ie. it is spill push
2307 and spill push is always done on the local stack */
2311 /* and the item is spilt then do nothing */
2312 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2315 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2316 size = AOP_SIZE (IC_LEFT (ic));
2317 /* push it on the stack */
2318 _startLazyDPSEvaluation ();
2321 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2327 emitcode ("push", "%s", l);
2329 _endLazyDPSEvaluation ();
2333 /* this is a paramter push: in this case we call
2334 the routine to find the call and save those
2335 registers that need to be saved */
2338 /* if use external stack then call the external
2339 stack pushing routine */
2340 if (options.useXstack)
2346 /* then do the push */
2347 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2349 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2350 size = AOP_SIZE (IC_LEFT (ic));
2352 _startLazyDPSEvaluation ();
2355 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2356 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2357 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2360 emitcode ("mov", "a,%s", l);
2361 emitcode ("push", "acc");
2365 emitcode ("push", "%s", l);
2368 _endLazyDPSEvaluation ();
2370 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2373 /*-----------------------------------------------------------------*/
2374 /* genIpop - recover the registers: can happen only for spilling */
2375 /*-----------------------------------------------------------------*/
2377 genIpop (iCode * ic)
2381 D (emitcode (";", "genIpop ");
2385 /* if the temp was not pushed then */
2386 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2389 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2390 size = AOP_SIZE (IC_LEFT (ic));
2391 offset = (size - 1);
2392 _startLazyDPSEvaluation ();
2395 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2396 FALSE, TRUE, NULL));
2398 _endLazyDPSEvaluation ();
2400 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2403 /*-----------------------------------------------------------------*/
2404 /* unsaveRBank - restores the resgister bank from stack */
2405 /*-----------------------------------------------------------------*/
2407 unsaveRBank (int bank, iCode * ic, bool popPsw)
2413 if (options.useXstack)
2417 /* Assume r0 is available for use. */
2418 r = ds390_regWithIdx (R0_IDX);;
2423 r = getFreePtr (ic, &aop, FALSE);
2425 emitcode ("mov", "%s,_spx", r->name);
2430 if (options.useXstack)
2432 emitcode ("movx", "a,@%s", r->name);
2433 emitcode ("mov", "psw,a");
2434 emitcode ("dec", "%s", r->name);
2438 emitcode ("pop", "psw");
2442 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2444 if (options.useXstack)
2446 emitcode ("movx", "a,@%s", r->name);
2447 emitcode ("mov", "(%s+%d),a",
2448 regs390[i].base, 8 * bank + regs390[i].offset);
2449 emitcode ("dec", "%s", r->name);
2453 emitcode ("pop", "(%s+%d)",
2454 regs390[i].base, 8 * bank + regs390[i].offset);
2457 if (options.useXstack)
2459 emitcode ("mov", "_spx,%s", r->name);
2464 freeAsmop (NULL, aop, ic, TRUE);
2468 /*-----------------------------------------------------------------*/
2469 /* saveRBank - saves an entire register bank on the stack */
2470 /*-----------------------------------------------------------------*/
2472 saveRBank (int bank, iCode * ic, bool pushPsw)
2478 if (options.useXstack)
2482 /* Assume r0 is available for use. */
2483 r = ds390_regWithIdx (R0_IDX);;
2488 r = getFreePtr (ic, &aop, FALSE);
2490 emitcode ("mov", "%s,_spx", r->name);
2493 for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2495 if (options.useXstack)
2497 emitcode ("inc", "%s", r->name);
2498 emitcode ("mov", "a,(%s+%d)",
2499 regs390[i].base, 8 * bank + regs390[i].offset);
2500 emitcode ("movx", "@%s,a", r->name);
2503 emitcode ("push", "(%s+%d)",
2504 regs390[i].base, 8 * bank + regs390[i].offset);
2509 if (options.useXstack)
2511 emitcode ("mov", "a,psw");
2512 emitcode ("movx", "@%s,a", r->name);
2513 emitcode ("inc", "%s", r->name);
2514 emitcode ("mov", "_spx,%s", r->name);
2518 emitcode ("push", "psw");
2521 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2526 freeAsmop (NULL, aop, ic, TRUE);
2535 /*-----------------------------------------------------------------*/
2536 /* genSend - gen code for SEND */
2537 /*-----------------------------------------------------------------*/
2538 static void genSend(set *sendSet)
2542 static int rb1_count = 0;
2544 for (sic = setFirstItem (sendSet); sic;
2545 sic = setNextItem (sendSet)) {
2546 int size, offset = 0;
2548 size=getSize(operandType(IC_LEFT(sic)));
2549 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2550 if (sendCount == 0) { /* first parameter */
2551 // we know that dpl(hxb) is the result, so
2553 _startLazyDPSEvaluation ();
2555 aopOp (IC_LEFT (sic), sic, FALSE,
2556 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2558 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2561 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2562 FALSE, FALSE, NULL);
2563 if (strcmp (l, fReturn[offset])) {
2564 emitcode ("mov", "%s,%s",
2570 _endLazyDPSEvaluation ();
2571 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2573 } else { /* if more parameter in registers */
2574 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2576 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2577 FALSE, FALSE, NULL));
2579 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2586 adjustEsp(const char *reg)
2588 emitcode ("anl","%s,#3", reg);
2589 if (TARGET_IS_DS400)
2591 emitcode ("orl","%s,#!constbyte",
2593 (options.stack_loc >> 8) & 0xff);
2597 /*-----------------------------------------------------------------*/
2598 /* genCall - generates a call statement */
2599 /*-----------------------------------------------------------------*/
2601 genCall (iCode * ic)
2604 bool restoreBank = FALSE;
2605 bool swapBanks = FALSE;
2607 D (emitcode (";", "genCall "););
2609 /* if we are calling a not _naked function that is not using
2610 the same register bank then we need to save the
2611 destination registers on the stack */
2612 dtype = operandType (IC_LEFT (ic));
2613 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2614 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2615 IFFUNC_ISISR (currFunc->type))
2619 /* This is unexpected; the bank should have been saved in
2622 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2628 /* if caller saves & we have not saved then */
2632 /* if send set is not empty the assign */
2633 /* We've saved all the registers we care about;
2634 * therefore, we may clobber any register not used
2635 * in the calling convention (i.e. anything not in
2640 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2641 genSend(reverseSet(_G.sendSet));
2643 genSend(_G.sendSet);
2650 emitcode ("mov", "psw,#!constbyte",
2651 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2655 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2656 OP_SYMBOL (IC_LEFT (ic))->rname :
2657 OP_SYMBOL (IC_LEFT (ic))->name));
2661 emitcode ("mov", "psw,#!constbyte",
2662 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2665 /* if we need assign a result value */
2666 if ((IS_ITEMP (IC_RESULT (ic)) &&
2667 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2668 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2669 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2670 IS_TRUE_SYMOP (IC_RESULT (ic)))
2672 if (isOperandInFarSpace (IC_RESULT (ic))
2673 && getSize (operandType (IC_RESULT (ic))) <= 2)
2675 int size = getSize (operandType (IC_RESULT (ic)));
2677 /* Special case for 1 or 2 byte return in far space. */
2681 emitcode ("mov", "b,%s", fReturn[1]);
2686 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2692 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2696 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2698 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2703 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2706 assignResultValue (IC_RESULT (ic));
2708 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2712 /* adjust the stack for parameters if
2714 if (ic->parmBytes) {
2716 if (options.stack10bit) {
2717 if (ic->parmBytes <= 10) {
2718 emitcode(";","stack adjustment for parms");
2719 for (i=0; i < ic->parmBytes ; i++) {
2720 emitcode("pop","acc");
2724 emitcode ("clr","c");
2725 emitcode ("mov","a,sp");
2726 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2727 emitcode ("mov","sp,a");
2728 emitcode ("mov","a,esp");
2730 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2731 emitcode ("mov","esp,a");
2735 if (ic->parmBytes > 3) {
2736 emitcode ("mov", "a,%s", spname);
2737 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2738 emitcode ("mov", "%s,a", spname);
2740 for (i = 0; i < ic->parmBytes; i++)
2741 emitcode ("dec", "%s", spname);
2745 /* if we hade saved some registers then unsave them */
2747 unsaveRegisters (ic);
2749 /* if register bank was saved then pop them */
2751 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2754 /*-----------------------------------------------------------------*/
2755 /* genPcall - generates a call by pointer statement */
2756 /*-----------------------------------------------------------------*/
2758 genPcall (iCode * ic)
2761 symbol *rlbl = newiTempLabel (NULL);
2762 bool restoreBank=FALSE;
2764 D (emitcode (";", "genPcall ");
2768 /* if caller saves & we have not saved then */
2772 /* if we are calling a function that is not using
2773 the same register bank then we need to save the
2774 destination registers on the stack */
2775 dtype = operandType (IC_LEFT (ic));
2776 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2777 IFFUNC_ISISR (currFunc->type) &&
2778 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2779 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2783 /* push the return address on to the stack */
2784 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2785 emitcode ("push", "acc");
2786 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2787 emitcode ("push", "acc");
2789 if (options.model == MODEL_FLAT24)
2791 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2792 emitcode ("push", "acc");
2795 /* now push the calling address */
2796 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2798 pushSide (IC_LEFT (ic), FPTRSIZE);
2800 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2802 /* if send set is not empty the assign */
2805 genSend(reverseSet(_G.sendSet));
2809 emitcode ("ret", "");
2810 emitcode ("", "!tlabeldef", (rlbl->key + 100));
2813 /* if we need assign a result value */
2814 if ((IS_ITEMP (IC_RESULT (ic)) &&
2815 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2816 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2817 IS_TRUE_SYMOP (IC_RESULT (ic)))
2821 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2824 assignResultValue (IC_RESULT (ic));
2826 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2829 /* adjust the stack for parameters if
2834 if (options.stack10bit) {
2835 if (ic->parmBytes <= 10) {
2836 emitcode(";","stack adjustment for parms");
2837 for (i=0; i < ic->parmBytes ; i++) {
2838 emitcode("pop","acc");
2842 emitcode ("clr","c");
2843 emitcode ("mov","a,sp");
2844 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2845 emitcode ("mov","sp,a");
2846 emitcode ("mov","a,esp");
2848 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2849 emitcode ("mov","esp,a");
2853 if (ic->parmBytes > 3) {
2854 emitcode ("mov", "a,%s", spname);
2855 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2856 emitcode ("mov", "%s,a", spname);
2859 for (i = 0; i < ic->parmBytes; i++)
2860 emitcode ("dec", "%s", spname);
2864 /* if register bank was saved then unsave them */
2866 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2868 /* if we hade saved some registers then
2871 unsaveRegisters (ic);
2875 /*-----------------------------------------------------------------*/
2876 /* resultRemat - result is rematerializable */
2877 /*-----------------------------------------------------------------*/
2879 resultRemat (iCode * ic)
2881 if (SKIP_IC (ic) || ic->op == IFX)
2884 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2886 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2887 if (sym->remat && !POINTER_SET (ic))
2894 #if defined(__BORLANDC__) || defined(_MSC_VER)
2895 #define STRCASECMP stricmp
2897 #define STRCASECMP strcasecmp
2900 /*-----------------------------------------------------------------*/
2901 /* inExcludeList - return 1 if the string is in exclude Reg list */
2902 /*-----------------------------------------------------------------*/
2904 regsCmp(void *p1, void *p2)
2906 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2910 inExcludeList (char *s)
2912 const char *p = setFirstItem(options.excludeRegsSet);
2914 if (p == NULL || STRCASECMP(p, "none") == 0)
2918 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2921 /*-----------------------------------------------------------------*/
2922 /* genFunction - generated code for function entry */
2923 /*-----------------------------------------------------------------*/
2925 genFunction (iCode * ic)
2929 bool switchedPSW = FALSE;
2931 D (emitcode (";", "genFunction "););
2934 /* create the function header */
2935 emitcode (";", "-----------------------------------------");
2936 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2937 emitcode (";", "-----------------------------------------");
2939 emitcode ("", "%s:", sym->rname);
2940 ftype = operandType (IC_LEFT (ic));
2942 if (IFFUNC_ISNAKED(ftype))
2944 emitcode(";", "naked function: no prologue.");
2948 if (options.stack_probe)
2949 emitcode ("lcall","__stack_probe");
2951 /* here we need to generate the equates for the
2952 register bank if required */
2953 if (FUNC_REGBANK (ftype) != rbank)
2957 rbank = FUNC_REGBANK (ftype);
2958 for (i = 0; i < ds390_nRegs; i++)
2960 if (regs390[i].print) {
2961 if (strcmp (regs390[i].base, "0") == 0)
2962 emitcode ("", "%s !equ !constbyte",
2964 8 * rbank + regs390[i].offset);
2966 emitcode ("", "%s !equ %s + !constbyte",
2969 8 * rbank + regs390[i].offset);
2974 /* if this is an interrupt service routine then
2975 save acc, b, dpl, dph */
2976 if (IFFUNC_ISISR (sym->type))
2978 if (!inExcludeList ("acc"))
2979 emitcode ("push", "acc");
2980 if (!inExcludeList ("b"))
2981 emitcode ("push", "b");
2982 if (!inExcludeList ("dpl"))
2983 emitcode ("push", "dpl");
2984 if (!inExcludeList ("dph"))
2985 emitcode ("push", "dph");
2986 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2988 emitcode ("push", "dpx");
2989 /* Make sure we're using standard DPTR */
2990 emitcode ("push", "dps");
2991 emitcode ("mov", "dps,#0");
2992 if (options.stack10bit)
2994 /* This ISR could conceivably use DPTR2. Better save it. */
2995 emitcode ("push", "dpl1");
2996 emitcode ("push", "dph1");
2997 emitcode ("push", "dpx1");
2998 emitcode ("push", DP2_RESULT_REG);
3001 /* if this isr has no bank i.e. is going to
3002 run with bank 0 , then we need to save more
3004 if (!FUNC_REGBANK (sym->type))
3008 /* if this function does not call any other
3009 function then we can be economical and
3010 save only those registers that are used */
3011 if (!IFFUNC_HASFCALL(sym->type))
3014 /* if any registers used */
3017 /* save the registers used */
3018 for (i = 0; i < sym->regsUsed->size; i++)
3020 if (bitVectBitValue (sym->regsUsed, i) ||
3021 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3022 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3025 else if (ds390_ptrRegReq)
3027 emitcode ("push", "%s", ds390_regWithIdx (R0_IDX)->dname);
3028 emitcode ("push", "%s", ds390_regWithIdx (R1_IDX)->dname);
3034 /* this function has a function call cannot
3035 determines register usage so we will have to push the
3037 saveRBank (0, ic, FALSE);
3038 if (options.parms_in_bank1) {
3039 for (i=0; i < 8 ; i++ ) {
3040 emitcode ("push","%s",rb1regs[i]);
3047 /* This ISR uses a non-zero bank.
3049 * We assume that the bank is available for our
3052 * However, if this ISR calls a function which uses some
3053 * other bank, we must save that bank entirely.
3055 unsigned long banksToSave = 0;
3057 if (IFFUNC_HASFCALL(sym->type))
3060 #define MAX_REGISTER_BANKS 4
3065 for (i = ic; i; i = i->next)
3067 if (i->op == ENDFUNCTION)
3069 /* we got to the end OK. */
3077 dtype = operandType (IC_LEFT(i));
3079 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3081 /* Mark this bank for saving. */
3082 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3084 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3088 banksToSave |= (1 << FUNC_REGBANK(dtype));
3091 /* And note that we don't need to do it in
3099 /* This is a mess; we have no idea what
3100 * register bank the called function might
3103 * The only thing I can think of to do is
3104 * throw a warning and hope.
3106 werror(W_FUNCPTR_IN_USING_ISR);
3110 if (banksToSave && options.useXstack)
3112 /* Since we aren't passing it an ic,
3113 * saveRBank will assume r0 is available to abuse.
3115 * So switch to our (trashable) bank now, so
3116 * the caller's R0 isn't trashed.
3118 emitcode ("push", "psw");
3119 emitcode ("mov", "psw,#!constbyte",
3120 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3124 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3126 if (banksToSave & (1 << ix))
3128 saveRBank(ix, NULL, FALSE);
3132 // TODO: this needs a closer look
3133 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3138 /* if callee-save to be used for this function
3139 then save the registers being used in this function */
3140 if (IFFUNC_CALLEESAVES(sym->type))
3144 /* if any registers used */
3147 /* save the registers used */
3148 for (i = 0; i < sym->regsUsed->size; i++)
3150 if (bitVectBitValue (sym->regsUsed, i) ||
3151 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3153 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3158 else if (ds390_ptrRegReq)
3160 emitcode ("push", "%s", ds390_regWithIdx (R0_IDX)->dname);
3161 emitcode ("push", "%s", ds390_regWithIdx (R1_IDX)->dname);
3167 /* set the register bank to the desired value */
3168 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3171 emitcode ("push", "psw");
3172 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3175 if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3176 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3177 if (options.stack10bit) {
3178 emitcode ("push","_bpx");
3179 emitcode ("push","_bpx+1");
3180 emitcode ("mov","_bpx,%s",spname);
3181 emitcode ("mov","_bpx+1,esp");
3182 adjustEsp("_bpx+1");
3184 if (options.useXstack) {
3185 emitcode ("mov", "r0,%s", spname);
3186 emitcode ("mov", "a,_bp");
3187 emitcode ("movx", "@r0,a");
3188 emitcode ("inc", "%s", spname);
3190 /* set up the stack */
3191 emitcode ("push", "_bp"); /* save the callers stack */
3193 emitcode ("mov", "_bp,%s", spname);
3197 /* adjust the stack for the function */
3200 if (options.stack10bit) {
3201 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3202 assert (sym->recvSize <= 4);
3203 if (sym->stack <= 8) {
3204 while (i--) emitcode ("push","acc");
3207 emitcode ("mov","a,sp");
3208 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3209 emitcode ("mov","sp,a");
3210 emitcode ("mov","a,esp");
3212 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3213 emitcode ("mov","esp,a");
3218 werror (W_STACK_OVERFLOW, sym->name);
3220 if (i > 3 && sym->recvSize < 4) {
3222 emitcode ("mov", "a,sp");
3223 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3224 emitcode ("mov", "sp,a");
3228 emitcode ("inc", "sp");
3235 emitcode ("mov", "a,_spx");
3236 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3237 emitcode ("mov", "_spx,a");
3240 /* if critical function then turn interrupts off */
3241 if (IFFUNC_ISCRITICAL (ftype))
3243 symbol *tlbl = newiTempLabel (NULL);
3244 emitcode ("setb", "c");
3245 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3246 emitcode ("clr", "c");
3247 emitcode ("", "%05d$:", (tlbl->key + 100));
3248 emitcode ("push", "psw"); /* save old ea via c in psw */
3253 /*-----------------------------------------------------------------*/
3254 /* genEndFunction - generates epilogue for functions */
3255 /*-----------------------------------------------------------------*/
3257 genEndFunction (iCode * ic)
3259 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3260 lineNode *lnp = lineCurr;
3262 bitVect *regsUsedPrologue;
3263 bitVect *regsUnneeded;
3266 D (emitcode (";", "genEndFunction "););
3268 if (IFFUNC_ISNAKED(sym->type))
3270 emitcode(";", "naked function: no epilogue.");
3274 if (IFFUNC_ISCRITICAL (sym->type))
3276 emitcode ("pop", "psw"); /* restore ea via c in psw */
3277 emitcode ("mov", "ea,c");
3280 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3281 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3283 if (options.stack10bit) {
3285 emitcode ("mov", "sp,_bpx", spname);
3286 emitcode ("mov", "esp,_bpx+1", spname);
3289 emitcode ("mov", "%s,_bp", spname);
3293 /* if use external stack but some variables were
3294 added to the local stack then decrement the
3296 if (options.useXstack && sym->stack) {
3297 emitcode ("mov", "a,sp");
3298 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3299 emitcode ("mov", "sp,a");
3303 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3304 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3306 if (options.useXstack) {
3307 emitcode ("mov", "r0,%s", spname);
3308 emitcode ("movx", "a,@r0");
3309 emitcode ("mov", "_bp,a");
3310 emitcode ("dec", "%s", spname);
3312 if (options.stack10bit) {
3313 emitcode ("pop", "_bpx+1");
3314 emitcode ("pop", "_bpx");
3316 emitcode ("pop", "_bp");
3321 /* restore the register bank */
3322 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3324 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3325 || !options.useXstack)
3327 /* Special case of ISR using non-zero bank with useXstack
3330 emitcode ("pop", "psw");
3334 if (IFFUNC_ISISR (sym->type))
3337 /* now we need to restore the registers */
3338 /* if this isr has no bank i.e. is going to
3339 run with bank 0 , then we need to save more
3341 if (!FUNC_REGBANK (sym->type))
3344 /* if this function does not call any other
3345 function then we can be economical and
3346 save only those registers that are used */
3347 if (!IFFUNC_HASFCALL(sym->type))
3350 /* if any registers used */
3353 /* save the registers used */
3354 for (i = sym->regsUsed->size; i >= 0; i--)
3356 if (bitVectBitValue (sym->regsUsed, i) ||
3357 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3358 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3361 else if (ds390_ptrRegReq)
3363 emitcode ("pop", "%s", ds390_regWithIdx (R1_IDX)->dname);
3364 emitcode ("pop", "%s", ds390_regWithIdx (R0_IDX)->dname);
3370 /* this function has a function call cannot
3371 determines register usage so we will have to pop the
3373 if (options.parms_in_bank1) {
3374 for (i = 7 ; i >= 0 ; i-- ) {
3375 emitcode ("pop","%s",rb1regs[i]);
3378 unsaveRBank (0, ic, FALSE);
3383 /* This ISR uses a non-zero bank.
3385 * Restore any register banks saved by genFunction
3388 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3391 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3393 if (savedBanks & (1 << ix))
3395 unsaveRBank(ix, NULL, FALSE);
3399 if (options.useXstack)
3401 /* Restore bank AFTER calling unsaveRBank,
3402 * since it can trash r0.
3404 emitcode ("pop", "psw");
3408 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3410 if (options.stack10bit)
3412 emitcode ("pop", DP2_RESULT_REG);
3413 emitcode ("pop", "dpx1");
3414 emitcode ("pop", "dph1");
3415 emitcode ("pop", "dpl1");
3417 emitcode ("pop", "dps");
3418 emitcode ("pop", "dpx");
3420 if (!inExcludeList ("dph"))
3421 emitcode ("pop", "dph");
3422 if (!inExcludeList ("dpl"))
3423 emitcode ("pop", "dpl");
3424 if (!inExcludeList ("b"))
3425 emitcode ("pop", "b");
3426 if (!inExcludeList ("acc"))
3427 emitcode ("pop", "acc");
3429 /* if debug then send end of function */
3430 if (options.debug && currFunc) {
3432 emitcode ("", "C$%s$%d$%d$%d ==.",
3433 FileBaseName (ic->filename), currFunc->lastLine,
3434 ic->level, ic->block);
3435 if (IS_STATIC (currFunc->etype))
3436 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3438 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3442 emitcode ("reti", "");
3446 if (IFFUNC_CALLEESAVES(sym->type))
3450 /* if any registers used */
3453 /* save the registers used */
3454 for (i = sym->regsUsed->size; i >= 0; i--)
3456 if (bitVectBitValue (sym->regsUsed, i) ||
3457 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3458 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3461 else if (ds390_ptrRegReq)
3463 emitcode ("pop", "%s", ds390_regWithIdx (R1_IDX)->dname);
3464 emitcode ("pop", "%s", ds390_regWithIdx (R0_IDX)->dname);
3469 /* if debug then send end of function */
3470 if (options.debug && currFunc)
3473 emitcode ("", "C$%s$%d$%d$%d ==.",
3474 FileBaseName (ic->filename), currFunc->lastLine,
3475 ic->level, ic->block);
3476 if (IS_STATIC (currFunc->etype))
3477 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3479 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3483 emitcode ("ret", "");
3486 if (!port->peep.getRegsRead || !port->peep.getRegsWritten)
3489 /* If this was an interrupt handler using bank 0 that called another */
3490 /* function, then all registers must be saved; nothing to optimized. */
3491 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3492 && !FUNC_REGBANK(sym->type))
3495 /* Compute the registers actually used */
3496 regsUsed = newBitVect (ds390_nRegs);
3497 regsUsedPrologue = newBitVect (ds390_nRegs);
3500 if (lnp->ic && lnp->ic->op == FUNCTION)
3501 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3503 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3505 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3506 && lnp->prev->ic && lnp->prev->ic->op != FUNCTION)
3513 if (bitVectBitValue (regsUsedPrologue, DPS_IDX)
3514 && !bitVectBitValue (regsUsed, DPS_IDX))
3516 bitVectUnSetBit (regsUsedPrologue, DPS_IDX);
3519 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3520 && !bitVectBitValue (regsUsed, CND_IDX))
3522 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3523 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK(sym->type)
3525 bitVectUnSetBit (regsUsed, CND_IDX);
3528 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3530 /* If this was an interrupt handler that called another function */
3531 /* function, then assume working registers may be modified by it. */
3532 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3534 regsUsed = bitVectSetBit (regsUsed, AP_IDX);
3535 regsUsed = bitVectSetBit (regsUsed, DPX1_IDX);
3536 regsUsed = bitVectSetBit (regsUsed, DPL1_IDX);
3537 regsUsed = bitVectSetBit (regsUsed, DPH1_IDX);
3538 regsUsed = bitVectSetBit (regsUsed, DPX_IDX);
3539 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3540 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3541 regsUsed = bitVectSetBit (regsUsed, DPS_IDX);
3542 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3543 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3544 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3547 /* Remove the unneeded push/pops */
3548 regsUnneeded = newBitVect (ds390_nRegs);
3551 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3553 if (!strncmp(lnp->line, "push", 4))
3555 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3556 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3558 connectLine (lnp->prev, lnp->next);
3559 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3562 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3564 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3565 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3567 connectLine (lnp->prev, lnp->next);
3568 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3575 for (idx = 0; idx < regsUnneeded->size; idx++)
3576 if (bitVectBitValue (regsUnneeded, idx))
3577 emitcode ("", ";\teliminated unneeded push/pop %s", ds390_regWithIdx (idx)->dname);
3579 freeBitVect (regsUnneeded);
3580 freeBitVect (regsUsed);
3581 freeBitVect (regsUsedPrologue);
3584 /*-----------------------------------------------------------------*/
3585 /* genJavaNativeRet - generate code for return JavaNative */
3586 /*-----------------------------------------------------------------*/
3587 static void genJavaNativeRet(iCode *ic)
3591 aopOp (IC_LEFT (ic), ic, FALSE,
3592 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3593 size = AOP_SIZE (IC_LEFT (ic));
3597 /* it is assigned to GPR0-R3 then push them */
3598 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3599 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3600 for (i = 0 ; i < size ; i++ ) {
3601 emitcode ("push","%s",
3602 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3604 for (i = (size-1) ; i >= 0 ; i--) {
3605 emitcode ("pop","a%s",javaRet[i]);
3608 for (i = 0 ; i < size ; i++)
3609 emitcode ("mov","%s,%s",javaRet[i],
3610 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3612 for (i = size ; i < 4 ; i++ )
3613 emitcode ("mov","%s,#0",javaRet[i]);
3617 /*-----------------------------------------------------------------*/
3618 /* genRet - generate code for return statement */
3619 /*-----------------------------------------------------------------*/
3623 int size, offset = 0, pushed = 0;
3625 D (emitcode (";", "genRet "););
3627 /* if we have no return value then
3628 just generate the "ret" */
3632 /* if this is a JavaNative function then return
3633 value in different register */
3634 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3635 genJavaNativeRet(ic);
3638 /* we have something to return then
3639 move the return value into place */
3640 aopOp (IC_LEFT (ic), ic, FALSE,
3641 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3642 size = AOP_SIZE (IC_LEFT (ic));
3644 _startLazyDPSEvaluation ();
3648 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3650 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3652 emitcode ("push", "%s", l);
3657 /* Since A is the last element of fReturn,
3658 * is is OK to clobber it in the aopGet.
3660 l = aopGet (AOP (IC_LEFT (ic)), offset,
3661 FALSE, FALSE, NULL);
3662 if (strcmp (fReturn[offset], l))
3663 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3666 _endLazyDPSEvaluation ();
3673 if (strcmp (fReturn[pushed], "a"))
3674 emitcode ("pop", fReturn[pushed]);
3676 emitcode ("pop", "acc");
3679 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3682 /* generate a jump to the return label
3683 if the next is not the return statement */
3684 if (!(ic->next && ic->next->op == LABEL &&
3685 IC_LABEL (ic->next) == returnLabel))
3687 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3691 /*-----------------------------------------------------------------*/
3692 /* genLabel - generates a label */
3693 /*-----------------------------------------------------------------*/
3695 genLabel (iCode * ic)
3697 /* special case never generate */
3698 if (IC_LABEL (ic) == entryLabel)
3701 D (emitcode (";", "genLabel ");
3704 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3707 /*-----------------------------------------------------------------*/
3708 /* genGoto - generates a ljmp */
3709 /*-----------------------------------------------------------------*/
3711 genGoto (iCode * ic)
3713 D (emitcode (";", "genGoto ");
3715 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3718 /*-----------------------------------------------------------------*/
3719 /* findLabelBackwards: walks back through the iCode chain looking */
3720 /* for the given label. Returns number of iCode instructions */
3721 /* between that label and given ic. */
3722 /* Returns zero if label not found. */
3723 /*-----------------------------------------------------------------*/
3725 findLabelBackwards (iCode * ic, int key)
3734 /* If we have any pushes or pops, we cannot predict the distance.
3735 I don't like this at all, this should be dealt with in the
3737 if (ic->op == IPUSH || ic->op == IPOP) {
3741 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3743 /* printf("findLabelBackwards = %d\n", count); */
3751 /*-----------------------------------------------------------------*/
3752 /* genPlusIncr :- does addition with increment if possible */
3753 /*-----------------------------------------------------------------*/
3755 genPlusIncr (iCode * ic)
3757 unsigned int icount;
3758 unsigned int size = getDataSize (IC_RESULT (ic));
3760 /* will try to generate an increment */
3761 /* if the right side is not a literal
3763 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3766 /* if the literal value of the right hand side
3767 is greater than 4 then it is not worth it */
3768 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3771 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3772 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3774 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3778 /* if increment 16 bits in register */
3780 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3781 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3782 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3791 /* If the next instruction is a goto and the goto target
3792 * is <= 5 instructions previous to this, we can generate
3793 * jumps straight to that target.
3795 if (ic->next && ic->next->op == GOTO
3796 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3799 D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3800 tlbl = IC_LABEL (ic->next);
3805 tlbl = newiTempLabel (NULL);
3809 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3810 emitcode ("inc", "%s", l);
3812 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3813 IS_AOP_PREG (IC_RESULT (ic)))
3815 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3819 emitcode ("clr", "a");
3820 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3823 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
3824 emitcode ("inc", "%s", l);
3827 if (!strcmp(l, "acc"))
3829 emitcode("jnz", "!tlabel", tlbl->key + 100);
3831 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3832 IS_AOP_PREG (IC_RESULT (ic)))
3834 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3838 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3841 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3842 emitcode ("inc", "%s", l);
3846 if (!strcmp(l, "acc"))
3848 emitcode("jnz", "!tlabel", tlbl->key + 100);
3850 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3851 IS_AOP_PREG (IC_RESULT (ic)))
3853 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3857 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3860 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3861 emitcode ("inc", "%s", l); }
3865 emitcode ("", "!tlabeldef", tlbl->key + 100);
3870 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3871 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
3872 options.model == MODEL_FLAT24 ) {
3876 emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3878 emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3880 emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3883 while (icount--) emitcode ("inc","dptr");
3887 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3888 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3890 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3891 while (icount--) emitcode ("inc","dptr");
3892 emitcode ("mov","dps,#0");
3896 /* if the sizes are greater than 1 then we cannot */
3897 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3898 AOP_SIZE (IC_LEFT (ic)) > 1)
3901 /* we can if the aops of the left & result match or
3902 if they are in registers and the registers are the
3905 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3906 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3907 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3912 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3913 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3914 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3919 _startLazyDPSEvaluation ();
3922 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3924 _endLazyDPSEvaluation ();
3933 /*-----------------------------------------------------------------*/
3934 /* outBitAcc - output a bit in acc */
3935 /*-----------------------------------------------------------------*/
3937 outBitAcc (operand * result)
3939 symbol *tlbl = newiTempLabel (NULL);
3940 /* if the result is a bit */
3941 if (AOP_TYPE (result) == AOP_CRY)
3943 aopPut (AOP (result), "a", 0);
3947 emitcode ("jz", "!tlabel", tlbl->key + 100);
3948 emitcode ("mov", "a,%s", one);
3949 emitcode ("", "!tlabeldef", tlbl->key + 100);
3954 /*-----------------------------------------------------------------*/
3955 /* genPlusBits - generates code for addition of two bits */
3956 /*-----------------------------------------------------------------*/
3958 genPlusBits (iCode * ic)
3960 D (emitcode (";", "genPlusBits "););
3962 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3964 symbol *lbl = newiTempLabel (NULL);
3965 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3966 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3967 emitcode ("cpl", "c");
3968 emitcode ("", "!tlabeldef", (lbl->key + 100));
3969 outBitC (IC_RESULT (ic));
3973 emitcode ("clr", "a");
3974 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3975 emitcode ("rlc", "a");
3976 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3977 emitcode ("addc", "a,#0");
3978 outAcc (IC_RESULT (ic));
3983 adjustArithmeticResult (iCode * ic)
3985 if (opIsGptr (IC_RESULT (ic)) &&
3986 opIsGptr (IC_LEFT (ic)) &&
3987 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3989 aopPut (AOP (IC_RESULT (ic)),
3990 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3994 if (opIsGptr (IC_RESULT (ic)) &&
3995 opIsGptr (IC_RIGHT (ic)) &&
3996 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3998 aopPut (AOP (IC_RESULT (ic)),
3999 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
4003 if (opIsGptr (IC_RESULT (ic)) &&
4004 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4005 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4006 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4007 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4010 SNPRINTF (buff, sizeof(buff),
4011 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
4012 aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
4016 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
4017 // generates the result if possible. If result is generated, returns TRUE; otherwise
4018 // returns false and caller must deal with fact that result isn't aopOp'd.
4019 bool aopOp3(iCode * ic)
4021 bool dp1InUse, dp2InUse;
4024 // First, generate the right opcode. DPTR may be used if neither left nor result are
4027 // D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
4028 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
4029 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
4030 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
4032 // D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
4033 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
4034 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
4035 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
4038 // Right uses DPTR unless left or result is an AOP_STR; however,
4039 // if right is an AOP_STR, it must use DPTR regardless.
4040 if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
4041 && !AOP_IS_STR(IC_RIGHT(ic)))
4050 aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
4052 // if the right used DPTR, left MUST use DPTR2.
4053 // if the right used DPTR2, left MUST use DPTR.
4054 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
4055 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
4056 // enabling us to assign DPTR to result.
4058 if (AOP_USESDPTR(IC_RIGHT(ic)))
4062 else if (AOP_USESDPTR2(IC_RIGHT(ic)))
4068 if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
4078 aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
4081 // We've op'd the left & right. So, if left or right are the same operand as result,
4082 // we know aopOp will succeed, and we can just do it & bail.
4083 if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))
4085 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4088 if (isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
4090 // D(emitcode(";", "aopOp3: (left | right) & result equal"););
4091 aopOp(IC_RESULT(ic),ic,TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4095 // Operands may be equivalent (but not equal) if they share a spill location. If
4096 // so, use the same DPTR or DPTR2.
4097 if (operandsEqu (IC_LEFT(ic), IC_RESULT(ic)))
4099 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4102 if (operandsEqu (IC_RIGHT(ic), IC_RESULT(ic)))
4104 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4108 // Note which dptrs are currently in use.
4109 dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
4110 dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
4112 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
4114 if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
4119 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
4120 if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
4125 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
4126 if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
4131 aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
4133 // Some sanity checking...
4134 if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
4137 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
4138 __FILE__, __LINE__, ic->filename, ic->lineno);
4139 emitcode(";", ">>> unexpected DPTR here.");
4142 if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
4145 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
4146 __FILE__, __LINE__, ic->filename, ic->lineno);
4147 emitcode(";", ">>> unexpected DPTR2 here.");
4153 // Macro to aopOp all three operands of an ic. If this cannot be done,
4154 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
4155 // will be set TRUE. The caller must then handle the case specially, noting
4156 // that the IC_RESULT operand is not aopOp'd.
4158 #define AOP_OP_3_NOFATAL(ic, rc) \
4159 do { rc = !aopOp3(ic); } while (0)
4161 // aopOp the left & right operands of an ic.
4162 #define AOP_OP_2(ic) \
4163 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
4164 aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
4166 // convienience macro.
4167 #define AOP_SET_LOCALS(ic) \
4168 left = IC_LEFT(ic); \
4169 right = IC_RIGHT(ic); \
4170 result = IC_RESULT(ic);
4173 // Given an integer value of pushedSize bytes on the stack,
4174 // adjust it to be resultSize bytes, either by discarding
4175 // the most significant bytes or by zero-padding.
4177 // On exit from this macro, pushedSize will have been adjusted to
4178 // equal resultSize, and ACC may be trashed.
4179 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
4180 /* If the pushed data is bigger than the result, \
4181 * simply discard unused bytes. Icky, but works. \
4183 while (pushedSize > resultSize) \
4185 D (emitcode (";", "discarding unused result byte."););\
4186 emitcode ("pop", "acc"); \
4189 if (pushedSize < resultSize) \
4191 emitcode ("clr", "a"); \
4192 /* Conversly, we haven't pushed enough here. \
4193 * just zero-pad, and all is well. \
4195 while (pushedSize < resultSize) \
4197 emitcode("push", "acc"); \
4201 assert(pushedSize == resultSize);
4203 /*-----------------------------------------------------------------*/
4204 /* genPlus - generates code for addition */
4205 /*-----------------------------------------------------------------*/
4207 genPlus (iCode * ic)
4209 int size, offset = 0;
4213 D (emitcode (";", "genPlus "););
4215 /* special cases :- */
4216 if ( AOP_IS_STR(IC_LEFT(ic)) &&
4217 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4218 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4219 size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4221 while (size--) emitcode ("inc","dptr");
4223 emitcode ("mov","a,dpl");
4224 emitcode ("add","a,#!constbyte",size & 0xff);
4225 emitcode ("mov","dpl,a");
4226 emitcode ("mov","a,dph");
4227 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4228 emitcode ("mov","dph,a");
4229 emitcode ("mov","a,dpx");
4230 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4231 emitcode ("mov","dpx,a");
4233 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4236 if ( IS_SYMOP(IC_LEFT(ic)) &&
4237 OP_SYMBOL(IC_LEFT(ic))->remat &&
4238 isOperandInFarSpace(IC_RIGHT(ic))) {
4239 operand *op = IC_RIGHT(ic);
4240 IC_RIGHT(ic) = IC_LEFT(ic);
4244 AOP_OP_3_NOFATAL (ic, pushResult);
4248 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4253 /* if literal, literal on the right or
4254 if left requires ACC or right is already
4256 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4257 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4258 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4260 operand *t = IC_RIGHT (ic);
4261 IC_RIGHT (ic) = IC_LEFT (ic);
4263 emitcode (";", "Swapped plus args.");
4266 /* if both left & right are in bit
4268 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4269 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4275 /* if left in bit space & right literal */
4276 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4277 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4279 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4280 /* if result in bit space */
4281 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4283 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4284 emitcode ("cpl", "c");
4285 outBitC (IC_RESULT (ic));
4289 size = getDataSize (IC_RESULT (ic));
4290 _startLazyDPSEvaluation ();
4293 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4294 emitcode ("addc", "a,#0");
4295 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4297 _endLazyDPSEvaluation ();
4302 /* if I can do an increment instead
4303 of add then GOOD for ME */
4304 if (genPlusIncr (ic) == TRUE)
4306 emitcode (";", "did genPlusIncr");
4311 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4313 _startLazyDPSEvaluation ();
4316 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4318 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4320 emitcode ("add", "a,%s",
4321 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4323 emitcode ("addc", "a,%s",
4324 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4328 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4330 /* right is going to use ACC or we would have taken the
4333 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4335 D(emitcode(";", "+ AOP_ACC special case."););
4336 emitcode("xch", "a, %s", DP2_RESULT_REG);
4338 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4341 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4344 emitcode("add", "a, %s", DP2_RESULT_REG);
4348 emitcode ("add", "a,%s",
4349 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4355 emitcode ("addc", "a,%s",
4356 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4362 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4366 emitcode ("push", "acc");
4370 _endLazyDPSEvaluation ();
4374 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4376 size = getDataSize (IC_LEFT (ic));
4377 rSize = getDataSize (IC_RESULT (ic));
4379 ADJUST_PUSHED_RESULT(size, rSize);
4381 _startLazyDPSEvaluation ();
4384 emitcode ("pop", "acc");
4385 aopPut (AOP (IC_RESULT (ic)), "a", size);
4387 _endLazyDPSEvaluation ();
4390 adjustArithmeticResult (ic);
4393 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4394 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4395 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4398 /*-----------------------------------------------------------------*/
4399 /* genMinusDec :- does subtraction with deccrement if possible */
4400 /*-----------------------------------------------------------------*/
4402 genMinusDec (iCode * ic)
4404 unsigned int icount;
4405 unsigned int size = getDataSize (IC_RESULT (ic));
4407 /* will try to generate an increment */
4408 /* if the right side is not a literal
4410 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4413 /* if the literal value of the right hand side
4414 is greater than 4 then it is not worth it */
4415 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4418 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4419 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4421 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4425 /* if decrement 16 bits in register */
4426 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4427 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4428 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4437 /* If the next instruction is a goto and the goto target
4438 * is <= 5 instructions previous to this, we can generate
4439 * jumps straight to that target.
4441 if (ic->next && ic->next->op == GOTO
4442 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4445 emitcode (";", "tail decrement optimized (range %d)", labelRange);
4446 tlbl = IC_LABEL (ic->next);
4451 tlbl = newiTempLabel (NULL);
4455 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4456 emitcode ("dec", "%s", l);
4458 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)), MSB16, FALSE, FALSE, NULL);
4470 emitcode ("dec", "%s", l);
4473 if (!strcmp(l, "acc"))
4475 emitcode("jnz", "!tlabel", tlbl->key + 100);
4477 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4478 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4479 IS_AOP_PREG (IC_RESULT (ic)))
4481 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4485 emitcode ("mov", "a,#!constbyte",0xff);
4486 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4488 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4489 emitcode ("dec", "%s", l);
4493 if (!strcmp(l, "acc"))
4495 emitcode("jnz", "!tlabel", tlbl->key + 100);
4497 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4498 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4499 IS_AOP_PREG (IC_RESULT (ic)))
4501 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4505 emitcode ("mov", "a,#!constbyte",0xff);
4506 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4508 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4509 emitcode ("dec", "%s", l);
4513 emitcode ("", "!tlabeldef", tlbl->key + 100);
4518 /* if the sizes are greater than 1 then we cannot */
4519 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4520 AOP_SIZE (IC_LEFT (ic)) > 1)
4523 /* we can if the aops of the left & result match or
4524 if they are in registers and the registers are the
4527 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4528 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4529 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4532 _startLazyDPSEvaluation ();
4535 emitcode ("dec", "%s",
4536 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4538 _endLazyDPSEvaluation ();
4546 /*-----------------------------------------------------------------*/
4547 /* addSign - complete with sign */
4548 /*-----------------------------------------------------------------*/
4550 addSign (operand * result, int offset, int sign)
4552 int size = (getDataSize (result) - offset);
4555 _startLazyDPSEvaluation();
4558 emitcode ("rlc", "a");
4559 emitcode ("subb", "a,acc");
4562 aopPut (AOP (result), "a", offset++);
4569 aopPut (AOP (result), zero, offset++);
4572 _endLazyDPSEvaluation();
4576 /*-----------------------------------------------------------------*/
4577 /* genMinusBits - generates code for subtraction of two bits */
4578 /*-----------------------------------------------------------------*/
4580 genMinusBits (iCode * ic)
4582 symbol *lbl = newiTempLabel (NULL);
4584 D (emitcode (";", "genMinusBits "););
4586 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4588 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4589 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4590 emitcode ("cpl", "c");
4591 emitcode ("", "!tlabeldef", (lbl->key + 100));
4592 outBitC (IC_RESULT (ic));
4596 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4597 emitcode ("subb", "a,acc");
4598 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4599 emitcode ("inc", "a");
4600 emitcode ("", "!tlabeldef", (lbl->key + 100));
4601 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4602 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4606 /*-----------------------------------------------------------------*/
4607 /* genMinus - generates code for subtraction */
4608 /*-----------------------------------------------------------------*/
4610 genMinus (iCode * ic)
4612 int size, offset = 0;
4617 D (emitcode (";", "genMinus "););
4619 AOP_OP_3_NOFATAL(ic, pushResult);
4623 /* special cases :- */
4624 /* if both left & right are in bit space */
4625 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4626 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4632 /* if I can do an decrement instead
4633 of subtract then GOOD for ME */
4634 if (genMinusDec (ic) == TRUE)
4639 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4641 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4647 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4652 /* if literal, add a,#-lit, else normal subb */
4653 _startLazyDPSEvaluation ();
4655 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4656 if (AOP_USESDPTR(IC_RIGHT(ic))) {
4657 emitcode ("mov","b,%s",
4658 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4659 MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4660 emitcode ("subb","a,b");
4662 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4663 emitcode ("subb", "a,%s",
4664 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE,
4668 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4669 /* first add without previous c */
4671 if (!size && lit==-1) {
4672 emitcode ("dec", "a");
4674 emitcode ("add", "a,#!constbyte",
4675 (unsigned int) (lit & 0x0FFL));
4678 emitcode ("addc", "a,#!constbyte",
4679 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4684 emitcode ("push", "acc");
4686 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4690 _endLazyDPSEvaluation ();
4694 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4696 size = getDataSize (IC_LEFT (ic));
4697 rSize = getDataSize (IC_RESULT (ic));
4699 ADJUST_PUSHED_RESULT(size, rSize);
4701 _startLazyDPSEvaluation ();
4704 emitcode ("pop", "acc");
4705 aopPut (AOP (IC_RESULT (ic)), "a", size);
4707 _endLazyDPSEvaluation ();
4710 adjustArithmeticResult (ic);
4713 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4714 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4715 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4719 /*-----------------------------------------------------------------*/
4720 /* genMultbits :- multiplication of bits */
4721 /*-----------------------------------------------------------------*/
4723 genMultbits (operand * left,
4728 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4729 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4730 aopOp(result, ic, TRUE, FALSE);
4735 /*-----------------------------------------------------------------*/
4736 /* genMultOneByte : 8*8=8/16 bit multiplication */
4737 /*-----------------------------------------------------------------*/
4739 genMultOneByte (operand * left,
4746 bool runtimeSign, compiletimeSign;
4747 bool lUnsigned, rUnsigned;
4750 /* (if two literals: the value is computed before) */
4751 /* if one literal, literal on the right */
4752 if (AOP_TYPE (left) == AOP_LIT)
4757 emitcode (";", "swapped left and right");
4760 /* (if two literals: the value is computed before) */
4761 /* if one literal, literal on the right */
4762 if (AOP_TYPE (left) == AOP_LIT)
4767 /* emitcode (";", "swapped left and right"); */
4769 /* if no literal, unsigned on the right: shorter code */
4770 if ( AOP_TYPE (right) != AOP_LIT
4771 && SPEC_USIGN (getSpec (operandType (left))))
4778 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4779 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4781 if ((lUnsigned && rUnsigned)
4782 /* sorry, I don't know how to get size
4783 without calling aopOp (result,...);
4784 see Feature Request */
4785 /* || size == 1 */ ) /* no, this is not a bug; with a 1 byte result there's
4786 no need to take care about the signedness! */
4788 /* just an unsigned 8 * 8 = 8 multiply
4790 /* emitcode (";","unsigned"); */
4791 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4792 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4793 emitcode ("mul", "ab");
4795 _G.accInUse++; _G.bInUse++;
4796 aopOp (result, ic, TRUE, FALSE);
4797 size = AOP_SIZE (result);
4799 if (size < 1 || size > 2)
4801 /* this should never happen */
4802 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4803 size, __FILE__, lineno);
4807 aopPut (AOP (result), "a", 0);
4808 _G.accInUse--; _G.bInUse--;
4810 aopPut (AOP (result), "b", 1);
4814 /* we have to do a signed multiply */
4815 /* emitcode (";", "signed"); */
4817 /* now sign adjust for both left & right */
4819 /* let's see what's needed: */
4820 /* apply negative sign during runtime */
4821 runtimeSign = FALSE;
4822 /* negative sign from literals */
4823 compiletimeSign = FALSE;
4827 if (AOP_TYPE(left) == AOP_LIT)
4829 /* signed literal */
4830 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4832 compiletimeSign = TRUE;
4835 /* signed but not literal */
4841 if (AOP_TYPE(right) == AOP_LIT)
4843 /* signed literal */
4844 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4846 compiletimeSign ^= TRUE;
4849 /* signed but not literal */
4853 /* initialize F0, which stores the runtime sign */
4856 if (compiletimeSign)
4857 emitcode ("setb", "F0"); /* set sign flag */
4859 emitcode ("clr", "F0"); /* reset sign flag */
4862 /* save the signs of the operands */
4863 if (AOP_TYPE(right) == AOP_LIT)
4865 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4867 if (!rUnsigned && val < 0)
4868 emitcode ("mov", "b,#!constbyte", -val);
4870 emitcode ("mov", "b,#!constbyte", (unsigned char) val);
4872 else /* ! literal */
4874 if (rUnsigned) /* emitcode (";", "signed"); */
4875 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4878 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4879 lbl = newiTempLabel (NULL);
4880 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
4881 emitcode ("cpl", "F0"); /* complement sign flag */
4882 emitcode ("cpl", "a"); /* 2's complement */
4883 emitcode ("inc", "a");
4884 emitcode ("", "!tlabeldef", lbl->key + 100);
4885 emitcode ("mov", "b,a");
4889 if (AOP_TYPE(left) == AOP_LIT)
4891 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4893 if (!lUnsigned && val < 0)
4894 emitcode ("mov", "a,#!constbyte", -val);
4896 emitcode ("mov", "a,#!constbyte", (unsigned char) val);
4898 else /* ! literal */
4900 if (lUnsigned) /* emitcode (";", "signed"); */
4902 emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4905 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4906 lbl = newiTempLabel (NULL);
4907 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
4908 emitcode ("cpl", "F0"); /* complement sign flag */
4909 emitcode ("cpl", "a"); /* 2's complement */
4910 emitcode ("inc", "a");
4911 emitcode ("", "!tlabeldef", lbl->key + 100);
4915 /* now the multiplication */
4916 emitcode ("mul", "ab");
4917 _G.accInUse++;_G.bInUse++;
4918 aopOp(result, ic, TRUE, FALSE);
4919 size = AOP_SIZE (result);
4921 if (size < 1 || size > 2)
4923 /* this should never happen */
4924 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4925 size, __FILE__, lineno);
4929 if (runtimeSign || compiletimeSign)
4931 lbl = newiTempLabel (NULL);
4933 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
4934 emitcode ("cpl", "a"); /* lsb 2's complement */
4936 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4939 emitcode ("add", "a,#1"); /* this sets carry flag */
4940 emitcode ("xch", "a,b");
4941 emitcode ("cpl", "a"); /* msb 2's complement */
4942 emitcode ("addc", "a,#0");
4943 emitcode ("xch", "a,b");
4945 emitcode ("", "!tlabeldef", lbl->key + 100);
4947 aopPut (AOP (result), "a", 0);
4948 _G.accInUse--;_G.bInUse--;
4950 aopPut (AOP (result), "b", 1);
4953 /*-----------------------------------------------------------------*/
4954 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4955 /*-----------------------------------------------------------------*/
4956 static void genMultTwoByte (operand *left, operand *right,
4957 operand *result, iCode *ic)
4959 sym_link *retype = getSpec(operandType(right));
4960 sym_link *letype = getSpec(operandType(left));
4961 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4964 if (AOP_TYPE (left) == AOP_LIT) {
4969 /* save EA bit in F1 */
4970 lbl = newiTempLabel(NULL);
4971 emitcode ("setb","F1");
4972 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4973 emitcode ("clr","F1");
4974 emitcode("","!tlabeldef",lbl->key+100);
4976 /* load up MB with right */
4978 emitcode("clr","F0");
4979 if (AOP_TYPE(right) == AOP_LIT) {
4980 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4982 emitcode("setb","F0");
4985 emitcode ("mov","mb,#!constbyte",val & 0xff);
4986 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4988 lbl = newiTempLabel(NULL);
4989 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4990 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4991 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4992 emitcode ("xch", "a,b");
4993 emitcode ("cpl","a");
4994 emitcode ("add", "a,#1");
4995 emitcode ("xch", "a,b");
4996 emitcode ("cpl", "a"); // msb
4997 emitcode ("addc", "a,#0");
4998 emitcode ("setb","F0");
4999 emitcode ("","!tlabeldef",lbl->key+100);
5000 emitcode ("mov","mb,b");
5001 emitcode ("mov","mb,a");
5004 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5005 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5007 /* load up MA with left */
5009 lbl = newiTempLabel(NULL);
5010 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5011 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5012 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5013 emitcode ("xch", "a,b");
5014 emitcode ("cpl","a");
5015 emitcode ("add", "a,#1");
5016 emitcode ("xch", "a,b");
5017 emitcode ("cpl", "a"); // msb
5018 emitcode ("addc","a,#0");
5019 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5020 emitcode ("setb","F0");
5021 emitcode ("","!tlabeldef",lbl->key+100);
5022 emitcode ("mov","ma,b");
5023 emitcode ("mov","ma,a");
5025 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5026 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5028 /* wait for multiplication to finish */
5029 lbl = newiTempLabel(NULL);
5030 emitcode("","!tlabeldef", lbl->key+100);
5031 emitcode("mov","a,mcnt1");
5032 emitcode("anl","a,#!constbyte",0x80);
5033 emitcode("jnz","!tlabel",lbl->key+100);
5035 freeAsmop (left, NULL, ic, TRUE);
5036 freeAsmop (right, NULL, ic,TRUE);
5037 aopOp(result, ic, TRUE, FALSE);
5039 /* if unsigned then simple */
5041 emitcode ("mov","a,ma");
5042 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
5043 emitcode ("mov","a,ma");
5044 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
5045 aopPut(AOP(result),"ma",1);
5046 aopPut(AOP(result),"ma",0);
5048 emitcode("push","ma");
5049 emitcode("push","ma");
5050 emitcode("push","ma");
5052 /* negate result if needed */
5053 lbl = newiTempLabel(NULL);
5054 emitcode("jnb","F0,!tlabel",lbl->key+100);
5055 emitcode("cpl","a");
5056 emitcode("add","a,#1");
5057 emitcode("","!tlabeldef", lbl->key+100);
5058 if (AOP_TYPE(result) == AOP_ACC)
5060 D(emitcode(";", "ACC special case."););
5061 /* We know result is the only live aop, and
5062 * it's obviously not a DPTR2, so AP is available.
5064 emitcode("mov", "%s,acc", DP2_RESULT_REG);
5068 aopPut(AOP(result),"a",0);
5071 emitcode("pop","acc");
5072 lbl = newiTempLabel(NULL);
5073 emitcode("jnb","F0,!tlabel",lbl->key+100);
5074 emitcode("cpl","a");
5075 emitcode("addc","a,#0");
5076 emitcode("","!tlabeldef", lbl->key+100);
5077 aopPut(AOP(result),"a",1);
5078 emitcode("pop","acc");
5079 if (AOP_SIZE(result) >= 3) {
5080 lbl = newiTempLabel(NULL);
5081 emitcode("jnb","F0,!tlabel",lbl->key+100);
5082 emitcode("cpl","a");
5083 emitcode("addc","a,#0");
5084 emitcode("","!tlabeldef", lbl->key+100);
5085 aopPut(AOP(result),"a",2);
5087 emitcode("pop","acc");
5088 if (AOP_SIZE(result) >= 4) {
5089 lbl = newiTempLabel(NULL);
5090 emitcode("jnb","F0,!tlabel",lbl->key+100);
5091 emitcode("cpl","a");
5092 emitcode("addc","a,#0");
5093 emitcode("","!tlabeldef", lbl->key+100);
5094 aopPut(AOP(result),"a",3);
5096 if (AOP_TYPE(result) == AOP_ACC)
5098 /* We stashed the result away above. */
5099 emitcode("mov", "acc,%s", DP2_RESULT_REG);
5103 freeAsmop (result, NULL, ic, TRUE);
5105 /* restore EA bit in F1 */
5106 lbl = newiTempLabel(NULL);
5107 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5108 emitcode ("setb","EA");
5109 emitcode("","!tlabeldef",lbl->key+100);
5113 /*-----------------------------------------------------------------*/
5114 /* genMult - generates code for multiplication */
5115 /*-----------------------------------------------------------------*/
5117 genMult (iCode * ic)
5119 operand *left = IC_LEFT (ic);
5120 operand *right = IC_RIGHT (ic);
5121 operand *result = IC_RESULT (ic);
5123 D (emitcode (";", "genMult "););
5125 /* assign the amsops */
5128 /* special cases first */
5130 if (AOP_TYPE (left) == AOP_CRY &&
5131 AOP_TYPE (right) == AOP_CRY)
5133 genMultbits (left, right, result, ic);
5137 /* if both are of size == 1 */
5138 if (AOP_SIZE (left) == 1 &&
5139 AOP_SIZE (right) == 1)
5141 genMultOneByte (left, right, result, ic);
5145 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5146 /* use the ds390 ARITHMETIC accel UNIT */
5147 genMultTwoByte (left, right, result, ic);
5150 /* should have been converted to function call */
5154 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5155 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5156 freeAsmop (result, NULL, ic, TRUE);
5159 /*-----------------------------------------------------------------*/
5160 /* genDivbits :- division of bits */
5161 /*-----------------------------------------------------------------*/
5163 genDivbits (operand * left,
5171 /* the result must be bit */
5172 LOAD_AB_FOR_DIV (left, right, l);
5173 emitcode ("div", "ab");
5174 emitcode ("rrc", "a");
5175 aopOp(result, ic, TRUE, FALSE);
5177 aopPut (AOP (result), "c", 0);
5180 /*-----------------------------------------------------------------*/
5181 /* genDivOneByte : 8 bit division */
5182 /*-----------------------------------------------------------------*/
5184 genDivOneByte (operand * left,
5189 bool lUnsigned, rUnsigned;
5190 bool runtimeSign, compiletimeSign;
5196 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5197 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5199 /* signed or unsigned */
5200 if (lUnsigned && rUnsigned)
5202 /* unsigned is easy */
5203 LOAD_AB_FOR_DIV (left, right, l);
5204 emitcode ("div", "ab");
5207 aopOp (result, ic, TRUE, FALSE);
5208 aopPut (AOP (result), "a", 0);
5211 size = AOP_SIZE (result) - 1;
5214 aopPut (AOP (result), zero, offset++);
5218 /* signed is a little bit more difficult */
5220 /* now sign adjust for both left & right */
5222 /* let's see what's needed: */
5223 /* apply negative sign during runtime */
5224 runtimeSign = FALSE;
5225 /* negative sign from literals */
5226 compiletimeSign = FALSE;
5230 if (AOP_TYPE(left) == AOP_LIT)
5232 /* signed literal */
5233 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5235 compiletimeSign = TRUE;
5238 /* signed but not literal */
5244 if (AOP_TYPE(right) == AOP_LIT)
5246 /* signed literal */
5247 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5249 compiletimeSign ^= TRUE;
5252 /* signed but not literal */
5256 /* initialize F0, which stores the runtime sign */
5259 if (compiletimeSign)
5260 emitcode ("setb", "F0"); /* set sign flag */
5262 emitcode ("clr", "F0"); /* reset sign flag */
5265 /* save the signs of the operands */
5266 if (AOP_TYPE(right) == AOP_LIT)
5268 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5270 if (!rUnsigned && val < 0)
5271 emitcode ("mov", "b,#0x%02x", -val);
5273 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5275 else /* ! literal */
5278 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5281 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5282 lbl = newiTempLabel (NULL);
5283 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5284 emitcode ("cpl", "F0"); /* complement sign flag */
5285 emitcode ("cpl", "a"); /* 2's complement */
5286 emitcode ("inc", "a");
5287 emitcode ("", "!tlabeldef", lbl->key + 100);
5288 emitcode ("mov", "b,a");
5292 if (AOP_TYPE(left) == AOP_LIT)
5294 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5296 if (!lUnsigned && val < 0)
5297 emitcode ("mov", "a,#0x%02x", -val);
5299 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5301 else /* ! literal */
5304 emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5307 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5308 lbl = newiTempLabel (NULL);
5309 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5310 emitcode ("cpl", "F0"); /* complement sign flag */
5311 emitcode ("cpl", "a"); /* 2's complement */
5312 emitcode ("inc", "a");
5313 emitcode ("", "!tlabeldef", lbl->key + 100);
5317 /* now the division */
5318 emitcode ("nop", "; workaround for DS80C390 div bug.");
5319 emitcode ("div", "ab");
5321 if (runtimeSign || compiletimeSign)
5323 lbl = newiTempLabel (NULL);
5325 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5326 emitcode ("cpl", "a"); /* lsb 2's complement */
5327 emitcode ("inc", "a");
5328 emitcode ("", "!tlabeldef", lbl->key + 100);
5330 _G.accInUse++; _G.bInUse++;
5331 aopOp (result, ic, TRUE, FALSE);
5332 size = AOP_SIZE (result) - 1;
5336 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5337 then the result will be in b, a */
5338 emitcode ("mov", "b,a"); /* 1 */
5339 /* msb is 0x00 or 0xff depending on the sign */
5342 emitcode ("mov", "c,F0");
5343 emitcode ("subb", "a,acc");
5344 emitcode ("xch", "a,b"); /* 2 */
5346 aopPut (AOP (result), "b", offset++); /* write msb's */
5348 else /* compiletimeSign */
5350 aopPut (AOP (result), "#0xff", offset++); /* write msb's */
5352 aopPut (AOP (result), "a", 0); /* 3: write lsb */
5356 _G.accInUse++; _G.bInUse++;
5357 aopOp(result, ic, TRUE, FALSE);
5358 size = AOP_SIZE (result) - 1;
5360 aopPut (AOP (result), "a", 0);
5362 aopPut (AOP (result), zero, offset++);
5364 _G.accInUse--; _G.bInUse--;
5368 /*-----------------------------------------------------------------*/
5369 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
5370 /*-----------------------------------------------------------------*/
5371 static void genDivTwoByte (operand *left, operand *right,
5372 operand *result, iCode *ic)
5374 sym_link *retype = getSpec(operandType(right));
5375 sym_link *letype = getSpec(operandType(left));
5376 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5379 /* save EA bit in F1 */
5380 lbl = newiTempLabel(NULL);
5381 emitcode ("setb","F1");
5382 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5383 emitcode ("clr","F1");
5384 emitcode("","!tlabeldef",lbl->key+100);
5386 /* load up MA with left */
5388 emitcode("clr","F0");
5389 lbl = newiTempLabel(NULL);
5390 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5391 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5392 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5393 emitcode ("xch", "a,b");
5394 emitcode ("cpl","a");
5395 emitcode ("add", "a,#1");
5396 emitcode ("xch", "a,b");
5397 emitcode ("cpl", "a"); // msb
5398 emitcode ("addc","a,#0");
5399 emitcode ("setb","F0");
5400 emitcode ("","!tlabeldef",lbl->key+100);
5401 emitcode ("mov","ma,b");
5402 emitcode ("mov","ma,a");
5404 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5405 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5408 /* load up MB with right */
5410 if (AOP_TYPE(right) == AOP_LIT) {
5411 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5413 lbl = newiTempLabel(NULL);
5414 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5415 emitcode("setb","F0");
5416 emitcode ("","!tlabeldef",lbl->key+100);
5419 emitcode ("mov","mb,#!constbyte",val & 0xff);
5420 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5422 lbl = newiTempLabel(NULL);
5423 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5424 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5425 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5426 emitcode ("xch", "a,b");
5427 emitcode ("cpl","a");
5428 emitcode ("add", "a,#1");
5429 emitcode ("xch", "a,b");
5430 emitcode ("cpl", "a"); // msb
5431 emitcode ("addc", "a,#0");
5432 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5433 emitcode ("setb","F0");
5434 emitcode ("","!tlabeldef",lbl->key+100);
5435 emitcode ("mov","mb,b");
5436 emitcode ("mov","mb,a");
5439 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5440 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5443 /* wait for multiplication to finish */
5444 lbl = newiTempLabel(NULL);
5445 emitcode("","!tlabeldef", lbl->key+100);
5446 emitcode("mov","a,mcnt1");
5447 emitcode("anl","a,#!constbyte",0x80);
5448 emitcode("jnz","!tlabel",lbl->key+100);
5450 freeAsmop (left, NULL, ic, TRUE);
5451 freeAsmop (right, NULL, ic,TRUE);
5452 aopOp(result, ic, TRUE, FALSE);
5454 /* if unsigned then simple */
5456 aopPut(AOP(result),"ma",1);
5457 aopPut(AOP(result),"ma",0);
5459 emitcode("push","ma");
5461 /* negate result if needed */
5462 lbl = newiTempLabel(NULL);
5463 emitcode("jnb","F0,!tlabel",lbl->key+100);
5464 emitcode("cpl","a");
5465 emitcode("add","a,#1");
5466 emitcode("","!tlabeldef", lbl->key+100);
5467 aopPut(AOP(result),"a",0);
5468 emitcode("pop","acc");
5469 lbl = newiTempLabel(NULL);
5470 emitcode("jnb","F0,!tlabel",lbl->key+100);
5471 emitcode("cpl","a");
5472 emitcode("addc","a,#0");
5473 emitcode("","!tlabeldef", lbl->key+100);
5474 aopPut(AOP(result),"a",1);
5476 freeAsmop (result, NULL, ic, TRUE);
5477 /* restore EA bit in F1 */
5478 lbl = newiTempLabel(NULL);
5479 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5480 emitcode ("setb","EA");
5481 emitcode("","!tlabeldef",lbl->key+100);
5485 /*-----------------------------------------------------------------*/
5486 /* genDiv - generates code for division */
5487 /*-----------------------------------------------------------------*/
5491 operand *left = IC_LEFT (ic);
5492 operand *right = IC_RIGHT (ic);
5493 operand *result = IC_RESULT (ic);
5495 D (emitcode (";", "genDiv "););
5497 /* assign the amsops */
5500 /* special cases first */
5502 if (AOP_TYPE (left) == AOP_CRY &&
5503 AOP_TYPE (right) == AOP_CRY)
5505 genDivbits (left, right, result, ic);
5509 /* if both are of size == 1 */
5510 if (AOP_SIZE (left) == 1 &&
5511 AOP_SIZE (right) == 1)
5513 genDivOneByte (left, right, result, ic);
5517 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5518 /* use the ds390 ARITHMETIC accel UNIT */
5519 genDivTwoByte (left, right, result, ic);
5522 /* should have been converted to function call */
5525 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5526 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5527 freeAsmop (result, NULL, ic, TRUE);
5530 /*-----------------------------------------------------------------*/
5531 /* genModbits :- modulus of bits */
5532 /*-----------------------------------------------------------------*/
5534 genModbits (operand * left,
5542 /* the result must be bit */
5543 LOAD_AB_FOR_DIV (left, right, l);
5544 emitcode ("div", "ab");
5545 emitcode ("mov", "a,b");
5546 emitcode ("rrc", "a");
5547 aopOp(result, ic, TRUE, FALSE);
5548 aopPut (AOP (result), "c", 0);
5551 /*-----------------------------------------------------------------*/
5552 /* genModOneByte : 8 bit modulus */
5553 /*-----------------------------------------------------------------*/
5555 genModOneByte (operand * left,
5560 bool lUnsigned, rUnsigned;
5561 bool runtimeSign, compiletimeSign;
5567 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5568 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5570 /* signed or unsigned */
5571 if (lUnsigned && rUnsigned)
5573 /* unsigned is easy */
5574 LOAD_AB_FOR_DIV (left, right, l);
5575 emitcode ("div", "ab");
5576 aopOp (result, ic, TRUE, FALSE);
5577 aopPut (AOP (result), "b", 0);
5579 for (size = AOP_SIZE (result) - 1; size--;)
5580 aopPut (AOP (result), zero, offset++);
5584 /* signed is a little bit more difficult */
5586 /* now sign adjust for both left & right */
5588 /* modulus: sign of the right operand has no influence on the result! */
5589 if (AOP_TYPE(right) == AOP_LIT)
5591 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5593 if (!rUnsigned && val < 0)
5594 emitcode ("mov", "b,#0x%02x", -val);
5596 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5598 else /* ! literal */
5601 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5604 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5605 lbl = newiTempLabel (NULL);
5606 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5607 emitcode ("cpl", "a"); /* 2's complement */
5608 emitcode ("inc", "a");
5609 emitcode ("", "!tlabeldef", lbl->key + 100);
5610 emitcode ("mov", "b,a");
5614 /* let's see what's needed: */
5615 /* apply negative sign during runtime */
5616 runtimeSign = FALSE;
5617 /* negative sign from literals */
5618 compiletimeSign = FALSE;
5620 /* sign adjust left side */
5621 if (AOP_TYPE(left) == AOP_LIT)
5623 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5625 if (!lUnsigned && val < 0)
5627 compiletimeSign = TRUE; /* set sign flag */
5628 emitcode ("mov", "a,#0x%02x", -val);
5631 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5633 else /* ! literal */
5635 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5640 emitcode ("clr", "F0"); /* clear sign flag */
5642 lbl = newiTempLabel (NULL);
5643 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5644 emitcode ("setb", "F0"); /* set sign flag */
5645 emitcode ("cpl", "a"); /* 2's complement */
5646 emitcode ("inc", "a");
5647 emitcode ("", "!tlabeldef", lbl->key + 100);
5651 /* now the modulus */
5652 emitcode ("nop", "; workaround for DS80C390 div bug.");
5653 emitcode ("div", "ab");
5655 if (runtimeSign || compiletimeSign)
5657 emitcode ("mov", "a,b");
5658 lbl = newiTempLabel (NULL);
5660 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5661 emitcode ("cpl", "a"); /* lsb 2's complement */
5662 emitcode ("inc", "a");
5663 emitcode ("", "!tlabeldef", lbl->key + 100);
5665 _G.accInUse++; _G.bInUse++;
5666 aopOp (result, ic, TRUE, FALSE);
5667 size = AOP_SIZE (result) - 1;
5671 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5672 then the result will be in b, a */
5673 emitcode ("mov", "b,a"); /* 1 */
5674 /* msb is 0x00 or 0xff depending on the sign */
5677 emitcode ("mov", "c,F0");
5678 emitcode ("subb", "a,acc");
5679 emitcode ("xch", "a,b"); /* 2 */
5681 aopPut (AOP (result), "b", offset++); /* write msb's */
5683 else /* compiletimeSign */
5685 aopPut (AOP (result), "#0xff", offset++); /* write msb's */
5687 aopPut (AOP (result), "a", 0); /* 3: write lsb */
5691 _G.accInUse++; _G.bInUse++;
5692 aopOp(result, ic, TRUE, FALSE);
5693 size = AOP_SIZE (result) - 1;
5695 aopPut (AOP (result), "b", 0);
5697 aopPut (AOP (result), zero, offset++);
5699 _G.accInUse--; _G.bInUse--;
5703 /*-----------------------------------------------------------------*/
5704 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
5705 /*-----------------------------------------------------------------*/
5706 static void genModTwoByte (operand *left, operand *right,
5707 operand *result, iCode *ic)
5709 sym_link *retype = getSpec(operandType(right));
5710 sym_link *letype = getSpec(operandType(left));
5711 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5714 /* load up MA with left */
5715 /* save EA bit in F1 */
5716 lbl = newiTempLabel(NULL);
5717 emitcode ("setb","F1");
5718 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5719 emitcode ("clr","F1");
5720 emitcode("","!tlabeldef",lbl->key+100);
5723 lbl = newiTempLabel(NULL);
5724 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5725 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5726 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5727 emitcode ("xch", "a,b");
5728 emitcode ("cpl","a");
5729 emitcode ("add", "a,#1");
5730 emitcode ("xch", "a,b");
5731 emitcode ("cpl", "a"); // msb
5732 emitcode ("addc","a,#0");
5733 emitcode ("","!tlabeldef",lbl->key+100);
5734 emitcode ("mov","ma,b");
5735 emitcode ("mov","ma,a");
5737 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5738 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5741 /* load up MB with right */
5743 if (AOP_TYPE(right) == AOP_LIT) {
5744 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5748 emitcode ("mov","mb,#!constbyte",val & 0xff);
5749 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5751 lbl = newiTempLabel(NULL);
5752 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5753 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5754 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5755 emitcode ("xch", "a,b");
5756 emitcode ("cpl","a");
5757 emitcode ("add", "a,#1");
5758 emitcode ("xch", "a,b");
5759 emitcode ("cpl", "a"); // msb
5760 emitcode ("addc", "a,#0");
5761 emitcode ("","!tlabeldef",lbl->key+100);
5762 emitcode ("mov","mb,b");
5763 emitcode ("mov","mb,a");
5766 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5767 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5770 /* wait for multiplication to finish */
5771 lbl = newiTempLabel(NULL);
5772 emitcode("","!tlabeldef", lbl->key+100);
5773 emitcode("mov","a,mcnt1");
5774 emitcode("anl","a,#!constbyte",0x80);
5775 emitcode("jnz","!tlabel",lbl->key+100);
5777 freeAsmop (left, NULL, ic, TRUE);
5778 freeAsmop (right, NULL, ic,TRUE);
5779 aopOp(result, ic, TRUE, FALSE);
5781 aopPut(AOP(result),"mb",1);
5782 aopPut(AOP(result),"mb",0);
5783 freeAsmop (result, NULL, ic, TRUE);
5785 /* restore EA bit in F1 */
5786 lbl = newiTempLabel(NULL);
5787 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5788 emitcode ("setb","EA");
5789 emitcode("","!tlabeldef",lbl->key+100);
5793 /*-----------------------------------------------------------------*/
5794 /* genMod - generates code for division */
5795 /*-----------------------------------------------------------------*/
5799 operand *left = IC_LEFT (ic);
5800 operand *right = IC_RIGHT (ic);
5801 operand *result = IC_RESULT (ic);
5803 D (emitcode (";", "genMod "); );
5805 /* assign the amsops */
5808 /* special cases first */
5810 if (AOP_TYPE (left) == AOP_CRY &&
5811 AOP_TYPE (right) == AOP_CRY)
5813 genModbits (left, right, result, ic);
5817 /* if both are of size == 1 */
5818 if (AOP_SIZE (left) == 1 &&
5819 AOP_SIZE (right) == 1)
5821 genModOneByte (left, right, result, ic);
5825 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5826 /* use the ds390 ARITHMETIC accel UNIT */
5827 genModTwoByte (left, right, result, ic);
5831 /* should have been converted to function call */
5835 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5836 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5837 freeAsmop (result, NULL, ic, TRUE);
5840 /*-----------------------------------------------------------------*/
5841 /* genIfxJump :- will create a jump depending on the ifx */
5842 /*-----------------------------------------------------------------*/
5844 genIfxJump (iCode * ic, char *jval)
5847 symbol *tlbl = newiTempLabel (NULL);
5850 D (emitcode (";", "genIfxJump"););
5852 /* if true label then we jump if condition
5856 jlbl = IC_TRUE (ic);
5857 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5858 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5862 /* false label is present */
5863 jlbl = IC_FALSE (ic);
5864 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5865 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5867 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5868 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5870 emitcode (inst, "!tlabel", tlbl->key + 100);
5871 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5872 emitcode ("", "!tlabeldef", tlbl->key + 100);
5874 /* mark the icode as generated */
5878 /*-----------------------------------------------------------------*/
5879 /* genCmp :- greater or less than comparison */
5880 /*-----------------------------------------------------------------*/
5882 genCmp (operand * left, operand * right,
5883 iCode * ic, iCode * ifx, int sign)
5885 int size, offset = 0;
5886 unsigned long lit = 0L;
5889 D (emitcode (";", "genCmp"););
5891 result = IC_RESULT (ic);
5893 /* if left & right are bit variables */
5894 if (AOP_TYPE (left) == AOP_CRY &&
5895 AOP_TYPE (right) == AOP_CRY)
5897 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5898 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5902 /* subtract right from left if at the
5903 end the carry flag is set then we know that
5904 left is greater than right */
5905 size = max (AOP_SIZE (left), AOP_SIZE (right));
5907 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5908 if ((size == 1) && !sign
5909 && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5911 symbol *lbl = newiTempLabel (NULL);
5912 emitcode ("cjne", "%s,%s,!tlabel",
5913 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5914 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5916 emitcode ("", "!tlabeldef", lbl->key + 100);
5920 if (AOP_TYPE (right) == AOP_LIT)
5922 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5923 /* optimize if(x < 0) or if(x >= 0) */
5932 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5934 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5935 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5937 aopOp (result, ic, FALSE, FALSE);
5939 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5941 freeAsmop (result, NULL, ic, TRUE);
5942 genIfxJump (ifx, "acc.7");
5947 emitcode ("rlc", "a");
5949 goto release_freedLR;
5957 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5958 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5959 // emitcode (";", "genCmp #2");
5960 if (sign && (size == 0))
5962 // emitcode (";", "genCmp #3");
5963 emitcode ("xrl", "a,#!constbyte",0x80);
5964 if (AOP_TYPE (right) == AOP_LIT)
5966 unsigned long lit = (unsigned long)
5967 floatFromVal (AOP (right)->aopu.aop_lit);
5968 // emitcode (";", "genCmp #3.1");
5969 emitcode ("subb", "a,#!constbyte",
5970 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5974 // emitcode (";", "genCmp #3.2");
5976 MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5977 saveAccWarn = DEFAULT_ACC_WARNING;
5978 emitcode ("xrl", "b,#!constbyte",0x80);
5979 emitcode ("subb", "a,b");
5986 // emitcode (";", "genCmp #4");
5988 s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5989 saveAccWarn = DEFAULT_ACC_WARNING;
5991 emitcode ("subb", "a,%s", s);
5998 /* Don't need the left & right operands any more; do need the result. */
5999 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6000 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6002 aopOp (result, ic, FALSE, FALSE);
6006 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6012 /* if the result is used in the next
6013 ifx conditional branch then generate
6014 code a little differently */
6017 genIfxJump (ifx, "c");
6023 /* leave the result in acc */
6025 freeAsmop (result, NULL, ic, TRUE);
6028 /*-----------------------------------------------------------------*/
6029 /* genCmpGt :- greater than comparison */
6030 /*-----------------------------------------------------------------*/
6032 genCmpGt (iCode * ic, iCode * ifx)
6034 operand *left, *right;
6035 sym_link *letype, *retype;
6038 D (emitcode (";", "genCmpGt ");
6041 left = IC_LEFT (ic);
6042 right = IC_RIGHT (ic);
6044 letype = getSpec (operandType (left));
6045 retype = getSpec (operandType (right));
6046 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6048 /* assign the left & right amsops */
6051 genCmp (right, left, ic, ifx, sign);
6054 /*-----------------------------------------------------------------*/
6055 /* genCmpLt - less than comparisons */
6056 /*-----------------------------------------------------------------*/
6058 genCmpLt (iCode * ic, iCode * ifx)
6060 operand *left, *right;
6061 sym_link *letype, *retype;
6064 D (emitcode (";", "genCmpLt "););
6066 left = IC_LEFT (ic);
6067 right = IC_RIGHT (ic);
6069 letype = getSpec (operandType (left));
6070 retype = getSpec (operandType (right));
6071 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6073 /* assign the left & right amsops */
6076 genCmp (left, right, ic, ifx, sign);
6079 /*-----------------------------------------------------------------*/
6080 /* gencjneshort - compare and jump if not equal */
6081 /*-----------------------------------------------------------------*/
6083 gencjneshort (operand * left, operand * right, symbol * lbl)
6085 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6087 unsigned long lit = 0L;
6089 D (emitcode (";", "gencjneshort");
6092 /* if the left side is a literal or
6093 if the right is in a pointer register and left
6095 if ((AOP_TYPE (left) == AOP_LIT) ||
6096 (AOP_TYPE (left) == AOP_IMMD) ||
6097 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6104 if (AOP_TYPE (right) == AOP_LIT)
6105 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6107 if (opIsGptr (left) || opIsGptr (right))
6109 /* We are comparing a generic pointer to something.
6110 * Exclude the generic type byte from the comparison.
6113 D (emitcode (";", "cjneshort: generic ptr special case."););
6117 /* if the right side is a literal then anything goes */
6118 if (AOP_TYPE (right) == AOP_LIT &&
6119 AOP_TYPE (left) != AOP_DIR)
6123 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6124 emitcode ("cjne", "a,%s,!tlabel",
6125 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
6131 /* if the right side is in a register or in direct space or
6132 if the left is a pointer register & right is not */
6133 else if (AOP_TYPE (right) == AOP_REG ||
6134 AOP_TYPE (right) == AOP_DIR ||
6135 AOP_TYPE (right) == AOP_LIT ||
6136 AOP_TYPE (right) == AOP_IMMD ||
6137 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6138 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6142 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6143 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6144 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6145 emitcode ("jnz", "!tlabel", lbl->key + 100);
6147 emitcode ("cjne", "a,%s,!tlabel",
6148 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
6155 /* right is a pointer reg need both a & b */
6158 MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6159 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6160 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
6166 /*-----------------------------------------------------------------*/
6167 /* gencjne - compare and jump if not equal */
6168 /*-----------------------------------------------------------------*/
6170 gencjne (operand * left, operand * right, symbol * lbl)
6172 symbol *tlbl = newiTempLabel (NULL);
6174 D (emitcode (";", "gencjne");
6177 gencjneshort (left, right, lbl);
6179 emitcode ("mov", "a,%s", one);
6180 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
6181 emitcode ("", "!tlabeldef", lbl->key + 100);
6182 emitcode ("clr", "a");
6183 emitcode ("", "!tlabeldef", tlbl->key + 100);
6186 /*-----------------------------------------------------------------*/
6187 /* genCmpEq - generates code for equal to */
6188 /*-----------------------------------------------------------------*/
6190 genCmpEq (iCode * ic, iCode * ifx)
6192 operand *left, *right, *result;
6194 D (emitcode (";", "genCmpEq ");
6198 AOP_SET_LOCALS (ic);
6200 /* if literal, literal on the right or
6201 if the right is in a pointer register and left
6203 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6204 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6206 operand *t = IC_RIGHT (ic);
6207 IC_RIGHT (ic) = IC_LEFT (ic);
6211 if (ifx && /* !AOP_SIZE(result) */
6212 OP_SYMBOL (result) &&
6213 OP_SYMBOL (result)->regType == REG_CND)
6216 /* if they are both bit variables */
6217 if (AOP_TYPE (left) == AOP_CRY &&
6218 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6220 if (AOP_TYPE (right) == AOP_LIT)
6222 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6225 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6226 emitcode ("cpl", "c");
6230 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6234 emitcode ("clr", "c");
6236 /* AOP_TYPE(right) == AOP_CRY */
6240 symbol *lbl = newiTempLabel (NULL);
6241 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6242 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6243 emitcode ("cpl", "c");
6244 emitcode ("", "!tlabeldef", (lbl->key + 100));
6246 /* if true label then we jump if condition
6248 tlbl = newiTempLabel (NULL);
6251 emitcode ("jnc", "!tlabel", tlbl->key + 100);
6252 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6256 emitcode ("jc", "!tlabel", tlbl->key + 100);
6257 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6259 emitcode ("", "!tlabeldef", tlbl->key + 100);
6263 tlbl = newiTempLabel (NULL);
6264 gencjneshort (left, right, tlbl);
6267 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6268 emitcode ("", "!tlabeldef", tlbl->key + 100);
6272 symbol *lbl = newiTempLabel (NULL);
6273 emitcode ("sjmp", "!tlabel", lbl->key + 100);
6274 emitcode ("", "!tlabeldef", tlbl->key + 100);
6275 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6276 emitcode ("", "!tlabeldef", lbl->key + 100);
6279 /* mark the icode as generated */
6282 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6283 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6287 /* if they are both bit variables */
6288 if (AOP_TYPE (left) == AOP_CRY &&
6289 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6291 if (AOP_TYPE (right) == AOP_LIT)
6293 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6296 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6297 emitcode ("cpl", "c");
6301 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6305 emitcode ("clr", "c");
6307 /* AOP_TYPE(right) == AOP_CRY */
6311 symbol *lbl = newiTempLabel (NULL);
6312 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6313 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6314 emitcode ("cpl", "c");
6315 emitcode ("", "!tlabeldef", (lbl->key + 100));
6318 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6319 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6321 aopOp (result, ic, TRUE, FALSE);
6324 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6331 genIfxJump (ifx, "c");
6334 /* if the result is used in an arithmetic operation
6335 then put the result in place */
6340 gencjne (left, right, newiTempLabel (NULL));
6342 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6343 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6345 aopOp (result, ic, TRUE, FALSE);
6347 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6349 aopPut (AOP (result), "a", 0);
6354 genIfxJump (ifx, "a");
6357 /* if the result is used in an arithmetic operation
6358 then put the result in place */
6359 if (AOP_TYPE (result) != AOP_CRY)
6361 /* leave the result in acc */
6365 freeAsmop (result, NULL, ic, TRUE);
6368 /*-----------------------------------------------------------------*/
6369 /* ifxForOp - returns the icode containing the ifx for operand */
6370 /*-----------------------------------------------------------------*/
6372 ifxForOp (operand * op, iCode * ic)
6374 /* if true symbol then needs to be assigned */
6375 if (IS_TRUE_SYMOP (op))
6378 /* if this has register type condition and
6379 the next instruction is ifx with the same operand
6380 and live to of the operand is upto the ifx only then */
6382 ic->next->op == IFX &&
6383 IC_COND (ic->next)->key == op->key &&
6384 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6389 /*-----------------------------------------------------------------*/
6390 /* hasInc - operand is incremented before any other use */
6391 /*-----------------------------------------------------------------*/
6393 hasInc (operand *op, iCode *ic, int osize)
6395 sym_link *type = operandType(op);
6396 sym_link *retype = getSpec (type);
6397 iCode *lic = ic->next;
6400 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6401 if (!IS_SYMOP(op)) return NULL;
6403 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6404 if (IS_AGGREGATE(type->next)) return NULL;
6405 if (osize != (isize = getSize(type->next))) return NULL;
6408 /* if operand of the form op = op + <sizeof *op> */
6409 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6410 isOperandEqual(IC_RESULT(lic),op) &&
6411 isOperandLiteral(IC_RIGHT(lic)) &&
6412 operandLitValue(IC_RIGHT(lic)) == isize) {
6415 /* if the operand used or deffed */
6416 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
6419 /* if GOTO or IFX */
6420 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6426 /*-----------------------------------------------------------------*/
6427 /* genAndOp - for && operation */
6428 /*-----------------------------------------------------------------*/
6430 genAndOp (iCode * ic)
6432 operand *left, *right, *result;
6435 D (emitcode (";", "genAndOp "););
6437 /* note here that && operations that are in an
6438 if statement are taken away by backPatchLabels
6439 only those used in arthmetic operations remain */
6441 AOP_SET_LOCALS (ic);
6443 /* if both are bit variables */
6444 if (AOP_TYPE (left) == AOP_CRY &&
6445 AOP_TYPE (right) == AOP_CRY)
6447 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6448 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6449 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6450 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6452 aopOp (result,ic,FALSE, FALSE);
6457 tlbl = newiTempLabel (NULL);
6459 emitcode ("jz", "!tlabel", tlbl->key + 100);
6461 emitcode ("", "!tlabeldef", tlbl->key + 100);
6462 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6463 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6465 aopOp (result,ic,FALSE, FALSE);
6468 freeAsmop (result, NULL, ic, TRUE);
6472 /*-----------------------------------------------------------------*/
6473 /* genOrOp - for || operation */
6474 /*-----------------------------------------------------------------*/
6476 genOrOp (iCode * ic)
6478 operand *left, *right, *result;
6481 D (emitcode (";", "genOrOp "););
6483 /* note here that || operations that are in an
6484 if statement are taken away by backPatchLabels
6485 only those used in arthmetic operations remain */
6487 AOP_SET_LOCALS (ic);
6489 /* if both are bit variables */
6490 if (AOP_TYPE (left) == AOP_CRY &&
6491 AOP_TYPE (right) == AOP_CRY)
6493 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6494 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6495 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6496 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6498 aopOp (result,ic,FALSE, FALSE);
6504 tlbl = newiTempLabel (NULL);
6506 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6508 emitcode ("", "!tlabeldef", tlbl->key + 100);
6509 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6510 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6512 aopOp (result,ic,FALSE, FALSE);
6517 freeAsmop (result, NULL, ic, TRUE);
6520 /*-----------------------------------------------------------------*/
6521 /* isLiteralBit - test if lit == 2^n */
6522 /*-----------------------------------------------------------------*/
6524 isLiteralBit (unsigned long lit)
6526 unsigned long pw[32] =
6527 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6528 0x100L, 0x200L, 0x400L, 0x800L,
6529 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6530 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6531 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6532 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6533 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6536 for (idx = 0; idx < 32; idx++)
6542 /*-----------------------------------------------------------------*/
6543 /* continueIfTrue - */
6544 /*-----------------------------------------------------------------*/
6546 continueIfTrue (iCode * ic)
6549 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6553 /*-----------------------------------------------------------------*/
6555 /*-----------------------------------------------------------------*/
6557 jumpIfTrue (iCode * ic)
6560 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6564 /*-----------------------------------------------------------------*/
6565 /* jmpTrueOrFalse - */
6566 /*-----------------------------------------------------------------*/
6568 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6570 // ugly but optimized by peephole
6573 symbol *nlbl = newiTempLabel (NULL);
6574 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6575 emitcode ("", "!tlabeldef", tlbl->key + 100);
6576 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6577 emitcode ("", "!tlabeldef", nlbl->key + 100);
6581 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6582 emitcode ("", "!tlabeldef", tlbl->key + 100);
6587 // Generate code to perform a bit-wise logic operation
6588 // on two operands in far space (assumed to already have been
6589 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6590 // in far space. This requires pushing the result on the stack
6591 // then popping it into the result.
6593 genFarFarLogicOp(iCode *ic, char *logicOp)
6595 int size, resultSize, compSize;
6599 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6600 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
6601 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6603 _startLazyDPSEvaluation();
6604 for (size = compSize; (size--); offset++)
6606 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6607 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6608 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6610 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6611 emitcode ("push", "acc");
6613 _endLazyDPSEvaluation();
6615 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6616 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6617 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6619 resultSize = AOP_SIZE(IC_RESULT(ic));
6621 ADJUST_PUSHED_RESULT(compSize, resultSize);
6623 _startLazyDPSEvaluation();
6626 emitcode ("pop", "acc");
6627 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6629 _endLazyDPSEvaluation();
6630 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6634 /*-----------------------------------------------------------------*/
6635 /* genAnd - code for and */
6636 /*-----------------------------------------------------------------*/
6638 genAnd (iCode * ic, iCode * ifx)
6640 operand *left, *right, *result;
6641 int size, offset = 0;
6642 unsigned long lit = 0L;
6647 D (emitcode (";", "genAnd "););
6649 AOP_OP_3_NOFATAL (ic, pushResult);
6650 AOP_SET_LOCALS (ic);
6654 genFarFarLogicOp(ic, "anl");
6659 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6661 AOP_TYPE (left), AOP_TYPE (right));
6662 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6664 AOP_SIZE (left), AOP_SIZE (right));
6667 /* if left is a literal & right is not then exchange them */
6668 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6669 #ifdef LOGIC_OPS_BROKEN
6670 || AOP_NEEDSACC (left)
6674 operand *tmp = right;
6679 /* if result = right then exchange them */
6680 if (sameRegs (AOP (result), AOP (right)))
6682 operand *tmp = right;
6687 /* if right is bit then exchange them */
6688 if (AOP_TYPE (right) == AOP_CRY &&
6689 AOP_TYPE (left) != AOP_CRY)
6691 operand *tmp = right;
6695 if (AOP_TYPE (right) == AOP_LIT)
6696 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6698 size = AOP_SIZE (result);
6701 // result = bit & yy;
6702 if (AOP_TYPE (left) == AOP_CRY)
6704 // c = bit & literal;
6705 if (AOP_TYPE (right) == AOP_LIT)
6709 if (size && sameRegs (AOP (result), AOP (left)))
6712 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6717 if (size && (AOP_TYPE (result) == AOP_CRY))
6719 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6722 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6727 emitcode ("clr", "c");
6732 if (AOP_TYPE (right) == AOP_CRY)
6735 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6736 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6741 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6743 emitcode ("rrc", "a");
6744 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6752 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6753 genIfxJump (ifx, "c");
6757 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6758 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6759 if ((AOP_TYPE (right) == AOP_LIT) &&
6760 (AOP_TYPE (result) == AOP_CRY) &&
6761 (AOP_TYPE (left) != AOP_CRY))
6763 int posbit = isLiteralBit (lit);
6768 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6771 emitcode ("mov", "c,acc.%d", posbit & 0x07);
6777 SNPRINTF (buff, sizeof(buff),
6778 "acc.%d", posbit & 0x07);
6779 genIfxJump (ifx, buff);
6783 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6790 symbol *tlbl = newiTempLabel (NULL);
6791 int sizel = AOP_SIZE (left);
6793 emitcode ("setb", "c");
6796 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6798 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6800 if ((posbit = isLiteralBit (bytelit)) != 0)
6801 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6804 if (bytelit != 0x0FFL)
6805 emitcode ("anl", "a,%s",
6806 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6807 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6812 // bit = left & literal
6815 emitcode ("clr", "c");
6816 emitcode ("", "!tlabeldef", tlbl->key + 100);
6818 // if(left & literal)
6822 jmpTrueOrFalse (ifx, tlbl);
6824 emitcode ("", "!tlabeldef", tlbl->key + 100);
6832 /* if left is same as result */
6833 if (sameRegs (AOP (result), AOP (left)))
6835 for (; size--; offset++)
6837 if (AOP_TYPE (right) == AOP_LIT)
6839 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6841 else if (bytelit == 0)
6842 aopPut (AOP (result), zero, offset);
6843 else if (IS_AOP_PREG (result))
6845 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6846 emitcode ("anl", "a,%s",
6847 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6848 aopPut (AOP (result), "a", offset);
6851 emitcode ("anl", "%s,%s",
6852 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6853 aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6857 if (AOP_TYPE (left) == AOP_ACC)
6858 emitcode ("anl", "a,%s",
6859 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6862 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6863 if (IS_AOP_PREG (result))
6865 emitcode ("anl", "a,%s",
6866 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6867 aopPut (AOP (result), "a", offset);
6870 emitcode ("anl", "%s,a",
6871 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6878 // left & result in different registers
6879 if (AOP_TYPE (result) == AOP_CRY)
6882 // if(size), result in bit
6883 // if(!size && ifx), conditional oper: if(left & right)
6884 symbol *tlbl = newiTempLabel (NULL);
6885 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6887 emitcode ("setb", "c");
6890 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6891 emitcode ("anl", "a,%s",
6892 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6894 if (AOP_TYPE(left)==AOP_ACC) {
6895 emitcode("mov", "b,a");
6896 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6897 emitcode("anl", "a,b");
6899 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6900 emitcode ("anl", "a,%s",
6901 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6904 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6910 emitcode ("", "!tlabeldef", tlbl->key + 100);
6914 jmpTrueOrFalse (ifx, tlbl);
6916 emitcode ("", "!tlabeldef", tlbl->key + 100);
6920 for (; (size--); offset++)
6923 // result = left & right
6924 if (AOP_TYPE (right) == AOP_LIT)
6926 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6928 aopPut (AOP (result),
6929 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6933 else if (bytelit == 0)
6935 aopPut (AOP (result), zero, offset);
6938 D (emitcode (";", "better literal AND."););
6939 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6940 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6941 FALSE, FALSE, DP2_RESULT_REG));
6946 // faster than result <- left, anl result,right
6947 // and better if result is SFR
6948 if (AOP_TYPE (left) == AOP_ACC)
6950 emitcode ("anl", "a,%s",
6951 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6955 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6956 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6958 emitcode("mov", "b,a");
6962 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6963 emitcode ("anl", "a,%s", rOp);
6966 aopPut (AOP (result), "a", offset);
6972 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6973 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6974 freeAsmop (result, NULL, ic, TRUE);
6978 /*-----------------------------------------------------------------*/
6979 /* genOr - code for or */
6980 /*-----------------------------------------------------------------*/
6982 genOr (iCode * ic, iCode * ifx)
6984 operand *left, *right, *result;
6985 int size, offset = 0;
6986 unsigned long lit = 0L;
6989 D (emitcode (";", "genOr "););
6991 AOP_OP_3_NOFATAL (ic, pushResult);
6992 AOP_SET_LOCALS (ic);
6996 genFarFarLogicOp(ic, "orl");
7002 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7004 AOP_TYPE (left), AOP_TYPE (right));
7005 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7007 AOP_SIZE (left), AOP_SIZE (right));
7010 /* if left is a literal & right is not then exchange them */
7011 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7012 #ifdef LOGIC_OPS_BROKEN
7013 || AOP_NEEDSACC (left) // I think this is a net loss now.
7017 operand *tmp = right;
7022 /* if result = right then exchange them */
7023 if (sameRegs (AOP (result), AOP (right)))
7025 operand *tmp = right;
7030 /* if right is bit then exchange them */
7031 if (AOP_TYPE (right) == AOP_CRY &&
7032 AOP_TYPE (left) != AOP_CRY)
7034 operand *tmp = right;
7038 if (AOP_TYPE (right) == AOP_LIT)
7039 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7041 size = AOP_SIZE (result);
7045 if (AOP_TYPE (left) == AOP_CRY)
7047 if (AOP_TYPE (right) == AOP_LIT)
7049 // c = bit & literal;
7052 // lit != 0 => result = 1
7053 if (AOP_TYPE (result) == AOP_CRY)
7056 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7058 continueIfTrue (ifx);
7061 emitcode ("setb", "c");
7065 // lit == 0 => result = left
7066 if (size && sameRegs (AOP (result), AOP (left)))
7068 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7073 if (AOP_TYPE (right) == AOP_CRY)
7076 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7077 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7082 symbol *tlbl = newiTempLabel (NULL);
7083 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7084 emitcode ("setb", "c");
7085 emitcode ("jb", "%s,!tlabel",
7086 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7088 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7089 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7091 jmpTrueOrFalse (ifx, tlbl);
7097 emitcode ("", "!tlabeldef", tlbl->key + 100);
7106 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7107 genIfxJump (ifx, "c");
7111 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7112 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7113 if ((AOP_TYPE (right) == AOP_LIT) &&
7114 (AOP_TYPE (result) == AOP_CRY) &&
7115 (AOP_TYPE (left) != AOP_CRY))
7121 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7123 continueIfTrue (ifx);
7128 // lit = 0, result = boolean(left)
7130 emitcode ("setb", "c");
7134 symbol *tlbl = newiTempLabel (NULL);
7135 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7137 emitcode ("", "!tlabeldef", tlbl->key + 100);
7141 genIfxJump (ifx, "a");
7149 /* if left is same as result */
7150 if (sameRegs (AOP (result), AOP (left)))
7152 for (; size--; offset++)
7154 if (AOP_TYPE (right) == AOP_LIT)
7156 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7162 if (IS_AOP_PREG (left))
7164 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7165 emitcode ("orl", "a,%s",
7166 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7167 aopPut (AOP (result), "a", offset);
7171 emitcode ("orl", "%s,%s",
7172 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7173 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7179 if (AOP_TYPE (left) == AOP_ACC)
7181 emitcode ("orl", "a,%s",
7182 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7186 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7187 if (IS_AOP_PREG (left))
7189 emitcode ("orl", "a,%s",
7190 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7191 aopPut (AOP (result), "a", offset);
7195 emitcode ("orl", "%s,a",
7196 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7204 // left & result in different registers
7205 if (AOP_TYPE (result) == AOP_CRY)
7208 // if(size), result in bit
7209 // if(!size && ifx), conditional oper: if(left | right)
7210 symbol *tlbl = newiTempLabel (NULL);
7211 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7213 emitcode ("setb", "c");
7216 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7217 emitcode ("orl", "a,%s",
7218 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7220 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7221 emitcode ("orl", "a,%s",
7222 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
7224 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7230 emitcode ("", "!tlabeldef", tlbl->key + 100);
7234 jmpTrueOrFalse (ifx, tlbl);
7236 emitcode ("", "!tlabeldef", tlbl->key + 100);
7240 _startLazyDPSEvaluation();
7241 for (; (size--); offset++)
7244 // result = left & right
7245 if (AOP_TYPE (right) == AOP_LIT)
7247 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7249 aopPut (AOP (result),
7250 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7254 D (emitcode (";", "better literal OR."););
7255 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7256 emitcode ("orl", "a, %s",
7257 aopGet (AOP (right), offset,
7258 FALSE, FALSE, DP2_RESULT_REG));
7263 // faster than result <- left, anl result,right
7264 // and better if result is SFR
7265 if (AOP_TYPE (left) == AOP_ACC)
7267 emitcode ("orl", "a,%s",
7268 aopGet (AOP (right), offset,
7269 FALSE, FALSE, DP2_RESULT_REG));
7273 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7275 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7277 emitcode("mov", "b,a");
7281 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7282 emitcode ("orl", "a,%s", rOp);
7285 aopPut (AOP (result), "a", offset);
7287 _endLazyDPSEvaluation();
7292 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7293 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7294 freeAsmop (result, NULL, ic, TRUE);
7297 /*-----------------------------------------------------------------*/
7298 /* genXor - code for xclusive or */
7299 /*-----------------------------------------------------------------*/
7301 genXor (iCode * ic, iCode * ifx)
7303 operand *left, *right, *result;
7304 int size, offset = 0;
7305 unsigned long lit = 0L;
7308 D (emitcode (";", "genXor "););
7310 AOP_OP_3_NOFATAL (ic, pushResult);
7311 AOP_SET_LOCALS (ic);
7315 genFarFarLogicOp(ic, "xrl");
7320 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7322 AOP_TYPE (left), AOP_TYPE (right));
7323 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7325 AOP_SIZE (left), AOP_SIZE (right));
7328 /* if left is a literal & right is not ||
7329 if left needs acc & right does not */
7330 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7331 #ifdef LOGIC_OPS_BROKEN
7332 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
7336 operand *tmp = right;
7341 /* if result = right then exchange them */
7342 if (sameRegs (AOP (result), AOP (right)))
7344 operand *tmp = right;
7349 /* if right is bit then exchange them */
7350 if (AOP_TYPE (right) == AOP_CRY &&
7351 AOP_TYPE (left) != AOP_CRY)
7353 operand *tmp = right;
7357 if (AOP_TYPE (right) == AOP_LIT)
7358 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7360 size = AOP_SIZE (result);
7364 if (AOP_TYPE (left) == AOP_CRY)
7366 if (AOP_TYPE (right) == AOP_LIT)
7368 // c = bit & literal;
7371 // lit>>1 != 0 => result = 1
7372 if (AOP_TYPE (result) == AOP_CRY)
7375 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7377 continueIfTrue (ifx);
7380 emitcode ("setb", "c");
7387 // lit == 0, result = left
7388 if (size && sameRegs (AOP (result), AOP (left)))
7390 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7394 // lit == 1, result = not(left)
7395 if (size && sameRegs (AOP (result), AOP (left)))
7397 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7402 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7403 emitcode ("cpl", "c");
7412 symbol *tlbl = newiTempLabel (NULL);
7413 if (AOP_TYPE (right) == AOP_CRY)
7416 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7420 int sizer = AOP_SIZE (right);
7422 // if val>>1 != 0, result = 1
7423 emitcode ("setb", "c");
7426 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
7428 // test the msb of the lsb
7429 emitcode ("anl", "a,#!constbyte",0xfe);
7430 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7434 emitcode ("rrc", "a");
7436 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7437 emitcode ("cpl", "c");
7438 emitcode ("", "!tlabeldef", (tlbl->key + 100));
7445 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7446 genIfxJump (ifx, "c");
7450 if (sameRegs (AOP (result), AOP (left)))
7452 /* if left is same as result */
7453 for (; size--; offset++)
7455 if (AOP_TYPE (right) == AOP_LIT)
7457 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7459 else if (IS_AOP_PREG (left))
7461 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7462 emitcode ("xrl", "a,%s",
7463 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7464 aopPut (AOP (result), "a", offset);
7467 emitcode ("xrl", "%s,%s",
7468 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7469 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7473 if (AOP_TYPE (left) == AOP_ACC)
7474 emitcode ("xrl", "a,%s",
7475 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7478 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7479 if (IS_AOP_PREG (left))
7481 emitcode ("xrl", "a,%s",
7482 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7483 aopPut (AOP (result), "a", offset);
7486 emitcode ("xrl", "%s,a",
7487 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7494 // left & result in different registers
7495 if (AOP_TYPE (result) == AOP_CRY)
7498 // if(size), result in bit
7499 // if(!size && ifx), conditional oper: if(left ^ right)
7500 symbol *tlbl = newiTempLabel (NULL);
7501 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7504 emitcode ("setb", "c");
7507 if ((AOP_TYPE (right) == AOP_LIT) &&
7508 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7510 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7514 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7515 emitcode ("xrl", "a,%s",
7516 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7518 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7519 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7521 emitcode("mov", "b,a");
7525 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7526 emitcode ("xrl", "a,%s", rOp);
7529 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7535 emitcode ("", "!tlabeldef", tlbl->key + 100);
7539 jmpTrueOrFalse (ifx, tlbl);
7543 for (; (size--); offset++)
7546 // result = left & right
7547 if (AOP_TYPE (right) == AOP_LIT)
7549 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7551 aopPut (AOP (result),
7552 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7556 D (emitcode (";", "better literal XOR."););
7557 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7558 emitcode ("xrl", "a, %s",
7559 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7563 // faster than result <- left, anl result,right
7564 // and better if result is SFR
7565 if (AOP_TYPE (left) == AOP_ACC)
7567 emitcode ("xrl", "a,%s",
7568 aopGet (AOP (right), offset,
7569 FALSE, FALSE, DP2_RESULT_REG));
7573 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7574 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7576 emitcode("mov", "b,a");
7580 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7581 emitcode ("xrl", "a,%s", rOp);
7584 aopPut (AOP (result), "a", offset);
7591 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7592 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7593 freeAsmop (result, NULL, ic, TRUE);
7596 /*-----------------------------------------------------------------*/
7597 /* genInline - write the inline code out */
7598 /*-----------------------------------------------------------------*/
7600 genInline (iCode * ic)
7602 char *buffer, *bp, *bp1;
7604 D (emitcode (";", "genInline "); );
7606 _G.inLine += (!options.asmpeep);
7608 buffer = Safe_strdup(IC_INLINE(ic));
7612 /* emit each line as a code */
7637 /* emitcode("",buffer); */
7638 _G.inLine -= (!options.asmpeep);
7641 /*-----------------------------------------------------------------*/
7642 /* genRRC - rotate right with carry */
7643 /*-----------------------------------------------------------------*/
7647 operand *left, *result;
7650 D (emitcode (";", "genRRC "););
7652 /* rotate right with carry */
7653 left = IC_LEFT (ic);
7654 result = IC_RESULT (ic);
7655 aopOp (left, ic, FALSE, FALSE);
7656 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7658 /* move it to the result */
7659 size = AOP_SIZE (result);
7663 _startLazyDPSEvaluation ();
7666 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7667 emitcode ("rrc", "a");
7668 if (AOP_SIZE (result) > 1)
7669 aopPut (AOP (result), "a", offset--);
7671 _endLazyDPSEvaluation ();
7673 /* now we need to put the carry into the
7674 highest order byte of the result */
7675 if (AOP_SIZE (result) > 1)
7677 MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7679 emitcode ("mov", "acc.7,c");
7680 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7681 freeAsmop (left, NULL, ic, TRUE);
7682 freeAsmop (result, NULL, ic, TRUE);
7685 /*-----------------------------------------------------------------*/
7686 /* genRLC - generate code for rotate left with carry */
7687 /*-----------------------------------------------------------------*/
7691 operand *left, *result;
7695 D (emitcode (";", "genRLC "););
7697 /* rotate right with carry */
7698 left = IC_LEFT (ic);
7699 result = IC_RESULT (ic);
7700 aopOp (left, ic, FALSE, FALSE);
7701 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7703 /* move it to the result */
7704 size = AOP_SIZE (result);
7708 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7710 emitcode ("add", "a,acc");
7711 if (AOP_SIZE (result) > 1)
7713 aopPut (AOP (result), "a", offset++);
7716 _startLazyDPSEvaluation ();
7719 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7721 emitcode ("rlc", "a");
7722 if (AOP_SIZE (result) > 1)
7723 aopPut (AOP (result), "a", offset++);
7725 _endLazyDPSEvaluation ();
7727 /* now we need to put the carry into the
7728 highest order byte of the result */
7729 if (AOP_SIZE (result) > 1)
7731 l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7734 emitcode ("mov", "acc.0,c");
7735 aopPut (AOP (result), "a", 0);
7736 freeAsmop (left, NULL, ic, TRUE);
7737 freeAsmop (result, NULL, ic, TRUE);
7740 /*-----------------------------------------------------------------*/
7741 /* genGetHbit - generates code get highest order bit */
7742 /*-----------------------------------------------------------------*/
7744 genGetHbit (iCode * ic)
7746 operand *left, *result;
7747 left = IC_LEFT (ic);
7748 result = IC_RESULT (ic);
7749 aopOp (left, ic, FALSE, FALSE);
7750 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7752 D (emitcode (";", "genGetHbit "););
7754 /* get the highest order byte into a */
7755 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7756 if (AOP_TYPE (result) == AOP_CRY)
7758 emitcode ("rlc", "a");
7763 emitcode ("rl", "a");
7764 emitcode ("anl", "a,#1");
7769 freeAsmop (left, NULL, ic, TRUE);
7770 freeAsmop (result, NULL, ic, TRUE);
7773 /*-----------------------------------------------------------------*/
7774 /* genSwap - generates code to swap nibbles or bytes */
7775 /*-----------------------------------------------------------------*/
7777 genSwap (iCode * ic)
7779 operand *left, *result;
7781 D(emitcode ("; genSwap",""));
7783 left = IC_LEFT (ic);
7784 result = IC_RESULT (ic);
7785 aopOp (left, ic, FALSE, FALSE);
7786 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7788 _startLazyDPSEvaluation ();
7789 switch (AOP_SIZE (left))
7791 case 1: /* swap nibbles in byte */
7792 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7793 emitcode ("swap", "a");
7794 aopPut (AOP (result), "a", 0);
7796 case 2: /* swap bytes in word */
7797 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7799 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7800 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7801 aopPut (AOP (result), "a", 1);
7803 else if (operandsEqu (left, result))
7806 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7807 if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
7809 emitcode ("mov", "b,a");
7813 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7814 aopPut (AOP (result), reg, 1);
7819 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7820 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE, NULL), 1);
7824 wassertl(FALSE, "unsupported SWAP operand size");
7826 _endLazyDPSEvaluation ();
7828 freeAsmop (left, NULL, ic, TRUE);
7829 freeAsmop (result, NULL, ic, TRUE);
7832 /*-----------------------------------------------------------------*/
7833 /* AccRol - rotate left accumulator by known count */
7834 /*-----------------------------------------------------------------*/
7836 AccRol (int shCount)
7838 shCount &= 0x0007; // shCount : 0..7
7845 emitcode ("rl", "a");
7848 emitcode ("rl", "a");
7849 emitcode ("rl", "a");
7852 emitcode ("swap", "a");
7853 emitcode ("rr", "a");
7856 emitcode ("swap", "a");
7859 emitcode ("swap", "a");
7860 emitcode ("rl", "a");
7863 emitcode ("rr", "a");
7864 emitcode ("rr", "a");
7867 emitcode ("rr", "a");
7872 /*-----------------------------------------------------------------*/
7873 /* AccLsh - left shift accumulator by known count */
7874 /*-----------------------------------------------------------------*/
7876 AccLsh (int shCount)
7881 emitcode ("add", "a,acc");
7882 else if (shCount == 2)
7884 emitcode ("add", "a,acc");
7885 emitcode ("add", "a,acc");
7889 /* rotate left accumulator */
7891 /* and kill the lower order bits */
7892 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7897 /*-----------------------------------------------------------------*/
7898 /* AccRsh - right shift accumulator by known count */
7899 /*-----------------------------------------------------------------*/
7901 AccRsh (int shCount)
7908 emitcode ("rrc", "a");
7912 /* rotate right accumulator */
7913 AccRol (8 - shCount);
7914 /* and kill the higher order bits */
7915 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7920 #ifdef BETTER_LITERAL_SHIFT
7921 /*-----------------------------------------------------------------*/
7922 /* AccSRsh - signed right shift accumulator by known count */
7923 /*-----------------------------------------------------------------*/
7925 AccSRsh (int shCount)
7932 emitcode ("mov", "c,acc.7");
7933 emitcode ("rrc", "a");
7935 else if (shCount == 2)
7937 emitcode ("mov", "c,acc.7");
7938 emitcode ("rrc", "a");
7939 emitcode ("mov", "c,acc.7");
7940 emitcode ("rrc", "a");
7944 tlbl = newiTempLabel (NULL);
7945 /* rotate right accumulator */
7946 AccRol (8 - shCount);
7947 /* and kill the higher order bits */
7948 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7949 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7950 emitcode ("orl", "a,#!constbyte",
7951 (unsigned char) ~SRMask[shCount]);
7952 emitcode ("", "!tlabeldef", tlbl->key + 100);
7958 #ifdef BETTER_LITERAL_SHIFT
7959 /*-----------------------------------------------------------------*/
7960 /* shiftR1Left2Result - shift right one byte from left to result */
7961 /*-----------------------------------------------------------------*/
7963 shiftR1Left2Result (operand * left, int offl,
7964 operand * result, int offr,
7965 int shCount, int sign)
7967 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7968 /* shift right accumulator */
7973 aopPut (AOP (result), "a", offr);
7977 #ifdef BETTER_LITERAL_SHIFT
7978 /*-----------------------------------------------------------------*/
7979 /* shiftL1Left2Result - shift left one byte from left to result */
7980 /*-----------------------------------------------------------------*/
7982 shiftL1Left2Result (operand * left, int offl,
7983 operand * result, int offr, int shCount)
7985 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7986 /* shift left accumulator */
7988 aopPut (AOP (result), "a", offr);
7992 #ifdef BETTER_LITERAL_SHIFT
7993 /*-----------------------------------------------------------------*/
7994 /* movLeft2Result - move byte from left to result */
7995 /*-----------------------------------------------------------------*/
7997 movLeft2Result (operand * left, int offl,
7998 operand * result, int offr, int sign)
8001 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8003 l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
8005 if (*l == '@' && (IS_AOP_PREG (result)))
8007 emitcode ("mov", "a,%s", l);
8008 aopPut (AOP (result), "a", offr);
8014 aopPut (AOP (result), l, offr);
8018 /* MSB sign in acc.7 ! */
8019 if (getDataSize (left) == offl + 1)
8021 emitcode ("mov", "a,%s", l);
8022 aopPut (AOP (result), "a", offr);
8030 #ifdef BETTER_LITERAL_SHIFT
8031 /*-----------------------------------------------------------------*/
8032 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8033 /*-----------------------------------------------------------------*/
8037 emitcode ("rrc", "a");
8038 emitcode ("xch", "a,%s", x);
8039 emitcode ("rrc", "a");
8040 emitcode ("xch", "a,%s", x);
8044 #ifdef BETTER_LITERAL_SHIFT
8046 /*-----------------------------------------------------------------*/
8047 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8048 /*-----------------------------------------------------------------*/
8052 emitcode ("xch", "a,%s", x);
8053 emitcode ("rlc", "a");
8054 emitcode ("xch", "a,%s", x);
8055 emitcode ("rlc", "a");
8059 #ifdef BETTER_LITERAL_SHIFT
8060 /*-----------------------------------------------------------------*/
8061 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8062 /*-----------------------------------------------------------------*/
8066 emitcode ("xch", "a,%s", x);
8067 emitcode ("add", "a,acc");
8068 emitcode ("xch", "a,%s", x);
8069 emitcode ("rlc", "a");
8073 #ifdef BETTER_LITERAL_SHIFT
8074 /*-----------------------------------------------------------------*/
8075 /* AccAXLsh - left shift a:x by known count (0..7) */
8076 /*-----------------------------------------------------------------*/
8078 AccAXLsh (char *x, int shCount)
8093 case 5: // AAAAABBB:CCCCCDDD
8095 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8097 emitcode ("anl", "a,#!constbyte",
8098 SLMask[shCount]); // BBB00000:CCCCCDDD
8100 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8102 AccRol (shCount); // DDDCCCCC:BBB00000
8104 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8106 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8108 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8110 emitcode ("anl", "a,#!constbyte",
8111 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8113 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8115 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8118 case 6: // AAAAAABB:CCCCCCDD
8119 emitcode ("anl", "a,#!constbyte",
8120 SRMask[shCount]); // 000000BB:CCCCCCDD
8121 emitcode ("mov", "c,acc.0"); // c = B
8122 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8124 AccAXRrl1 (x); // BCCCCCCD:D000000B
8125 AccAXRrl1 (x); // BBCCCCCC:DD000000
8127 emitcode("rrc","a");
8128 emitcode("xch","a,%s", x);
8129 emitcode("rrc","a");
8130 emitcode("mov","c,acc.0"); //<< get correct bit
8131 emitcode("xch","a,%s", x);
8133 emitcode("rrc","a");
8134 emitcode("xch","a,%s", x);
8135 emitcode("rrc","a");
8136 emitcode("xch","a,%s", x);
8139 case 7: // a:x <<= 7
8141 emitcode ("anl", "a,#!constbyte",
8142 SRMask[shCount]); // 0000000B:CCCCCCCD
8144 emitcode ("mov", "c,acc.0"); // c = B
8146 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8148 AccAXRrl1 (x); // BCCCCCCC:D0000000
8157 #ifdef BETTER_LITERAL_SHIFT
8159 /*-----------------------------------------------------------------*/
8160 /* AccAXRsh - right shift a:x known count (0..7) */
8161 /*-----------------------------------------------------------------*/
8163 AccAXRsh (char *x, int shCount)
8171 AccAXRrl1 (x); // 0->a:x
8176 AccAXRrl1 (x); // 0->a:x
8179 AccAXRrl1 (x); // 0->a:x
8184 case 5: // AAAAABBB:CCCCCDDD = a:x
8186 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8188 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8190 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8192 emitcode ("anl", "a,#!constbyte",
8193 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8195 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8197 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8199 emitcode ("anl", "a,#!constbyte",
8200 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8202 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8204 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8206 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8209 case 6: // AABBBBBB:CCDDDDDD
8211 emitcode ("mov", "c,acc.7");
8212 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8214 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8216 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8218 emitcode ("anl", "a,#!constbyte",
8219 SRMask[shCount]); // 000000AA:BBBBBBCC
8222 case 7: // ABBBBBBB:CDDDDDDD
8224 emitcode ("mov", "c,acc.7"); // c = A
8226 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8228 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8230 emitcode ("anl", "a,#!constbyte",
8231 SRMask[shCount]); // 0000000A:BBBBBBBC
8240 #ifdef BETTER_LITERAL_SHIFT
8241 /*-----------------------------------------------------------------*/
8242 /* AccAXRshS - right shift signed a:x known count (0..7) */
8243 /*-----------------------------------------------------------------*/
8245 AccAXRshS (char *x, int shCount)
8253 emitcode ("mov", "c,acc.7");
8254 AccAXRrl1 (x); // s->a:x
8258 emitcode ("mov", "c,acc.7");
8259 AccAXRrl1 (x); // s->a:x
8261 emitcode ("mov", "c,acc.7");
8262 AccAXRrl1 (x); // s->a:x
8267 case 5: // AAAAABBB:CCCCCDDD = a:x
8269 tlbl = newiTempLabel (NULL);
8270 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8272 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8274 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8276 emitcode ("anl", "a,#!constbyte",
8277 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8279 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8281 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8283 emitcode ("anl", "a,#!constbyte",
8284 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8286 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8288 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8290 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8292 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8293 emitcode ("orl", "a,#!constbyte",
8294 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8296 emitcode ("", "!tlabeldef", tlbl->key + 100);
8297 break; // SSSSAAAA:BBBCCCCC
8299 case 6: // AABBBBBB:CCDDDDDD
8301 tlbl = newiTempLabel (NULL);
8302 emitcode ("mov", "c,acc.7");
8303 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8305 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8307 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8309 emitcode ("anl", "a,#!constbyte",
8310 SRMask[shCount]); // 000000AA:BBBBBBCC
8312 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8313 emitcode ("orl", "a,#!constbyte",
8314 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8316 emitcode ("", "!tlabeldef", tlbl->key + 100);
8318 case 7: // ABBBBBBB:CDDDDDDD
8320 tlbl = newiTempLabel (NULL);
8321 emitcode ("mov", "c,acc.7"); // c = A
8323 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8325 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8327 emitcode ("anl", "a,#!constbyte",
8328 SRMask[shCount]); // 0000000A:BBBBBBBC
8330 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8331 emitcode ("orl", "a,#!constbyte",
8332 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8334 emitcode ("", "!tlabeldef", tlbl->key + 100);
8342 #ifdef BETTER_LITERAL_SHIFT
8344 _loadLeftIntoAx(char **lsb,
8350 // Get the initial value from left into a pair of registers.
8351 // MSB must be in A, LSB can be any register.
8353 // If the result is held in registers, it is an optimization
8354 // if the LSB can be held in the register which will hold the,
8355 // result LSB since this saves us from having to copy it into
8356 // the result following AccAXLsh.
8358 // If the result is addressed indirectly, this is not a gain.
8359 if (AOP_NEEDSACC(result))
8363 _startLazyDPSEvaluation();
8364 if (AOP_TYPE(left) == AOP_DPTR2)
8367 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
8368 // get LSB in DP2_RESULT_REG.
8369 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
8370 assert(!strcmp(leftByte, DP2_RESULT_REG));
8374 // get LSB into DP2_RESULT_REG
8375 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
8376 if (strcmp(leftByte, DP2_RESULT_REG))
8379 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
8382 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
8383 assert(strcmp(leftByte, DP2_RESULT_REG));
8386 _endLazyDPSEvaluation();
8387 *lsb = DP2_RESULT_REG;
8391 if (sameRegs (AOP (result), AOP (left)) &&
8392 ((offl + MSB16) == offr))
8394 /* don't crash result[offr] */
8395 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
8396 emitcode ("xch", "a,%s",
8397 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
8401 movLeft2Result (left, offl, result, offr, 0);
8402 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
8404 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
8405 assert(strcmp(*lsb,"a"));
8410 _storeAxResults(char *lsb,
8414 _startLazyDPSEvaluation();
8415 if (AOP_NEEDSACC(result))
8417 /* We have to explicitly update the result LSB.
8419 emitcode("xch","a,%s", lsb);
8420 aopPut(AOP(result), "a", offr);
8421 emitcode("mov","a,%s", lsb);
8423 if (getDataSize (result) > 1)
8425 aopPut (AOP (result), "a", offr + MSB16);
8427 _endLazyDPSEvaluation();
8430 /*-----------------------------------------------------------------*/
8431 /* shiftL2Left2Result - shift left two bytes from left to result */
8432 /*-----------------------------------------------------------------*/
8434 shiftL2Left2Result (operand * left, int offl,
8435 operand * result, int offr, int shCount)
8439 _loadLeftIntoAx(&lsb, left, result, offl, offr);
8441 AccAXLsh (lsb, shCount);
8443 _storeAxResults(lsb, result, offr);
8447 #ifdef BETTER_LITERAL_SHIFT
8448 /*-----------------------------------------------------------------*/
8449 /* shiftR2Left2Result - shift right two bytes from left to result */
8450 /*-----------------------------------------------------------------*/
8452 shiftR2Left2Result (operand * left, int offl,
8453 operand * result, int offr,
8454 int shCount, int sign)
8458 _loadLeftIntoAx(&lsb, left, result, offl, offr);
8460 /* a:x >> shCount (x = lsb(result)) */
8463 AccAXRshS(lsb, shCount);
8467 AccAXRsh(lsb, shCount);
8470 _storeAxResults(lsb, result, offr);
8474 /*-----------------------------------------------------------------*/
8475 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8476 /*-----------------------------------------------------------------*/
8478 shiftLLeftOrResult (operand * left, int offl,
8479 operand * result, int offr, int shCount)
8481 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8482 /* shift left accumulator */
8484 /* or with result */
8485 emitcode ("orl", "a,%s",
8486 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8487 /* back to result */
8488 aopPut (AOP (result), "a", offr);
8493 /*-----------------------------------------------------------------*/
8494 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8495 /*-----------------------------------------------------------------*/
8497 shiftRLeftOrResult (operand * left, int offl,
8498 operand * result, int offr, int shCount)
8500 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8501 /* shift right accumulator */
8503 /* or with result */
8504 emitcode ("orl", "a,%s",
8505 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8506 /* back to result */
8507 aopPut (AOP (result), "a", offr);
8511 #ifdef BETTER_LITERAL_SHIFT
8512 /*-----------------------------------------------------------------*/
8513 /* genlshOne - left shift a one byte quantity by known count */
8514 /*-----------------------------------------------------------------*/
8516 genlshOne (operand * result, operand * left, int shCount)
8518 D (emitcode (";", "genlshOne "););
8519 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8523 #ifdef BETTER_LITERAL_SHIFT
8524 /*-----------------------------------------------------------------*/
8525 /* genlshTwo - left shift two bytes by known amount != 0 */
8526 /*-----------------------------------------------------------------*/
8528 genlshTwo (operand * result, operand * left, int shCount)
8532 D (emitcode (";", "genlshTwo "););
8534 size = getDataSize (result);
8536 /* if shCount >= 8 */
8541 _startLazyDPSEvaluation();
8547 _endLazyDPSEvaluation();
8548 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8549 aopPut (AOP (result), zero, LSB);
8553 movLeft2Result (left, LSB, result, MSB16, 0);
8554 aopPut (AOP (result), zero, LSB);
8555 _endLazyDPSEvaluation();
8560 aopPut (AOP (result), zero, LSB);
8561 _endLazyDPSEvaluation();
8565 /* 1 <= shCount <= 7 */
8570 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8574 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8582 /*-----------------------------------------------------------------*/
8583 /* shiftLLong - shift left one long from left to result */
8584 /* offl = LSB or MSB16 */
8585 /*-----------------------------------------------------------------*/
8587 shiftLLong (operand * left, operand * result, int offr)
8590 int size = AOP_SIZE (result);
8592 if (size >= LSB + offr)
8594 l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8596 emitcode ("add", "a,acc");
8597 if (sameRegs (AOP (left), AOP (result)) &&
8598 size >= MSB16 + offr && offr != LSB)
8599 emitcode ("xch", "a,%s",
8600 aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8602 aopPut (AOP (result), "a", LSB + offr);
8605 if (size >= MSB16 + offr)
8607 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8609 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8611 emitcode ("rlc", "a");
8612 if (sameRegs (AOP (left), AOP (result)) &&
8613 size >= MSB24 + offr && offr != LSB)
8614 emitcode ("xch", "a,%s",
8615 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8617 aopPut (AOP (result), "a", MSB16 + offr);
8620 if (size >= MSB24 + offr)
8622 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8624 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8626 emitcode ("rlc", "a");
8627 if (sameRegs (AOP (left), AOP (result)) &&
8628 size >= MSB32 + offr && offr != LSB)
8629 emitcode ("xch", "a,%s",
8630 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8632 aopPut (AOP (result), "a", MSB24 + offr);
8635 if (size > MSB32 + offr)
8637 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8639 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8641 emitcode ("rlc", "a");
8642 aopPut (AOP (result), "a", MSB32 + offr);
8645 aopPut (AOP (result), zero, LSB);
8651 /*-----------------------------------------------------------------*/
8652 /* genlshFour - shift four byte by a known amount != 0 */
8653 /*-----------------------------------------------------------------*/
8655 genlshFour (operand * result, operand * left, int shCount)
8659 D (emitcode (";", "genlshFour ");
8662 size = AOP_SIZE (result);
8664 /* if shifting more that 3 bytes */
8669 /* lowest order of left goes to the highest
8670 order of the destination */
8671 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8673 movLeft2Result (left, LSB, result, MSB32, 0);
8674 aopPut (AOP (result), zero, LSB);
8675 aopPut (AOP (result), zero, MSB16);
8676 aopPut (AOP (result), zero, MSB24);
8680 /* more than two bytes */
8681 else if (shCount >= 16)
8683 /* lower order two bytes goes to higher order two bytes */
8685 /* if some more remaining */
8687 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8690 movLeft2Result (left, MSB16, result, MSB32, 0);
8691 movLeft2Result (left, LSB, result, MSB24, 0);
8693 aopPut (AOP (result), zero, MSB16);
8694 aopPut (AOP (result), zero, LSB);
8698 /* if more than 1 byte */
8699 else if (shCount >= 8)
8701 /* lower order three bytes goes to higher order three bytes */
8706 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8708 movLeft2Result (left, LSB, result, MSB16, 0);
8714 movLeft2Result (left, MSB24, result, MSB32, 0);
8715 movLeft2Result (left, MSB16, result, MSB24, 0);
8716 movLeft2Result (left, LSB, result, MSB16, 0);
8717 aopPut (AOP (result), zero, LSB);
8719 else if (shCount == 1)
8720 shiftLLong (left, result, MSB16);
8723 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8724 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8725 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8726 aopPut (AOP (result), zero, LSB);
8731 /* 1 <= shCount <= 7 */
8732 else if (shCount <= 2)
8734 shiftLLong (left, result, LSB);
8736 shiftLLong (result, result, LSB);
8738 /* 3 <= shCount <= 7, optimize */
8741 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8742 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8743 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8748 #ifdef BETTER_LITERAL_SHIFT
8749 /*-----------------------------------------------------------------*/
8750 /* genLeftShiftLiteral - left shifting by known count */
8751 /*-----------------------------------------------------------------*/
8753 genLeftShiftLiteral (operand * left,
8758 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8761 size = getSize (operandType (result));
8763 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8765 /* We only handle certain easy cases so far. */
8767 && (shCount < (size * 8))
8771 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8775 freeAsmop (right, NULL, ic, TRUE);
8777 aopOp(left, ic, FALSE, FALSE);
8778 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8781 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8783 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8784 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8786 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8789 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8791 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8792 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8794 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8800 emitcode ("; shift left ", "result %d, left %d", size,
8804 /* I suppose that the left size >= result size */
8807 _startLazyDPSEvaluation();
8810 movLeft2Result (left, size, result, size, 0);
8812 _endLazyDPSEvaluation();
8814 else if (shCount >= (size * 8))
8816 _startLazyDPSEvaluation();
8819 aopPut (AOP (result), zero, size);
8821 _endLazyDPSEvaluation();
8828 genlshOne (result, left, shCount);
8832 genlshTwo (result, left, shCount);
8836 genlshFour (result, left, shCount);
8840 fprintf(stderr, "*** ack! mystery literal shift!\n");
8844 freeAsmop (left, NULL, ic, TRUE);
8845 freeAsmop (result, NULL, ic, TRUE);
8850 /*-----------------------------------------------------------------*/
8851 /* genLeftShift - generates code for left shifting */
8852 /*-----------------------------------------------------------------*/
8854 genLeftShift (iCode * ic)
8856 operand *left, *right, *result;
8859 symbol *tlbl, *tlbl1;
8861 D (emitcode (";", "genLeftShift "););
8863 right = IC_RIGHT (ic);
8864 left = IC_LEFT (ic);
8865 result = IC_RESULT (ic);
8867 aopOp (right, ic, FALSE, FALSE);
8870 #ifdef BETTER_LITERAL_SHIFT
8871 /* if the shift count is known then do it
8872 as efficiently as possible */
8873 if (AOP_TYPE (right) == AOP_LIT)
8875 if (genLeftShiftLiteral (left, right, result, ic))
8882 /* shift count is unknown then we have to form
8883 a loop get the loop count in B : Note: we take
8884 only the lower order byte since shifting
8885 more that 32 bits make no sense anyway, ( the
8886 largest size of an object can be only 32 bits ) */
8888 if (AOP_TYPE (right) == AOP_LIT)
8890 /* Really should be handled by genLeftShiftLiteral,
8891 * but since I'm too lazy to fix that today, at least we can make
8892 * some small improvement.
8894 emitcode("mov", "b,#!constbyte",
8895 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8899 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8900 emitcode ("inc", "b");
8902 freeAsmop (right, NULL, ic, TRUE);
8903 aopOp (left, ic, FALSE, FALSE);
8904 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8906 /* now move the left to the result if they are not the
8908 if (!sameRegs (AOP (left), AOP (result)) &&
8909 AOP_SIZE (result) > 1)
8912 size = AOP_SIZE (result);
8914 _startLazyDPSEvaluation ();
8917 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8918 if (*l == '@' && (IS_AOP_PREG (result)))
8921 emitcode ("mov", "a,%s", l);
8922 aopPut (AOP (result), "a", offset);
8925 aopPut (AOP (result), l, offset);
8928 _endLazyDPSEvaluation ();
8931 tlbl = newiTempLabel (NULL);
8932 size = AOP_SIZE (result);
8934 tlbl1 = newiTempLabel (NULL);
8936 /* if it is only one byte then */
8939 symbol *tlbl1 = newiTempLabel (NULL);
8941 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8942 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8943 emitcode ("", "!tlabeldef", tlbl->key + 100);
8944 emitcode ("add", "a,acc");
8945 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8946 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8947 aopPut (AOP (result), "a", 0);
8951 reAdjustPreg (AOP (result));
8953 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8954 emitcode ("", "!tlabeldef", tlbl->key + 100);
8955 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8956 emitcode ("add", "a,acc");
8957 aopPut (AOP (result), "a", offset++);
8958 _startLazyDPSEvaluation ();
8961 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8962 emitcode ("rlc", "a");
8963 aopPut (AOP (result), "a", offset++);
8965 _endLazyDPSEvaluation ();
8966 reAdjustPreg (AOP (result));
8968 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8969 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8971 freeAsmop (left, NULL, ic, TRUE);
8972 freeAsmop (result, NULL, ic, TRUE);
8975 #ifdef BETTER_LITERAL_SHIFT
8976 /*-----------------------------------------------------------------*/
8977 /* genrshOne - right shift a one byte quantity by known count */
8978 /*-----------------------------------------------------------------*/
8980 genrshOne (operand * result, operand * left,
8981 int shCount, int sign)
8983 D (emitcode (";", "genrshOne"););
8984 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8988 #ifdef BETTER_LITERAL_SHIFT
8989 /*-----------------------------------------------------------------*/
8990 /* genrshTwo - right shift two bytes by known amount != 0 */
8991 /*-----------------------------------------------------------------*/
8993 genrshTwo (operand * result, operand * left,
8994 int shCount, int sign)
8996 D (emitcode (";", "genrshTwo"););
8998 /* if shCount >= 8 */
9002 _startLazyDPSEvaluation();
9005 shiftR1Left2Result (left, MSB16, result, LSB,
9010 movLeft2Result (left, MSB16, result, LSB, sign);
9012 addSign (result, MSB16, sign);
9013 _endLazyDPSEvaluation();
9016 /* 1 <= shCount <= 7 */
9019 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9024 /*-----------------------------------------------------------------*/
9025 /* shiftRLong - shift right one long from left to result */
9026 /* offl = LSB or MSB16 */
9027 /*-----------------------------------------------------------------*/
9029 shiftRLong (operand * left, int offl,
9030 operand * result, int sign)
9032 int isSameRegs=sameRegs(AOP(left),AOP(result));
9034 if (isSameRegs && offl>1) {
9035 // we are in big trouble, but this shouldn't happen
9036 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9039 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
9044 emitcode ("rlc", "a");
9045 emitcode ("subb", "a,acc");
9046 emitcode ("xch", "a,%s",
9047 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
9049 aopPut (AOP(result), zero, MSB32);
9054 emitcode ("clr", "c");
9056 emitcode ("mov", "c,acc.7");
9059 emitcode ("rrc", "a");
9061 if (isSameRegs && offl==MSB16) {
9063 "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
9065 aopPut (AOP (result), "a", MSB32);
9066 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
9069 emitcode ("rrc", "a");
9070 if (isSameRegs && offl==1) {
9071 emitcode ("xch", "a,%s",
9072 aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
9074 aopPut (AOP (result), "a", MSB24);
9075 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
9077 emitcode ("rrc", "a");
9078 aopPut (AOP (result), "a", MSB16 - offl);
9082 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
9083 emitcode ("rrc", "a");
9084 aopPut (AOP (result), "a", LSB);
9088 /*-----------------------------------------------------------------*/
9089 /* genrshFour - shift four byte by a known amount != 0 */
9090 /*-----------------------------------------------------------------*/
9092 genrshFour (operand * result, operand * left,
9093 int shCount, int sign)
9095 D (emitcode (";", "genrshFour"););
9097 /* if shifting more that 3 bytes */
9101 _startLazyDPSEvaluation();
9103 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9105 movLeft2Result (left, MSB32, result, LSB, sign);
9106 addSign (result, MSB16, sign);
9107 _endLazyDPSEvaluation();
9109 else if (shCount >= 16)
9112 _startLazyDPSEvaluation();
9114 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9117 movLeft2Result (left, MSB24, result, LSB, 0);
9118 movLeft2Result (left, MSB32, result, MSB16, sign);
9120 addSign (result, MSB24, sign);
9121 _endLazyDPSEvaluation();
9123 else if (shCount >= 8)
9126 _startLazyDPSEvaluation();
9129 shiftRLong (left, MSB16, result, sign);
9131 else if (shCount == 0)
9133 movLeft2Result (left, MSB16, result, LSB, 0);
9134 movLeft2Result (left, MSB24, result, MSB16, 0);
9135 movLeft2Result (left, MSB32, result, MSB24, sign);
9136 addSign (result, MSB32, sign);
9140 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9141 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9142 /* the last shift is signed */
9143 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9144 addSign (result, MSB32, sign);
9146 _endLazyDPSEvaluation();
9150 /* 1 <= shCount <= 7 */
9153 shiftRLong (left, LSB, result, sign);
9155 shiftRLong (result, LSB, result, sign);
9159 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9160 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9161 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9166 #ifdef BETTER_LITERAL_SHIFT
9167 /*-----------------------------------------------------------------*/
9168 /* genRightShiftLiteral - right shifting by known count */
9169 /*-----------------------------------------------------------------*/
9171 genRightShiftLiteral (operand * left,
9177 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9180 size = getSize (operandType (result));
9182 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
9184 /* We only handle certain easy cases so far. */
9186 && (shCount < (size * 8))
9191 D(emitcode (";", "genRightShiftLiteral wimping out"););
9195 freeAsmop (right, NULL, ic, TRUE);
9197 aopOp (left, ic, FALSE, FALSE);
9198 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9201 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9205 /* test the LEFT size !!! */
9207 /* I suppose that the left size >= result size */
9210 size = getDataSize (result);
9211 _startLazyDPSEvaluation();
9214 movLeft2Result (left, size, result, size, 0);
9216 _endLazyDPSEvaluation();
9218 else if (shCount >= (size * 8))
9222 /* get sign in acc.7 */
9223 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
9225 addSign (result, LSB, sign);
9232 genrshOne (result, left, shCount, sign);
9236 genrshTwo (result, left, shCount, sign);
9240 genrshFour (result, left, shCount, sign);
9247 freeAsmop (left, NULL, ic, TRUE);
9248 freeAsmop (result, NULL, ic, TRUE);
9254 /*-----------------------------------------------------------------*/
9255 /* genSignedRightShift - right shift of signed number */
9256 /*-----------------------------------------------------------------*/
9258 genSignedRightShift (iCode * ic)
9260 operand *right, *left, *result;
9263 symbol *tlbl, *tlbl1;
9265 D (emitcode (";", "genSignedRightShift "););
9267 /* we do it the hard way put the shift count in b
9268 and loop thru preserving the sign */
9270 right = IC_RIGHT (ic);
9271 left = IC_LEFT (ic);
9272 result = IC_RESULT (ic);
9274 aopOp (right, ic, FALSE, FALSE);
9276 #ifdef BETTER_LITERAL_SHIFT
9277 if (AOP_TYPE (right) == AOP_LIT)
9279 if (genRightShiftLiteral (left, right, result, ic, 1))
9285 /* shift count is unknown then we have to form
9286 a loop get the loop count in B : Note: we take
9287 only the lower order byte since shifting
9288 more that 32 bits make no sense anyway, ( the
9289 largest size of an object can be only 32 bits ) */
9291 if (AOP_TYPE (right) == AOP_LIT)
9293 /* Really should be handled by genRightShiftLiteral,
9294 * but since I'm too lazy to fix that today, at least we can make
9295 * some small improvement.
9297 emitcode("mov", "b,#!constbyte",
9298 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9302 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9303 emitcode ("inc", "b");
9305 freeAsmop (right, NULL, ic, TRUE);
9306 aopOp (left, ic, FALSE, FALSE);
9307 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9309 /* now move the left to the result if they are not the
9311 if (!sameRegs (AOP (left), AOP (result)) &&
9312 AOP_SIZE (result) > 1)
9315 size = AOP_SIZE (result);
9317 _startLazyDPSEvaluation ();
9320 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9321 if (*l == '@' && IS_AOP_PREG (result))
9324 emitcode ("mov", "a,%s", l);
9325 aopPut (AOP (result), "a", offset);
9328 aopPut (AOP (result), l, offset);
9331 _endLazyDPSEvaluation ();
9334 /* mov the highest order bit to OVR */
9335 tlbl = newiTempLabel (NULL);
9336 tlbl1 = newiTempLabel (NULL);
9338 size = AOP_SIZE (result);
9340 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
9341 emitcode ("rlc", "a");
9342 emitcode ("mov", "ov,c");
9343 /* if it is only one byte then */
9346 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9347 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9348 emitcode ("", "!tlabeldef", tlbl->key + 100);
9349 emitcode ("mov", "c,ov");
9350 emitcode ("rrc", "a");
9351 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9352 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9353 aopPut (AOP (result), "a", 0);
9357 reAdjustPreg (AOP (result));
9358 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9359 emitcode ("", "!tlabeldef", tlbl->key + 100);
9360 emitcode ("mov", "c,ov");
9361 _startLazyDPSEvaluation ();
9364 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9365 emitcode ("rrc", "a");
9366 aopPut (AOP (result), "a", offset--);
9368 _endLazyDPSEvaluation ();
9369 reAdjustPreg (AOP (result));
9370 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9371 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9374 freeAsmop (left, NULL, ic, TRUE);
9375 freeAsmop (result, NULL, ic, TRUE);
9378 /*-----------------------------------------------------------------*/
9379 /* genRightShift - generate code for right shifting */
9380 /*-----------------------------------------------------------------*/
9382 genRightShift (iCode * ic)
9384 operand *right, *left, *result;
9388 symbol *tlbl, *tlbl1;
9390 D (emitcode (";", "genRightShift "););
9392 /* if signed then we do it the hard way preserve the
9393 sign bit moving it inwards */
9394 letype = getSpec (operandType (IC_LEFT (ic)));
9396 if (!SPEC_USIGN (letype))
9398 genSignedRightShift (ic);
9402 /* signed & unsigned types are treated the same : i.e. the
9403 signed is NOT propagated inwards : quoting from the
9404 ANSI - standard : "for E1 >> E2, is equivalent to division
9405 by 2**E2 if unsigned or if it has a non-negative value,
9406 otherwise the result is implementation defined ", MY definition
9407 is that the sign does not get propagated */
9409 right = IC_RIGHT (ic);
9410 left = IC_LEFT (ic);
9411 result = IC_RESULT (ic);
9413 aopOp (right, ic, FALSE, FALSE);
9415 #ifdef BETTER_LITERAL_SHIFT
9416 /* if the shift count is known then do it
9417 as efficiently as possible */
9418 if (AOP_TYPE (right) == AOP_LIT)
9420 if (genRightShiftLiteral (left, right, result, ic, 0))
9427 /* shift count is unknown then we have to form
9428 a loop get the loop count in B : Note: we take
9429 only the lower order byte since shifting
9430 more that 32 bits make no sense anyway, ( the
9431 largest size of an object can be only 32 bits ) */
9433 if (AOP_TYPE (right) == AOP_LIT)
9435 /* Really should be handled by genRightShiftLiteral,
9436 * but since I'm too lazy to fix that today, at least we can make
9437 * some small improvement.
9439 emitcode("mov", "b,#!constbyte",
9440 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9444 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9445 emitcode ("inc", "b");
9447 freeAsmop (right, NULL, ic, TRUE);
9448 aopOp (left, ic, FALSE, FALSE);
9449 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9451 /* now move the left to the result if they are not the
9453 if (!sameRegs (AOP (left), AOP (result)) &&
9454 AOP_SIZE (result) > 1)
9457 size = AOP_SIZE (result);
9459 _startLazyDPSEvaluation ();
9462 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9463 if (*l == '@' && IS_AOP_PREG (result))
9466 emitcode ("mov", "a,%s", l);
9467 aopPut (AOP (result), "a", offset);
9470 aopPut (AOP (result), l, offset);
9473 _endLazyDPSEvaluation ();
9476 tlbl = newiTempLabel (NULL);
9477 tlbl1 = newiTempLabel (NULL);
9478 size = AOP_SIZE (result);
9481 /* if it is only one byte then */
9484 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9485 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9486 emitcode ("", "!tlabeldef", tlbl->key + 100);
9488 emitcode ("rrc", "a");
9489 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9490 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9491 aopPut (AOP (result), "a", 0);
9495 reAdjustPreg (AOP (result));
9496 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9497 emitcode ("", "!tlabeldef", tlbl->key + 100);
9499 _startLazyDPSEvaluation ();
9502 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9503 emitcode ("rrc", "a");
9504 aopPut (AOP (result), "a", offset--);
9506 _endLazyDPSEvaluation ();
9507 reAdjustPreg (AOP (result));
9509 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9510 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9513 freeAsmop (left, NULL, ic, TRUE);
9514 freeAsmop (result, NULL, ic, TRUE);
9518 /*-----------------------------------------------------------------*/
9519 /* emitPtrByteGet - emits code to get a byte into A through a */
9520 /* pointer register (R0, R1, or DPTR). The */
9521 /* original value of A can be preserved in B. */
9522 /*-----------------------------------------------------------------*/
9524 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9531 emitcode ("mov", "b,a");
9532 emitcode ("mov", "a,@%s", rname);
9537 emitcode ("mov", "b,a");
9538 emitcode ("movx", "a,@%s", rname);
9543 emitcode ("mov", "b,a");
9544 emitcode ("movx", "a,@dptr");
9549 emitcode ("mov", "b,a");
9550 emitcode ("clr", "a");
9551 emitcode ("movc", "a,@a+dptr");
9557 emitcode ("push", "b");
9558 emitcode ("push", "acc");
9560 emitcode ("lcall", "__gptrget");
9562 emitcode ("pop", "b");
9567 /*-----------------------------------------------------------------*/
9568 /* emitPtrByteSet - emits code to set a byte from src through a */
9569 /* pointer register (R0, R1, or DPTR). */
9570 /*-----------------------------------------------------------------*/
9572 emitPtrByteSet (char *rname, int p_type, char *src)
9581 emitcode ("mov", "@%s,a", rname);
9584 emitcode ("mov", "@%s,%s", rname, src);
9589 emitcode ("movx", "@%s,a", rname);
9594 emitcode ("movx", "@dptr,a");
9599 emitcode ("lcall", "__gptrput");
9604 /*-----------------------------------------------------------------*/
9605 /* genUnpackBits - generates code for unpacking bits */
9606 /*-----------------------------------------------------------------*/
9608 genUnpackBits (operand * result, char *rname, int ptype)
9610 int offset = 0; /* result byte offset */
9611 int rsize; /* result size */
9612 int rlen = 0; /* remaining bitfield length */
9613 sym_link *etype; /* bitfield type information */
9614 int blen; /* bitfield length */
9615 int bstr; /* bitfield starting bit within byte */
9617 D(emitcode ("; genUnpackBits",""));
9619 etype = getSpec (operandType (result));
9620 rsize = getSize (operandType (result));
9621 blen = SPEC_BLEN (etype);
9622 bstr = SPEC_BSTR (etype);
9624 /* If the bitfield length is less than a byte */
9627 emitPtrByteGet (rname, ptype, FALSE);
9629 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9630 aopPut (AOP (result), "a", offset++);
9634 /* Bit field did not fit in a byte. Copy all
9635 but the partial byte at the end. */
9636 for (rlen=blen;rlen>=8;rlen-=8)
9638 emitPtrByteGet (rname, ptype, FALSE);
9639 aopPut (AOP (result), "a", offset++);
9641 emitcode ("inc", "%s", rname);
9644 /* Handle the partial byte at the end */
9647 emitPtrByteGet (rname, ptype, FALSE);
9648 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9649 aopPut (AOP (result), "a", offset++);
9657 aopPut (AOP (result), zero, offset++);
9662 /*-----------------------------------------------------------------*/
9663 /* genDataPointerGet - generates code when ptr offset is known */
9664 /*-----------------------------------------------------------------*/
9666 genDataPointerGet (operand * left,
9672 int size, offset = 0;
9673 aopOp (result, ic, TRUE, FALSE);
9675 /* get the string representation of the name */
9676 l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9677 size = AOP_SIZE (result);
9678 _startLazyDPSEvaluation ();
9683 SNPRINTF (buff, sizeof(buff),
9684 "(%s + %d)", l + 1, offset);
9688 SNPRINTF (buff, sizeof(buff),
9691 aopPut (AOP (result), buff, offset++);
9693 _endLazyDPSEvaluation ();
9695 freeAsmop (left, NULL, ic, TRUE);
9696 freeAsmop (result, NULL, ic, TRUE);
9699 /*-----------------------------------------------------------------*/
9700 /* genNearPointerGet - emitcode for near pointer fetch */
9701 /*-----------------------------------------------------------------*/
9703 genNearPointerGet (operand * left,
9711 sym_link *rtype, *retype, *letype;
9712 sym_link *ltype = operandType (left);
9715 rtype = operandType (result);
9716 retype = getSpec (rtype);
9717 letype = getSpec (ltype);
9719 aopOp (left, ic, FALSE, FALSE);
9721 /* if left is rematerialisable and
9722 result is not bitfield variable type and
9723 the left is pointer to data space i.e
9724 lower 128 bytes of space */
9725 if (AOP_TYPE (left) == AOP_IMMD &&
9726 !IS_BITFIELD (retype) &&
9727 !IS_BITFIELD (letype) &&
9728 DCL_TYPE (ltype) == POINTER)
9730 genDataPointerGet (left, result, ic);
9734 /* if the value is already in a pointer register
9735 then don't need anything more */
9736 if (!AOP_INPREG (AOP (left)))
9738 /* otherwise get a free pointer register */
9740 preg = getFreePtr (ic, &aop, FALSE);
9741 emitcode ("mov", "%s,%s",
9743 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9747 rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9749 freeAsmop (left, NULL, ic, TRUE);
9750 aopOp (result, ic, FALSE, FALSE);
9752 /* if bitfield then unpack the bits */
9753 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9754 genUnpackBits (result, rname, POINTER);
9757 /* we have can just get the values */
9758 int size = AOP_SIZE (result);
9763 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9766 emitcode ("mov", "a,@%s", rname);
9767 aopPut (AOP (result), "a", offset);
9771 SNPRINTF (buff, sizeof(buff), "@%s", rname);
9772 aopPut (AOP (result), buff, offset);
9777 emitcode ("inc", "%s", rname);
9782 /* now some housekeeping stuff */
9785 /* we had to allocate for this iCode */
9786 if (pi) { /* post increment present */
9787 aopPut(AOP ( left ),rname,0);
9789 freeAsmop (NULL, aop, ic, TRUE);
9793 /* we did not allocate which means left
9794 already in a pointer register, then
9795 if size > 0 && this could be used again
9796 we have to point it back to where it
9798 if (AOP_SIZE (result) > 1 &&
9799 !OP_SYMBOL (left)->remat &&
9800 (OP_SYMBOL (left)->liveTo > ic->seq ||
9804 int size = AOP_SIZE (result) - 1;
9806 emitcode ("dec", "%s", rname);
9811 freeAsmop (result, NULL, ic, TRUE);
9812 if (pi) pi->generated = 1;
9815 /*-----------------------------------------------------------------*/
9816 /* genPagedPointerGet - emitcode for paged pointer fetch */
9817 /*-----------------------------------------------------------------*/
9819 genPagedPointerGet (operand * left,
9827 sym_link *rtype, *retype, *letype;
9829 rtype = operandType (result);
9830 retype = getSpec (rtype);
9831 letype = getSpec (operandType (left));
9832 aopOp (left, ic, FALSE, FALSE);
9834 /* if the value is already in a pointer register
9835 then don't need anything more */
9836 if (!AOP_INPREG (AOP (left)))
9838 /* otherwise get a free pointer register */
9840 preg = getFreePtr (ic, &aop, FALSE);
9841 emitcode ("mov", "%s,%s",
9843 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9847 rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9849 freeAsmop (left, NULL, ic, TRUE);
9850 aopOp (result, ic, FALSE, FALSE);
9852 /* if bitfield then unpack the bits */
9853 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9854 genUnpackBits (result, rname, PPOINTER);
9857 /* we have can just get the values */
9858 int size = AOP_SIZE (result);
9864 emitcode ("movx", "a,@%s", rname);
9865 aopPut (AOP (result), "a", offset);
9870 emitcode ("inc", "%s", rname);
9874 /* now some housekeeping stuff */
9877 /* we had to allocate for this iCode */
9878 if (pi) aopPut ( AOP (left), rname, 0);
9879 freeAsmop (NULL, aop, ic, TRUE);
9883 /* we did not allocate which means left
9884 already in a pointer register, then
9885 if size > 0 && this could be used again
9886 we have to point it back to where it
9888 if (AOP_SIZE (result) > 1 &&
9889 !OP_SYMBOL (left)->remat &&
9890 (OP_SYMBOL (left)->liveTo > ic->seq ||
9894 int size = AOP_SIZE (result) - 1;
9896 emitcode ("dec", "%s", rname);
9901 freeAsmop (result, NULL, ic, TRUE);
9902 if (pi) pi->generated = 1;
9905 /*-----------------------------------------------------------------*/
9906 /* genFarPointerGet - gget value from far space */
9907 /*-----------------------------------------------------------------*/
9909 genFarPointerGet (operand * left,
9910 operand * result, iCode * ic, iCode *pi)
9912 int size, offset, dopi=1;
9913 sym_link *retype = getSpec (operandType (result));
9914 sym_link *letype = getSpec (operandType (left));
9915 D (emitcode (";", "genFarPointerGet"););
9917 aopOp (left, ic, FALSE, FALSE);
9919 /* if the operand is already in dptr
9920 then we do nothing else we move the value to dptr */
9921 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9923 /* if this is remateriazable */
9924 if (AOP_TYPE (left) == AOP_IMMD)
9926 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9930 /* we need to get it byte by byte */
9931 _startLazyDPSEvaluation ();
9932 if (AOP_TYPE (left) != AOP_DPTR)
9934 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9935 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9936 if (options.model == MODEL_FLAT24)
9937 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9941 /* We need to generate a load to DPTR indirect through DPTR. */
9942 D (emitcode (";", "genFarPointerGet -- indirection special case."););
9943 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9944 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9945 if (options.model == MODEL_FLAT24)
9946 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9947 emitcode ("pop", "dph");
9948 emitcode ("pop", "dpl");
9951 _endLazyDPSEvaluation ();
9954 /* so dptr know contains the address */
9955 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9957 /* if bit then unpack */
9958 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9959 if (AOP_INDPTRn(left)) {
9960 genSetDPTR(AOP(left)->aopu.dptr);
9962 genUnpackBits (result, "dptr", FPOINTER);
9963 if (AOP_INDPTRn(left)) {
9968 size = AOP_SIZE (result);
9971 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9973 genSetDPTR(AOP(left)->aopu.dptr);
9974 emitcode ("movx", "a,@dptr");
9975 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9976 emitcode ("inc", "dptr");
9978 aopPut (AOP (result), "a", offset++);
9981 _startLazyDPSEvaluation ();
9983 if (AOP_INDPTRn(left)) {
9984 genSetDPTR(AOP(left)->aopu.dptr);
9990 emitcode ("movx", "a,@dptr");
9991 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9992 emitcode ("inc", "dptr");
9994 aopPut (AOP (result), "a", offset++);
9996 _endLazyDPSEvaluation ();
9999 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10000 if (!AOP_INDPTRn(left)) {
10001 _startLazyDPSEvaluation ();
10002 aopPut ( AOP (left), "dpl", 0);
10003 aopPut ( AOP (left), "dph", 1);
10004 if (options.model == MODEL_FLAT24)
10005 aopPut ( AOP (left), "dpx", 2);
10006 _endLazyDPSEvaluation ();
10009 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
10010 AOP_SIZE(result) > 1 &&
10012 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
10014 size = AOP_SIZE (result) - 1;
10015 if (AOP_INDPTRn(left)) {
10016 genSetDPTR(AOP(left)->aopu.dptr);
10018 while (size--) emitcode ("lcall","__decdptr");
10019 if (AOP_INDPTRn(left)) {
10024 freeAsmop (left, NULL, ic, TRUE);
10025 freeAsmop (result, NULL, ic, TRUE);
10028 /*-----------------------------------------------------------------*/
10029 /* genCodePointerGet - get value from code space */
10030 /*-----------------------------------------------------------------*/
10032 genCodePointerGet (operand * left,
10033 operand * result, iCode * ic, iCode *pi)
10035 int size, offset, dopi=1;
10036 sym_link *retype = getSpec (operandType (result));
10038 aopOp (left, ic, FALSE, FALSE);
10040 /* if the operand is already in dptr
10041 then we do nothing else we move the value to dptr */
10042 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
10044 /* if this is remateriazable */
10045 if (AOP_TYPE (left) == AOP_IMMD)
10047 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10050 { /* we need to get it byte by byte */
10051 _startLazyDPSEvaluation ();
10052 if (AOP_TYPE (left) != AOP_DPTR)
10054 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10055 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10056 if (options.model == MODEL_FLAT24)
10057 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10061 /* We need to generate a load to DPTR indirect through DPTR. */
10062 D (emitcode (";", "gencodePointerGet -- indirection special case."););
10063 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
10064 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
10065 if (options.model == MODEL_FLAT24)
10066 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10067 emitcode ("pop", "dph");
10068 emitcode ("pop", "dpl");
10071 _endLazyDPSEvaluation ();
10074 /* so dptr know contains the address */
10075 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10077 /* if bit then unpack */
10078 if (IS_BITFIELD (retype)) {
10079 if (AOP_INDPTRn(left)) {
10080 genSetDPTR(AOP(left)->aopu.dptr);
10082 genUnpackBits (result, "dptr", CPOINTER);
10083 if (AOP_INDPTRn(left)) {
10088 size = AOP_SIZE (result);
10090 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10092 genSetDPTR(AOP(left)->aopu.dptr);
10093 emitcode ("clr", "a");
10094 emitcode ("movc", "a,@a+dptr");
10095 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10096 emitcode ("inc", "dptr");
10098 aopPut (AOP (result), "a", offset++);
10101 _startLazyDPSEvaluation ();
10104 if (AOP_INDPTRn(left)) {
10105 genSetDPTR(AOP(left)->aopu.dptr);
10111 emitcode ("clr", "a");
10112 emitcode ("movc", "a,@a+dptr");
10113 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10114 emitcode ("inc", "dptr");
10115 aopPut (AOP (result), "a", offset++);
10117 _endLazyDPSEvaluation ();
10120 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10121 if (!AOP_INDPTRn(left)) {
10122 _startLazyDPSEvaluation ();
10124 aopPut ( AOP (left), "dpl", 0);
10125 aopPut ( AOP (left), "dph", 1);
10126 if (options.model == MODEL_FLAT24)
10127 aopPut ( AOP (left), "dpx", 2);
10129 _endLazyDPSEvaluation ();
10132 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
10133 AOP_SIZE(result) > 1 &&
10134 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10136 size = AOP_SIZE (result) - 1;
10137 if (AOP_INDPTRn(left)) {
10138 genSetDPTR(AOP(left)->aopu.dptr);
10140 while (size--) emitcode ("lcall","__decdptr");
10141 if (AOP_INDPTRn(left)) {
10146 freeAsmop (left, NULL, ic, TRUE);
10147 freeAsmop (result, NULL, ic, TRUE);
10150 /*-----------------------------------------------------------------*/
10151 /* genGenPointerGet - gget value from generic pointer space */
10152 /*-----------------------------------------------------------------*/
10154 genGenPointerGet (operand * left,
10155 operand * result, iCode * ic, iCode * pi)
10158 sym_link *retype = getSpec (operandType (result));
10159 sym_link *letype = getSpec (operandType (left));
10161 D (emitcode (";", "genGenPointerGet "); );
10163 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
10165 /* if the operand is already in dptr
10166 then we do nothing else we move the value to dptr */
10167 if (AOP_TYPE (left) != AOP_STR)
10169 /* if this is remateriazable */
10170 if (AOP_TYPE (left) == AOP_IMMD)
10172 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10173 if (AOP(left)->aopu.aop_immd.from_cast_remat)
10175 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
10179 emitcode ("mov", "b,#%d", pointerCode (retype));
10183 { /* we need to get it byte by byte */
10184 _startLazyDPSEvaluation ();
10185 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
10186 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
10187 if (options.model == MODEL_FLAT24) {
10188 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10189 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
10191 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10193 _endLazyDPSEvaluation ();
10197 /* so dptr-b now contains the address */
10199 aopOp (result, ic, FALSE, TRUE);
10202 /* if bit then unpack */
10203 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10205 genUnpackBits (result, "dptr", GPOINTER);
10209 size = AOP_SIZE (result);
10216 // Get two bytes at a time, results in _AP & A.
10217 // dptr will be incremented ONCE by __gptrgetWord.
10219 // Note: any change here must be coordinated
10220 // with the implementation of __gptrgetWord
10221 // in device/lib/_gptrget.c
10222 emitcode ("lcall", "__gptrgetWord");
10223 aopPut (AOP (result), DP2_RESULT_REG, offset++);
10224 aopPut (AOP (result), "a", offset++);
10229 // Only one byte to get.
10230 emitcode ("lcall", "__gptrget");
10231 aopPut (AOP (result), "a", offset++);
10234 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
10236 emitcode ("inc", "dptr");
10241 if (pi && AOP_TYPE (left) != AOP_IMMD) {
10242 _startLazyDPSEvaluation ();
10244 aopPut ( AOP (left), "dpl", 0);
10245 aopPut ( AOP (left), "dph", 1);
10246 if (options.model == MODEL_FLAT24) {
10247 aopPut ( AOP (left), "dpx", 2);
10248 aopPut ( AOP (left), "b", 3);
10249 } else aopPut ( AOP (left), "b", 2);
10251 _endLazyDPSEvaluation ();
10254 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
10255 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10257 size = AOP_SIZE (result) - 1;
10258 while (size--) emitcode ("lcall","__decdptr");
10261 freeAsmop (left, NULL, ic, TRUE);
10262 freeAsmop (result, NULL, ic, TRUE);
10265 /*-----------------------------------------------------------------*/
10266 /* genPointerGet - generate code for pointer get */
10267 /*-----------------------------------------------------------------*/
10269 genPointerGet (iCode * ic, iCode *pi)
10271 operand *left, *result;
10272 sym_link *type, *etype;
10275 D (emitcode (";", "genPointerGet ");
10278 left = IC_LEFT (ic);
10279 result = IC_RESULT (ic);
10281 /* depending on the type of pointer we need to
10282 move it to the correct pointer register */
10283 type = operandType (left);
10284 etype = getSpec (type);
10285 /* if left is of type of pointer then it is simple */
10286 if (IS_PTR (type) && !IS_FUNC (type->next))
10287 p_type = DCL_TYPE (type);
10290 /* we have to go by the storage class */
10291 p_type = PTR_TYPE (SPEC_OCLS (etype));
10293 /* special case when cast remat */
10294 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10295 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
10296 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10297 type = operandType (left);
10298 p_type = DCL_TYPE (type);
10300 /* now that we have the pointer type we assign
10301 the pointer values */
10307 genNearPointerGet (left, result, ic, pi);
10311 genPagedPointerGet (left, result, ic, pi);
10315 genFarPointerGet (left, result, ic, pi);
10319 genCodePointerGet (left, result, ic, pi);
10323 genGenPointerGet (left, result, ic, pi);
10329 /*-----------------------------------------------------------------*/
10330 /* genPackBits - generates code for packed bit storage */
10331 /*-----------------------------------------------------------------*/
10333 genPackBits (sym_link * etype,
10335 char *rname, int p_type)
10337 int offset = 0; /* source byte offset */
10338 int rlen = 0; /* remaining bitfield length */
10339 int blen; /* bitfield length */
10340 int bstr; /* bitfield starting bit within byte */
10341 int litval; /* source literal value (if AOP_LIT) */
10342 unsigned char mask; /* bitmask within current byte */
10344 D(emitcode ("; genPackBits",""));
10346 blen = SPEC_BLEN (etype);
10347 bstr = SPEC_BSTR (etype);
10349 /* If the bitfield length is less than a byte */
10352 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10353 (unsigned char) (0xFF >> (8 - bstr)));
10355 if (AOP_TYPE (right) == AOP_LIT)
10357 /* Case with a bitfield length <8 and literal source
10359 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10361 litval &= (~mask) & 0xff;
10362 emitPtrByteGet (rname, p_type, FALSE);
10363 if ((mask|litval)!=0xff)
10364 emitcode ("anl","a,#!constbyte", mask);
10366 emitcode ("orl","a,#!constbyte", litval);
10370 if ((blen==1) && (p_type!=GPOINTER))
10372 /* Case with a bitfield length == 1 and no generic pointer
10374 if (AOP_TYPE (right) == AOP_CRY)
10375 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10378 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10379 emitcode ("rrc","a");
10381 emitPtrByteGet (rname, p_type, FALSE);
10382 emitcode ("mov","acc.%d,c",bstr);
10386 /* Case with a bitfield length < 8 and arbitrary source
10388 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10389 /* shift and mask source value */
10391 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10393 /* transfer A to B and get next byte */
10394 emitPtrByteGet (rname, p_type, TRUE);
10396 emitcode ("anl", "a,#!constbyte", mask);
10397 emitcode ("orl", "a,b");
10398 if (p_type == GPOINTER)
10399 emitcode ("pop", "b");
10403 emitPtrByteSet (rname, p_type, "a");
10407 /* Bit length is greater than 7 bits. In this case, copy */
10408 /* all except the partial byte at the end */
10409 for (rlen=blen;rlen>=8;rlen-=8)
10411 emitPtrByteSet (rname, p_type,
10412 aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
10414 emitcode ("inc", "%s", rname);
10417 /* If there was a partial byte at the end */
10420 mask = (((unsigned char) -1 << rlen) & 0xff);
10422 if (AOP_TYPE (right) == AOP_LIT)
10424 /* Case with partial byte and literal source
10426 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10427 litval >>= (blen-rlen);
10428 litval &= (~mask) & 0xff;
10429 emitPtrByteGet (rname, p_type, FALSE);
10430 if ((mask|litval)!=0xff)
10431 emitcode ("anl","a,#!constbyte", mask);
10433 emitcode ("orl","a,#!constbyte", litval);
10437 /* Case with partial byte and arbitrary source
10439 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10440 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10442 /* transfer A to B and get next byte */
10443 emitPtrByteGet (rname, p_type, TRUE);
10445 emitcode ("anl", "a,#!constbyte", mask);
10446 emitcode ("orl", "a,b");
10447 if (p_type == GPOINTER)
10448 emitcode ("pop", "b");
10450 emitPtrByteSet (rname, p_type, "a");
10456 /*-----------------------------------------------------------------*/
10457 /* genDataPointerSet - remat pointer to data space */
10458 /*-----------------------------------------------------------------*/
10460 genDataPointerSet (operand * right,
10464 int size, offset = 0;
10465 char *l, buff[256];
10467 aopOp (right, ic, FALSE, FALSE);
10469 l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
10470 size = AOP_SIZE (right);
10475 SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
10479 SNPRINTF (buff, sizeof(buff), "%s", l + 1);
10482 emitcode ("mov", "%s,%s", buff,
10483 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10486 freeAsmop (right, NULL, ic, TRUE);
10487 freeAsmop (result, NULL, ic, TRUE);
10490 /*-----------------------------------------------------------------*/
10491 /* genNearPointerSet - emitcode for near pointer put */
10492 /*-----------------------------------------------------------------*/
10494 genNearPointerSet (operand * right,
10501 sym_link *retype, *letype;
10502 sym_link *ptype = operandType (result);
10504 retype = getSpec (operandType (right));
10505 letype = getSpec (ptype);
10507 aopOp (result, ic, FALSE, FALSE);
10509 /* if the result is rematerializable &
10510 in data space & not a bit variable */
10511 if (AOP_TYPE (result) == AOP_IMMD &&
10512 DCL_TYPE (ptype) == POINTER &&
10513 !IS_BITVAR (retype) &&
10514 !IS_BITVAR (letype))
10516 genDataPointerSet (right, result, ic);
10520 /* if the value is already in a pointer register
10521 then don't need anything more */
10522 if (!AOP_INPREG (AOP (result)))
10524 /* otherwise get a free pointer register */
10527 aop = newAsmop (0);
10528 preg = getFreePtr (ic, &aop, FALSE);
10529 emitcode ("mov", "%s,%s",
10531 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10532 rname = preg->name;
10535 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10537 aopOp (right, ic, FALSE, FALSE);
10539 /* if bitfield then unpack the bits */
10540 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10541 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10544 /* we have can just get the values */
10545 int size = AOP_SIZE (right);
10550 l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10554 emitcode ("mov", "@%s,a", rname);
10557 emitcode ("mov", "@%s,%s", rname, l);
10559 emitcode ("inc", "%s", rname);
10564 /* now some housekeeping stuff */
10567 /* we had to allocate for this iCode */
10568 if (pi) aopPut (AOP (result),rname,0);
10569 freeAsmop (NULL, aop, ic, TRUE);
10573 /* we did not allocate which means left
10574 already in a pointer register, then
10575 if size > 0 && this could be used again
10576 we have to point it back to where it
10578 if (AOP_SIZE (right) > 1 &&
10579 !OP_SYMBOL (result)->remat &&
10580 (OP_SYMBOL (result)->liveTo > ic->seq ||
10584 int size = AOP_SIZE (right) - 1;
10586 emitcode ("dec", "%s", rname);
10591 if (pi) pi->generated = 1;
10592 freeAsmop (result, NULL, ic, TRUE);
10593 freeAsmop (right, NULL, ic, TRUE);
10598 /*-----------------------------------------------------------------*/
10599 /* genPagedPointerSet - emitcode for Paged pointer put */
10600 /*-----------------------------------------------------------------*/
10602 genPagedPointerSet (operand * right,
10609 sym_link *retype, *letype;
10611 retype = getSpec (operandType (right));
10612 letype = getSpec (operandType (result));
10614 aopOp (result, ic, FALSE, FALSE);
10616 /* if the value is already in a pointer register
10617 then don't need anything more */
10618 if (!AOP_INPREG (AOP (result)))
10620 /* otherwise get a free pointer register */
10623 aop = newAsmop (0);
10624 preg = getFreePtr (ic, &aop, FALSE);
10625 emitcode ("mov", "%s,%s",
10627 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10628 rname = preg->name;
10631 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10633 aopOp (right, ic, FALSE, FALSE);
10635 /* if bitfield then unpack the bits */
10636 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10637 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10640 /* we have can just get the values */
10641 int size = AOP_SIZE (right);
10646 MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10648 emitcode ("movx", "@%s,a", rname);
10651 emitcode ("inc", "%s", rname);
10657 /* now some housekeeping stuff */
10660 if (pi) aopPut (AOP (result),rname,0);
10661 /* we had to allocate for this iCode */
10662 freeAsmop (NULL, aop, ic, TRUE);
10666 /* we did not allocate which means left
10667 already in a pointer register, then
10668 if size > 0 && this could be used again
10669 we have to point it back to where it
10671 if (AOP_SIZE (right) > 1 &&
10672 !OP_SYMBOL (result)->remat &&
10673 (OP_SYMBOL (result)->liveTo > ic->seq ||
10677 int size = AOP_SIZE (right) - 1;
10679 emitcode ("dec", "%s", rname);
10684 if (pi) pi->generated = 1;
10685 freeAsmop (result, NULL, ic, TRUE);
10686 freeAsmop (right, NULL, ic, TRUE);
10691 /*-----------------------------------------------------------------*/
10692 /* genFarPointerSet - set value from far space */
10693 /*-----------------------------------------------------------------*/
10695 genFarPointerSet (operand * right,
10696 operand * result, iCode * ic, iCode *pi)
10698 int size, offset, dopi=1;
10699 sym_link *retype = getSpec (operandType (right));
10700 sym_link *letype = getSpec (operandType (result));
10702 aopOp (result, ic, FALSE, FALSE);
10704 /* if the operand is already in dptr
10705 then we do nothing else we move the value to dptr */
10706 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10708 /* if this is remateriazable */
10709 if (AOP_TYPE (result) == AOP_IMMD)
10710 emitcode ("mov", "dptr,%s",
10711 aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10714 /* we need to get it byte by byte */
10715 _startLazyDPSEvaluation ();
10716 if (AOP_TYPE (result) != AOP_DPTR)
10718 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10719 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10720 if (options.model == MODEL_FLAT24)
10721 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10725 /* We need to generate a load to DPTR indirect through DPTR. */
10726 D (emitcode (";", "genFarPointerSet -- indirection special case."););
10728 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10729 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10730 if (options.model == MODEL_FLAT24)
10731 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10732 emitcode ("pop", "dph");
10733 emitcode ("pop", "dpl");
10736 _endLazyDPSEvaluation ();
10739 /* so dptr know contains the address */
10740 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10742 /* if bit then unpack */
10743 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10744 if (AOP_INDPTRn(result)) {
10745 genSetDPTR(AOP(result)->aopu.dptr);
10747 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10748 if (AOP_INDPTRn(result)) {
10752 size = AOP_SIZE (right);
10754 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10756 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10758 genSetDPTR(AOP(result)->aopu.dptr);
10759 emitcode ("movx", "@dptr,a");
10760 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10761 emitcode ("inc", "dptr");
10765 _startLazyDPSEvaluation ();
10767 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10769 if (AOP_INDPTRn(result)) {
10770 genSetDPTR(AOP(result)->aopu.dptr);
10776 emitcode ("movx", "@dptr,a");
10777 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10778 emitcode ("inc", "dptr");
10780 _endLazyDPSEvaluation ();
10784 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10785 if (!AOP_INDPTRn(result)) {
10786 _startLazyDPSEvaluation ();
10788 aopPut (AOP(result),"dpl",0);
10789 aopPut (AOP(result),"dph",1);
10790 if (options.model == MODEL_FLAT24)
10791 aopPut (AOP(result),"dpx",2);
10793 _endLazyDPSEvaluation ();
10796 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10797 AOP_SIZE(right) > 1 &&
10798 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10800 size = AOP_SIZE (right) - 1;
10801 if (AOP_INDPTRn(result)) {
10802 genSetDPTR(AOP(result)->aopu.dptr);
10804 while (size--) emitcode ("lcall","__decdptr");
10805 if (AOP_INDPTRn(result)) {
10809 freeAsmop (result, NULL, ic, TRUE);
10810 freeAsmop (right, NULL, ic, TRUE);
10813 /*-----------------------------------------------------------------*/
10814 /* genGenPointerSet - set value from generic pointer space */
10815 /*-----------------------------------------------------------------*/
10817 genGenPointerSet (operand * right,
10818 operand * result, iCode * ic, iCode *pi)
10821 sym_link *retype = getSpec (operandType (right));
10822 sym_link *letype = getSpec (operandType (result));
10824 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10826 /* if the operand is already in dptr
10827 then we do nothing else we move the value to dptr */
10828 if (AOP_TYPE (result) != AOP_STR)
10830 _startLazyDPSEvaluation ();
10831 /* if this is remateriazable */
10832 if (AOP_TYPE (result) == AOP_IMMD)
10834 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10835 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10837 MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10842 "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10846 { /* we need to get it byte by byte */
10847 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10848 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10849 if (options.model == MODEL_FLAT24) {
10850 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10851 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10853 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10856 _endLazyDPSEvaluation ();
10858 /* so dptr + b now contains the address */
10860 aopOp (right, ic, FALSE, TRUE);
10864 /* if bit then unpack */
10865 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10867 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10871 size = AOP_SIZE (right);
10874 _startLazyDPSEvaluation ();
10879 // Set two bytes at a time, passed in _AP & A.
10880 // dptr will be incremented ONCE by __gptrputWord.
10882 // Note: any change here must be coordinated
10883 // with the implementation of __gptrputWord
10884 // in device/lib/_gptrput.c
10885 emitcode("mov", "_ap, %s",
10886 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10887 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10891 emitcode ("lcall", "__gptrputWord");
10896 // Only one byte to put.
10897 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10901 emitcode ("lcall", "__gptrput");
10904 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10906 emitcode ("inc", "dptr");
10909 _endLazyDPSEvaluation ();
10912 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10913 _startLazyDPSEvaluation ();
10915 aopPut (AOP(result),"dpl",0);
10916 aopPut (AOP(result),"dph",1);
10917 if (options.model == MODEL_FLAT24) {
10918 aopPut (AOP(result),"dpx",2);
10919 aopPut (AOP(result),"b",3);
10921 aopPut (AOP(result),"b",2);
10923 _endLazyDPSEvaluation ();
10926 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10927 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10929 size = AOP_SIZE (right) - 1;
10930 while (size--) emitcode ("lcall","__decdptr");
10932 freeAsmop (result, NULL, ic, TRUE);
10933 freeAsmop (right, NULL, ic, TRUE);
10936 /*-----------------------------------------------------------------*/
10937 /* genPointerSet - stores the value into a pointer location */
10938 /*-----------------------------------------------------------------*/
10940 genPointerSet (iCode * ic, iCode *pi)
10942 operand *right, *result;
10943 sym_link *type, *etype;
10946 D (emitcode (";", "genPointerSet "););
10948 right = IC_RIGHT (ic);
10949 result = IC_RESULT (ic);
10951 /* depending on the type of pointer we need to
10952 move it to the correct pointer register */
10953 type = operandType (result);
10954 etype = getSpec (type);
10955 /* if left is of type of pointer then it is simple */
10956 if (IS_PTR (type) && !IS_FUNC (type->next))
10958 p_type = DCL_TYPE (type);
10962 /* we have to go by the storage class */
10963 p_type = PTR_TYPE (SPEC_OCLS (etype));
10965 /* special case when cast remat */
10966 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10967 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10968 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10969 type = operandType (result);
10970 p_type = DCL_TYPE (type);
10973 /* now that we have the pointer type we assign
10974 the pointer values */
10980 genNearPointerSet (right, result, ic, pi);
10984 genPagedPointerSet (right, result, ic, pi);
10988 genFarPointerSet (right, result, ic, pi);
10992 genGenPointerSet (right, result, ic, pi);
10996 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10997 "genPointerSet: illegal pointer type");
11002 /*-----------------------------------------------------------------*/
11003 /* genIfx - generate code for Ifx statement */
11004 /*-----------------------------------------------------------------*/
11006 genIfx (iCode * ic, iCode * popIc)
11008 operand *cond = IC_COND (ic);
11011 D (emitcode (";", "genIfx "););
11013 aopOp (cond, ic, FALSE, FALSE);
11015 /* get the value into acc */
11016 if (AOP_TYPE (cond) != AOP_CRY)
11025 /* the result is now in the accumulator */
11026 freeAsmop (cond, NULL, ic, TRUE);
11028 /* if there was something to be popped then do it */
11032 /* if the condition is a bit variable */
11033 if (isbit && IS_ITEMP (cond) &&
11036 genIfxJump (ic, SPIL_LOC (cond)->rname);
11038 else if (isbit && !IS_ITEMP (cond))
11040 genIfxJump (ic, OP_SYMBOL (cond)->rname);
11044 genIfxJump (ic, "a");
11050 /*-----------------------------------------------------------------*/
11051 /* genAddrOf - generates code for address of */
11052 /*-----------------------------------------------------------------*/
11054 genAddrOf (iCode * ic)
11056 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11059 D (emitcode (";", "genAddrOf ");
11062 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11064 /* if the operand is on the stack then we
11065 need to get the stack offset of this
11067 if (sym->onStack) {
11069 /* if 10 bit stack */
11070 if (options.stack10bit) {
11074 tsprintf(buff, sizeof(buff),
11075 "#!constbyte",(options.stack_loc >> 16) & 0xff);
11076 /* if it has an offset then we need to compute it */
11077 /* emitcode ("subb", "a,#!constbyte", */
11078 /* -((sym->stack < 0) ? */
11079 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11080 /* ((short) sym->stack)) & 0xff); */
11081 /* emitcode ("mov","b,a"); */
11082 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
11083 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11084 /* ((short) sym->stack)) >> 8) & 0xff); */
11086 emitcode ("mov", "a,_bpx");
11087 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
11088 ((char) (sym->stack - _G.nRegsSaved)) :
11089 ((char) sym->stack )) & 0xff);
11090 emitcode ("mov", "b,a");
11091 emitcode ("mov", "a,_bpx+1");
11093 offset = (((sym->stack < 0) ?
11094 ((short) (sym->stack - _G.nRegsSaved)) :
11095 ((short) sym->stack )) >> 8) & 0xff;
11097 emitcode ("addc","a,#!constbyte", offset);
11099 aopPut (AOP (IC_RESULT (ic)), "b", 0);
11100 aopPut (AOP (IC_RESULT (ic)), "a", 1);
11101 aopPut (AOP (IC_RESULT (ic)), buff, 2);
11103 /* we can just move _bp */
11104 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
11105 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
11106 aopPut (AOP (IC_RESULT (ic)), buff, 2);
11109 /* if it has an offset then we need to compute it */
11111 emitcode ("mov", "a,_bp");
11112 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
11113 aopPut (AOP (IC_RESULT (ic)), "a", 0);
11115 /* we can just move _bp */
11116 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
11118 /* fill the result with zero */
11119 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11122 if (options.stack10bit && size < (FPTRSIZE - 1)) {
11124 "*** warning: pointer to stack var truncated.\n");
11129 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
11135 /* object not on stack then we need the name */
11136 size = AOP_SIZE (IC_RESULT (ic));
11141 char s[SDCC_NAME_MAX];
11145 tsprintf(s, sizeof(s), "#!his",sym->rname);
11148 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
11151 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
11153 default: /* should not need this (just in case) */
11154 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
11161 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11164 aopPut (AOP (IC_RESULT (ic)), s, offset++);
11168 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11172 #if 0 // obsolete, and buggy for != xdata
11173 /*-----------------------------------------------------------------*/
11174 /* genArrayInit - generates code for address of */
11175 /*-----------------------------------------------------------------*/
11177 genArrayInit (iCode * ic)
11179 literalList *iLoop;
11181 int elementSize = 0, eIndex;
11182 unsigned val, lastVal;
11184 operand *left=IC_LEFT(ic);
11186 D (emitcode (";", "genArrayInit "););
11188 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
11190 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
11192 // Load immediate value into DPTR.
11193 emitcode("mov", "dptr, %s",
11194 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
11196 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
11199 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11200 "Unexpected operand to genArrayInit.\n");
11203 // a regression because of SDCCcse.c:1.52
11204 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
11205 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
11206 if (options.model == MODEL_FLAT24)
11207 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
11211 type = operandType(IC_LEFT(ic));
11213 if (type && type->next)
11215 elementSize = getSize(type->next);
11219 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11220 "can't determine element size in genArrayInit.\n");
11224 iLoop = IC_ARRAYILIST(ic);
11229 bool firstpass = TRUE;
11231 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
11232 iLoop->count, (int)iLoop->literalValue, elementSize);
11238 symbol *tlbl = NULL;
11240 count = ix > 256 ? 256 : ix;
11244 tlbl = newiTempLabel (NULL);
11245 if (firstpass || (count & 0xff))
11247 emitcode("mov", "b, #!constbyte", count & 0xff);
11250 emitcode ("", "!tlabeldef", tlbl->key + 100);
11255 for (eIndex = 0; eIndex < elementSize; eIndex++)
11257 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
11258 if (val != lastVal)
11260 emitcode("mov", "a, #!constbyte", val);
11264 emitcode("movx", "@dptr, a");
11265 emitcode("inc", "dptr");
11270 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
11276 iLoop = iLoop->next;
11279 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
11283 /*-----------------------------------------------------------------*/
11284 /* genFarFarAssign - assignment when both are in far space */
11285 /*-----------------------------------------------------------------*/
11287 genFarFarAssign (operand * result, operand * right, iCode * ic)
11289 int size = AOP_SIZE (right);
11291 symbol *rSym = NULL;
11295 /* quick & easy case. */
11296 D(emitcode(";","genFarFarAssign (1 byte case)"););
11297 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
11298 freeAsmop (right, NULL, ic, FALSE);
11299 /* now assign DPTR to result */
11301 aopOp(result, ic, FALSE, FALSE);
11303 aopPut(AOP(result), "a", 0);
11304 freeAsmop(result, NULL, ic, FALSE);
11308 /* See if we've got an underlying symbol to abuse. */
11309 if (IS_SYMOP(result) && OP_SYMBOL(result))
11311 if (IS_TRUE_SYMOP(result))
11313 rSym = OP_SYMBOL(result);
11315 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
11317 rSym = OP_SYMBOL(result)->usl.spillLoc;
11321 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
11323 /* We can use the '390 auto-toggle feature to good effect here. */
11325 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
11326 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11327 emitcode ("mov", "dptr,#%s", rSym->rname);
11328 /* DP2 = result, DP1 = right, DP1 is current. */
11331 emitcode("movx", "a,@dptr");
11332 emitcode("movx", "@dptr,a");
11335 emitcode("inc", "dptr");
11336 emitcode("inc", "dptr");
11339 emitcode("mov", "dps,#0");
11340 freeAsmop (right, NULL, ic, FALSE);
11342 some alternative code for processors without auto-toggle
11343 no time to test now, so later well put in...kpb
11344 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
11345 emitcode("mov", "dps,#1"); /* Select DPTR2. */
11346 emitcode ("mov", "dptr,#%s", rSym->rname);
11347 /* DP2 = result, DP1 = right, DP1 is current. */
11351 emitcode("movx", "a,@dptr");
11353 emitcode("inc", "dptr");
11354 emitcode("inc", "dps");
11355 emitcode("movx", "@dptr,a");
11357 emitcode("inc", "dptr");
11358 emitcode("inc", "dps");
11360 emitcode("mov", "dps,#0");
11361 freeAsmop (right, NULL, ic, FALSE);
11366 D (emitcode (";", "genFarFarAssign"););
11367 aopOp (result, ic, TRUE, TRUE);
11369 _startLazyDPSEvaluation ();
11373 aopPut (AOP (result),
11374 aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
11377 _endLazyDPSEvaluation ();
11378 freeAsmop (result, NULL, ic, FALSE);
11379 freeAsmop (right, NULL, ic, FALSE);
11383 /*-----------------------------------------------------------------*/
11384 /* genAssign - generate code for assignment */
11385 /*-----------------------------------------------------------------*/
11387 genAssign (iCode * ic)
11389 operand *result, *right;
11391 unsigned long lit = 0L;
11393 D (emitcode (";", "genAssign ");
11396 result = IC_RESULT (ic);
11397 right = IC_RIGHT (ic);
11399 /* if they are the same */
11400 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11403 aopOp (right, ic, FALSE, FALSE);
11405 emitcode (";", "genAssign: resultIsFar = %s",
11406 isOperandInFarSpace (result) ?
11409 /* special case both in far space */
11410 if ((AOP_TYPE (right) == AOP_DPTR ||
11411 AOP_TYPE (right) == AOP_DPTR2) &&
11412 /* IS_TRUE_SYMOP(result) && */
11413 isOperandInFarSpace (result))
11415 genFarFarAssign (result, right, ic);
11419 aopOp (result, ic, TRUE, FALSE);
11421 /* if they are the same registers */
11422 if (sameRegs (AOP (right), AOP (result)))
11425 /* if the result is a bit */
11426 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
11428 /* if the right size is a literal then
11429 we know what the value is */
11430 if (AOP_TYPE (right) == AOP_LIT)
11432 if (((int) operandLitValue (right)))
11433 aopPut (AOP (result), one, 0);
11435 aopPut (AOP (result), zero, 0);
11439 /* the right is also a bit variable */
11440 if (AOP_TYPE (right) == AOP_CRY)
11442 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11443 aopPut (AOP (result), "c", 0);
11447 /* we need to or */
11449 aopPut (AOP (result), "a", 0);
11453 /* bit variables done */
11455 size = AOP_SIZE (result);
11457 if (AOP_TYPE (right) == AOP_LIT)
11458 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11461 (AOP_TYPE (result) != AOP_REG) &&
11462 (AOP_TYPE (right) == AOP_LIT) &&
11463 !IS_FLOAT (operandType (right)))
11465 _startLazyDPSEvaluation ();
11466 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
11468 aopPut (AOP (result),
11469 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11474 /* And now fill the rest with zeros. */
11477 emitcode ("clr", "a");
11481 aopPut (AOP (result), "a", offset++);
11483 _endLazyDPSEvaluation ();
11487 _startLazyDPSEvaluation ();
11490 aopPut (AOP (result),
11491 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11495 _endLazyDPSEvaluation ();
11499 freeAsmop (right, NULL, ic, FALSE);
11500 freeAsmop (result, NULL, ic, TRUE);
11503 /*-----------------------------------------------------------------*/
11504 /* genJumpTab - generates code for jump table */
11505 /*-----------------------------------------------------------------*/
11507 genJumpTab (iCode * ic)
11512 D (emitcode (";", "genJumpTab ");
11515 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11516 /* get the condition into accumulator */
11517 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11519 /* multiply by four! */
11520 emitcode ("add", "a,acc");
11521 emitcode ("add", "a,acc");
11522 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11524 jtab = newiTempLabel (NULL);
11525 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11526 emitcode ("jmp", "@a+dptr");
11527 emitcode ("", "!tlabeldef", jtab->key + 100);
11528 /* now generate the jump labels */
11529 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11530 jtab = setNextItem (IC_JTLABELS (ic)))
11531 emitcode ("ljmp", "!tlabel", jtab->key + 100);
11535 /*-----------------------------------------------------------------*/
11536 /* genCast - gen code for casting */
11537 /*-----------------------------------------------------------------*/
11539 genCast (iCode * ic)
11541 operand *result = IC_RESULT (ic);
11542 sym_link *ctype = operandType (IC_LEFT (ic));
11543 sym_link *rtype = operandType (IC_RIGHT (ic));
11544 operand *right = IC_RIGHT (ic);
11547 D (emitcode (";", "genCast "););
11549 /* if they are equivalent then do nothing */
11550 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11553 aopOp (right, ic, FALSE, AOP_IS_STR (result));
11554 aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
11556 /* if the result is a bit */
11557 if (IS_BITVAR (OP_SYMBOL (result)->type)
11558 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11560 /* if the right size is a literal then
11561 we know what the value is */
11562 if (AOP_TYPE (right) == AOP_LIT)
11564 if (((int) operandLitValue (right)))
11565 aopPut (AOP (result), one, 0);
11567 aopPut (AOP (result), zero, 0);
11572 /* the right is also a bit variable */
11573 if (AOP_TYPE (right) == AOP_CRY)
11575 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11576 aopPut (AOP (result), "c", 0);
11580 /* we need to or */
11582 aopPut (AOP (result), "a", 0);
11586 /* if they are the same size : or less */
11587 if (AOP_SIZE (result) <= AOP_SIZE (right))
11590 /* if they are in the same place */
11591 if (sameRegs (AOP (right), AOP (result)))
11594 /* if they in different places then copy */
11595 size = AOP_SIZE (result);
11597 _startLazyDPSEvaluation ();
11600 aopPut (AOP (result),
11601 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11605 _endLazyDPSEvaluation ();
11610 /* if the result is of type pointer */
11611 if (IS_PTR (ctype))
11615 sym_link *type = operandType (right);
11617 /* pointer to generic pointer */
11618 if (IS_GENPTR (ctype))
11622 p_type = DCL_TYPE (type);
11626 #if OLD_CAST_BEHAVIOR
11627 /* KV: we are converting a non-pointer type to
11628 * a generic pointer. This (ifdef'd out) code
11629 * says that the resulting generic pointer
11630 * should have the same class as the storage
11631 * location of the non-pointer variable.
11633 * For example, converting an int (which happens
11634 * to be stored in DATA space) to a pointer results
11635 * in a DATA generic pointer; if the original int
11636 * in XDATA space, so will be the resulting pointer.
11638 * I don't like that behavior, and thus this change:
11639 * all such conversions will be forced to XDATA and
11640 * throw a warning. If you want some non-XDATA
11641 * type, or you want to suppress the warning, you
11642 * must go through an intermediate cast, like so:
11644 * char _generic *gp = (char _xdata *)(intVar);
11646 sym_link *etype = getSpec (type);
11648 /* we have to go by the storage class */
11649 if (SPEC_OCLS (etype) != generic)
11651 p_type = PTR_TYPE (SPEC_OCLS (etype));
11656 /* Converting unknown class (i.e. register variable)
11657 * to generic pointer. This is not good, but
11658 * we'll make a guess (and throw a warning).
11661 werror (W_INT_TO_GEN_PTR_CAST);
11665 /* the first two bytes are known */
11666 size = GPTRSIZE - 1;
11668 _startLazyDPSEvaluation ();
11671 aopPut (AOP (result),
11672 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11676 _endLazyDPSEvaluation ();
11678 /* the last byte depending on type */
11680 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11685 // pointerTypeToGPByte will have bitched.
11689 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11690 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11695 /* just copy the pointers */
11696 size = AOP_SIZE (result);
11698 _startLazyDPSEvaluation ();
11701 aopPut (AOP (result),
11702 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11706 _endLazyDPSEvaluation ();
11710 /* so we now know that the size of destination is greater
11711 than the size of the source */
11712 /* we move to result for the size of source */
11713 size = AOP_SIZE (right);
11715 _startLazyDPSEvaluation ();
11718 aopPut (AOP (result),
11719 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11723 _endLazyDPSEvaluation ();
11725 /* now depending on the sign of the source && destination */
11726 size = AOP_SIZE (result) - AOP_SIZE (right);
11727 /* if unsigned or not an integral type */
11728 /* also, if the source is a bit, we don't need to sign extend, because
11729 * it can't possibly have set the sign bit.
11731 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11735 aopPut (AOP (result), zero, offset++);
11740 /* we need to extend the sign :{ */
11741 MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11742 FALSE, FALSE, NULL));
11743 emitcode ("rlc", "a");
11744 emitcode ("subb", "a,acc");
11746 aopPut (AOP (result), "a", offset++);
11749 /* we are done hurray !!!! */
11752 freeAsmop (right, NULL, ic, TRUE);
11753 freeAsmop (result, NULL, ic, TRUE);
11757 /*-----------------------------------------------------------------*/
11758 /* genDjnz - generate decrement & jump if not zero instrucion */
11759 /*-----------------------------------------------------------------*/
11761 genDjnz (iCode * ic, iCode * ifx)
11763 symbol *lbl, *lbl1;
11767 /* if the if condition has a false label
11768 then we cannot save */
11769 if (IC_FALSE (ifx))
11772 /* if the minus is not of the form
11774 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11775 !IS_OP_LITERAL (IC_RIGHT (ic)))
11778 if (operandLitValue (IC_RIGHT (ic)) != 1)
11781 /* if the size of this greater than one then no
11783 if (getSize (operandType (IC_RESULT (ic))) > 1)
11786 /* otherwise we can save BIG */
11787 D(emitcode(";", "genDjnz"););
11789 lbl = newiTempLabel (NULL);
11790 lbl1 = newiTempLabel (NULL);
11792 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11794 if (AOP_NEEDSACC(IC_RESULT(ic)))
11796 /* If the result is accessed indirectly via
11797 * the accumulator, we must explicitly write
11798 * it back after the decrement.
11800 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11802 if (strcmp(rByte, "a"))
11804 /* Something is hopelessly wrong */
11805 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11806 __FILE__, __LINE__);
11807 /* We can just give up; the generated code will be inefficient,
11808 * but what the hey.
11810 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11813 emitcode ("dec", "%s", rByte);
11814 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11815 emitcode ("jnz", "!tlabel", lbl->key + 100);
11817 else if (IS_AOP_PREG (IC_RESULT (ic)))
11819 emitcode ("dec", "%s",
11820 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11821 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11822 emitcode ("jnz", "!tlabel", lbl->key + 100);
11826 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11829 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11830 emitcode ("", "!tlabeldef", lbl->key + 100);
11831 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11832 emitcode ("", "!tlabeldef", lbl1->key + 100);
11834 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11835 ifx->generated = 1;
11839 /*-----------------------------------------------------------------*/
11840 /* genReceive - generate code for a receive iCode */
11841 /*-----------------------------------------------------------------*/
11843 genReceive (iCode * ic)
11845 int size = getSize (operandType (IC_RESULT (ic)));
11849 D (emitcode (";", "genReceive "););
11851 if (ic->argreg == 1)
11853 /* first parameter */
11854 if (AOP_IS_STR(IC_RESULT(ic)))
11856 /* Nothing to do: it's already in the proper place. */
11863 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11864 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11865 IS_TRUE_SYMOP (IC_RESULT (ic)));
11868 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11871 /* Sanity checking... */
11872 if (AOP_USESDPTR(IC_RESULT(ic)))
11874 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11875 "genReceive got unexpected DPTR.");
11877 assignResultValue (IC_RESULT (ic));
11882 /* second receive onwards */
11883 /* this gets a little tricky since unused recevies will be
11884 eliminated, we have saved the reg in the type field . and
11885 we use that to figure out which register to use */
11886 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11887 rb1off = ic->argreg;
11890 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11893 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11896 /*-----------------------------------------------------------------*/
11897 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11898 /*-----------------------------------------------------------------*/
11899 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11901 operand *from , *to , *count;
11906 /* we know it has to be 3 parameters */
11907 assert (nparms == 3);
11909 rsave = newBitVect(16);
11910 /* save DPTR if it needs to be saved */
11911 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11912 if (bitVectBitValue(ic->rMask,i))
11913 rsave = bitVectSetBit(rsave,i);
11915 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11916 ds390_rUmaskForOp (IC_RESULT(ic))));
11923 aopOp (from, ic->next, FALSE, FALSE);
11925 /* get from into DPTR1 */
11926 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11927 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11928 if (options.model == MODEL_FLAT24) {
11929 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11932 freeAsmop (from, NULL, ic, FALSE);
11933 aopOp (to, ic, FALSE, FALSE);
11934 /* get "to" into DPTR */
11935 /* if the operand is already in dptr
11936 then we do nothing else we move the value to dptr */
11937 if (AOP_TYPE (to) != AOP_STR) {
11938 /* if already in DPTR then we need to push */
11939 if (AOP_TYPE(to) == AOP_DPTR) {
11940 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11941 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11942 if (options.model == MODEL_FLAT24)
11943 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11944 emitcode ("pop", "dph");
11945 emitcode ("pop", "dpl");
11947 _startLazyDPSEvaluation ();
11948 /* if this is remateriazable */
11949 if (AOP_TYPE (to) == AOP_IMMD) {
11950 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11951 } else { /* we need to get it byte by byte */
11952 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11953 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11954 if (options.model == MODEL_FLAT24) {
11955 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11958 _endLazyDPSEvaluation ();
11961 freeAsmop (to, NULL, ic, FALSE);
11962 _G.dptrInUse = _G.dptr1InUse = 1;
11963 aopOp (count, ic->next->next, FALSE,FALSE);
11964 lbl =newiTempLabel(NULL);
11966 /* now for the actual copy */
11967 if (AOP_TYPE(count) == AOP_LIT &&
11968 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11969 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11971 emitcode ("lcall","__bi_memcpyc2x_s");
11973 emitcode ("lcall","__bi_memcpyx2x_s");
11975 freeAsmop (count, NULL, ic, FALSE);
11977 symbol *lbl1 = newiTempLabel(NULL);
11979 emitcode (";"," Auto increment but no djnz");
11980 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11981 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11982 freeAsmop (count, NULL, ic, FALSE);
11983 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11984 emitcode ("","!tlabeldef",lbl->key+100);
11986 emitcode ("clr","a");
11987 emitcode ("movc", "a,@a+dptr");
11989 emitcode ("movx", "a,@dptr");
11990 emitcode ("movx", "@dptr,a");
11991 emitcode ("inc", "dptr");
11992 emitcode ("inc", "dptr");
11993 emitcode ("mov","a,b");
11994 emitcode ("orl","a,_ap");
11995 emitcode ("jz","!tlabel",lbl1->key+100);
11996 emitcode ("mov","a,_ap");
11997 emitcode ("add","a,#!constbyte",0xFF);
11998 emitcode ("mov","_ap,a");
11999 emitcode ("mov","a,b");
12000 emitcode ("addc","a,#!constbyte",0xFF);
12001 emitcode ("mov","b,a");
12002 emitcode ("sjmp","!tlabel",lbl->key+100);
12003 emitcode ("","!tlabeldef",lbl1->key+100);
12005 emitcode ("mov", "dps,#0");
12006 _G.dptrInUse = _G.dptr1InUse = 0;
12007 unsavermask(rsave);
12011 /*-----------------------------------------------------------------*/
12012 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
12013 /*-----------------------------------------------------------------*/
12014 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
12016 operand *from , *to , *count;
12021 /* we know it has to be 3 parameters */
12022 assert (nparms == 3);
12024 rsave = newBitVect(16);
12025 /* save DPTR if it needs to be saved */
12026 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12027 if (bitVectBitValue(ic->rMask,i))
12028 rsave = bitVectSetBit(rsave,i);
12030 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12031 ds390_rUmaskForOp (IC_RESULT(ic))));
12038 aopOp (from, ic->next, FALSE, FALSE);
12040 /* get from into DPTR1 */
12041 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12042 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12043 if (options.model == MODEL_FLAT24) {
12044 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12047 freeAsmop (from, NULL, ic, FALSE);
12048 aopOp (to, ic, FALSE, FALSE);
12049 /* get "to" into DPTR */
12050 /* if the operand is already in dptr
12051 then we do nothing else we move the value to dptr */
12052 if (AOP_TYPE (to) != AOP_STR) {
12053 /* if already in DPTR then we need to push */
12054 if (AOP_TYPE(to) == AOP_DPTR) {
12055 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12056 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12057 if (options.model == MODEL_FLAT24)
12058 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12059 emitcode ("pop", "dph");
12060 emitcode ("pop", "dpl");
12062 _startLazyDPSEvaluation ();
12063 /* if this is remateriazable */
12064 if (AOP_TYPE (to) == AOP_IMMD) {
12065 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12066 } else { /* we need to get it byte by byte */
12067 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12068 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12069 if (options.model == MODEL_FLAT24) {
12070 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12073 _endLazyDPSEvaluation ();
12076 freeAsmop (to, NULL, ic, FALSE);
12077 _G.dptrInUse = _G.dptr1InUse = 1;
12078 aopOp (count, ic->next->next, FALSE,FALSE);
12079 lbl =newiTempLabel(NULL);
12080 lbl2 =newiTempLabel(NULL);
12082 /* now for the actual compare */
12083 if (AOP_TYPE(count) == AOP_LIT &&
12084 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12085 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12087 emitcode("lcall","__bi_memcmpc2x_s");
12089 emitcode("lcall","__bi_memcmpx2x_s");
12090 freeAsmop (count, NULL, ic, FALSE);
12091 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12092 aopPut(AOP(IC_RESULT(ic)),"a",0);
12093 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12095 symbol *lbl1 = newiTempLabel(NULL);
12097 emitcode("push","ar0");
12098 emitcode (";"," Auto increment but no djnz");
12099 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12100 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12101 freeAsmop (count, NULL, ic, FALSE);
12102 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12103 emitcode ("","!tlabeldef",lbl->key+100);
12105 emitcode ("clr","a");
12106 emitcode ("movc", "a,@a+dptr");
12108 emitcode ("movx", "a,@dptr");
12109 emitcode ("mov","r0,a");
12110 emitcode ("movx", "a,@dptr");
12111 emitcode ("clr","c");
12112 emitcode ("subb","a,r0");
12113 emitcode ("jnz","!tlabel",lbl2->key+100);
12114 emitcode ("inc", "dptr");
12115 emitcode ("inc", "dptr");
12116 emitcode ("mov","a,b");
12117 emitcode ("orl","a,_ap");
12118 emitcode ("jz","!tlabel",lbl1->key+100);
12119 emitcode ("mov","a,_ap");
12120 emitcode ("add","a,#!constbyte",0xFF);
12121 emitcode ("mov","_ap,a");
12122 emitcode ("mov","a,b");
12123 emitcode ("addc","a,#!constbyte",0xFF);
12124 emitcode ("mov","b,a");
12125 emitcode ("sjmp","!tlabel",lbl->key+100);
12126 emitcode ("","!tlabeldef",lbl1->key+100);
12127 emitcode ("clr","a");
12128 emitcode ("","!tlabeldef",lbl2->key+100);
12129 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12130 aopPut(AOP(IC_RESULT(ic)),"a",0);
12131 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12132 emitcode("pop","ar0");
12133 emitcode ("mov", "dps,#0");
12135 _G.dptrInUse = _G.dptr1InUse = 0;
12136 unsavermask(rsave);
12140 /*-----------------------------------------------------------------*/
12141 /* genInp - gen code for __builtin_inp read data from a mem mapped */
12142 /* port, first parameter output area second parameter pointer to */
12143 /* port third parameter count */
12144 /*-----------------------------------------------------------------*/
12145 static void genInp( iCode *ic, int nparms, operand **parms)
12147 operand *from , *to , *count;
12152 /* we know it has to be 3 parameters */
12153 assert (nparms == 3);
12155 rsave = newBitVect(16);
12156 /* save DPTR if it needs to be saved */
12157 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12158 if (bitVectBitValue(ic->rMask,i))
12159 rsave = bitVectSetBit(rsave,i);
12161 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12162 ds390_rUmaskForOp (IC_RESULT(ic))));
12169 aopOp (from, ic->next, FALSE, FALSE);
12171 /* get from into DPTR1 */
12172 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12173 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12174 if (options.model == MODEL_FLAT24) {
12175 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12178 freeAsmop (from, NULL, ic, FALSE);
12179 aopOp (to, ic, FALSE, FALSE);
12180 /* get "to" into DPTR */
12181 /* if the operand is already in dptr
12182 then we do nothing else we move the value to dptr */
12183 if (AOP_TYPE (to) != AOP_STR) {
12184 /* if already in DPTR then we need to push */
12185 if (AOP_TYPE(to) == AOP_DPTR) {
12186 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12187 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12188 if (options.model == MODEL_FLAT24)
12189 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12190 emitcode ("pop", "dph");
12191 emitcode ("pop", "dpl");
12193 _startLazyDPSEvaluation ();
12194 /* if this is remateriazable */
12195 if (AOP_TYPE (to) == AOP_IMMD) {
12196 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12197 } else { /* we need to get it byte by byte */
12198 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12199 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12200 if (options.model == MODEL_FLAT24) {
12201 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12204 _endLazyDPSEvaluation ();
12207 freeAsmop (to, NULL, ic, FALSE);
12209 _G.dptrInUse = _G.dptr1InUse = 1;
12210 aopOp (count, ic->next->next, FALSE,FALSE);
12211 lbl =newiTempLabel(NULL);
12213 /* now for the actual copy */
12214 if (AOP_TYPE(count) == AOP_LIT &&
12215 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12216 emitcode (";","OH JOY auto increment with djnz (very fast)");
12217 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12218 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12219 freeAsmop (count, NULL, ic, FALSE);
12220 emitcode ("","!tlabeldef",lbl->key+100);
12221 emitcode ("movx", "a,@dptr"); /* read data from port */
12222 emitcode ("dec","dps"); /* switch to DPTR */
12223 emitcode ("movx", "@dptr,a"); /* save into location */
12224 emitcode ("inc", "dptr"); /* point to next area */
12225 emitcode ("inc","dps"); /* switch to DPTR2 */
12226 emitcode ("djnz","b,!tlabel",lbl->key+100);
12228 symbol *lbl1 = newiTempLabel(NULL);
12230 emitcode (";"," Auto increment but no djnz");
12231 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12232 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12233 freeAsmop (count, NULL, ic, FALSE);
12234 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12235 emitcode ("","!tlabeldef",lbl->key+100);
12236 emitcode ("movx", "a,@dptr");
12237 emitcode ("dec","dps"); /* switch to DPTR */
12238 emitcode ("movx", "@dptr,a");
12239 emitcode ("inc", "dptr");
12240 emitcode ("inc","dps"); /* switch to DPTR2 */
12241 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
12242 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
12243 emitcode ("mov","a,b");
12244 emitcode ("orl","a,_ap");
12245 emitcode ("jz","!tlabel",lbl1->key+100);
12246 emitcode ("mov","a,_ap");
12247 emitcode ("add","a,#!constbyte",0xFF);
12248 emitcode ("mov","_ap,a");
12249 emitcode ("mov","a,b");
12250 emitcode ("addc","a,#!constbyte",0xFF);
12251 emitcode ("mov","b,a");
12252 emitcode ("sjmp","!tlabel",lbl->key+100);
12253 emitcode ("","!tlabeldef",lbl1->key+100);
12255 emitcode ("mov", "dps,#0");
12256 _G.dptrInUse = _G.dptr1InUse = 0;
12257 unsavermask(rsave);
12261 /*-----------------------------------------------------------------*/
12262 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
12263 /* port, first parameter output area second parameter pointer to */
12264 /* port third parameter count */
12265 /*-----------------------------------------------------------------*/
12266 static void genOutp( iCode *ic, int nparms, operand **parms)
12268 operand *from , *to , *count;
12273 /* we know it has to be 3 parameters */
12274 assert (nparms == 3);
12276 rsave = newBitVect(16);
12277 /* save DPTR if it needs to be saved */
12278 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12279 if (bitVectBitValue(ic->rMask,i))
12280 rsave = bitVectSetBit(rsave,i);
12282 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12283 ds390_rUmaskForOp (IC_RESULT(ic))));
12290 aopOp (from, ic->next, FALSE, FALSE);
12292 /* get from into DPTR1 */
12293 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12294 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12295 if (options.model == MODEL_FLAT24) {
12296 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12299 freeAsmop (from, NULL, ic, FALSE);
12300 aopOp (to, ic, FALSE, FALSE);
12301 /* get "to" into DPTR */
12302 /* if the operand is already in dptr
12303 then we do nothing else we move the value to dptr */
12304 if (AOP_TYPE (to) != AOP_STR) {
12305 /* if already in DPTR then we need to push */
12306 if (AOP_TYPE(to) == AOP_DPTR) {
12307 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12308 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12309 if (options.model == MODEL_FLAT24)
12310 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12311 emitcode ("pop", "dph");
12312 emitcode ("pop", "dpl");
12314 _startLazyDPSEvaluation ();
12315 /* if this is remateriazable */
12316 if (AOP_TYPE (to) == AOP_IMMD) {
12317 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12318 } else { /* we need to get it byte by byte */
12319 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12320 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12321 if (options.model == MODEL_FLAT24) {
12322 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12325 _endLazyDPSEvaluation ();
12328 freeAsmop (to, NULL, ic, FALSE);
12330 _G.dptrInUse = _G.dptr1InUse = 1;
12331 aopOp (count, ic->next->next, FALSE,FALSE);
12332 lbl =newiTempLabel(NULL);
12334 /* now for the actual copy */
12335 if (AOP_TYPE(count) == AOP_LIT &&
12336 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12337 emitcode (";","OH JOY auto increment with djnz (very fast)");
12338 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12339 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12340 emitcode ("","!tlabeldef",lbl->key+100);
12341 emitcode ("movx", "a,@dptr"); /* read data from port */
12342 emitcode ("inc","dps"); /* switch to DPTR2 */
12343 emitcode ("movx", "@dptr,a"); /* save into location */
12344 emitcode ("inc", "dptr"); /* point to next area */
12345 emitcode ("dec","dps"); /* switch to DPTR */
12346 emitcode ("djnz","b,!tlabel",lbl->key+100);
12347 freeAsmop (count, NULL, ic, FALSE);
12349 symbol *lbl1 = newiTempLabel(NULL);
12351 emitcode (";"," Auto increment but no djnz");
12352 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12353 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12354 freeAsmop (count, NULL, ic, FALSE);
12355 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12356 emitcode ("","!tlabeldef",lbl->key+100);
12357 emitcode ("movx", "a,@dptr");
12358 emitcode ("inc", "dptr");
12359 emitcode ("inc","dps"); /* switch to DPTR2 */
12360 emitcode ("movx", "@dptr,a");
12361 emitcode ("dec","dps"); /* switch to DPTR */
12362 emitcode ("mov","a,b");
12363 emitcode ("orl","a,_ap");
12364 emitcode ("jz","!tlabel",lbl1->key+100);
12365 emitcode ("mov","a,_ap");
12366 emitcode ("add","a,#!constbyte",0xFF);
12367 emitcode ("mov","_ap,a");
12368 emitcode ("mov","a,b");
12369 emitcode ("addc","a,#!constbyte",0xFF);
12370 emitcode ("mov","b,a");
12371 emitcode ("sjmp","!tlabel",lbl->key+100);
12372 emitcode ("","!tlabeldef",lbl1->key+100);
12374 emitcode ("mov", "dps,#0");
12375 _G.dptrInUse = _G.dptr1InUse = 0;
12376 unsavermask(rsave);
12380 /*-----------------------------------------------------------------*/
12381 /* genSwapW - swap lower & high order bytes */
12382 /*-----------------------------------------------------------------*/
12383 static void genSwapW(iCode *ic, int nparms, operand **parms)
12387 assert (nparms==1);
12390 dest=IC_RESULT(ic);
12392 assert(getSize(operandType(src))==2);
12394 aopOp (src, ic, FALSE, FALSE);
12395 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
12397 MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
12399 freeAsmop (src, NULL, ic, FALSE);
12401 aopOp (dest,ic, FALSE, FALSE);
12402 aopPut(AOP(dest),"b",0);
12403 aopPut(AOP(dest),"a",1);
12404 freeAsmop (dest, NULL, ic, FALSE);
12407 /*-----------------------------------------------------------------*/
12408 /* genMemsetX - gencode for memSetX data */
12409 /*-----------------------------------------------------------------*/
12410 static void genMemsetX(iCode *ic, int nparms, operand **parms)
12412 operand *to , *val , *count;
12418 /* we know it has to be 3 parameters */
12419 assert (nparms == 3);
12425 /* save DPTR if it needs to be saved */
12426 rsave = newBitVect(16);
12427 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12428 if (bitVectBitValue(ic->rMask,i))
12429 rsave = bitVectSetBit(rsave,i);
12431 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12432 ds390_rUmaskForOp (IC_RESULT(ic))));
12435 aopOp (to, ic, FALSE, FALSE);
12436 /* get "to" into DPTR */
12437 /* if the operand is already in dptr
12438 then we do nothing else we move the value to dptr */
12439 if (AOP_TYPE (to) != AOP_STR) {
12440 /* if already in DPTR then we need to push */
12441 if (AOP_TYPE(to) == AOP_DPTR) {
12442 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12443 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12444 if (options.model == MODEL_FLAT24)
12445 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12446 emitcode ("pop", "dph");
12447 emitcode ("pop", "dpl");
12449 _startLazyDPSEvaluation ();
12450 /* if this is remateriazable */
12451 if (AOP_TYPE (to) == AOP_IMMD) {
12452 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12453 } else { /* we need to get it byte by byte */
12454 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12455 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12456 if (options.model == MODEL_FLAT24) {
12457 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12460 _endLazyDPSEvaluation ();
12463 freeAsmop (to, NULL, ic, FALSE);
12465 aopOp (val, ic->next->next, FALSE,FALSE);
12466 aopOp (count, ic->next->next, FALSE,FALSE);
12467 lbl =newiTempLabel(NULL);
12468 /* now for the actual copy */
12469 if (AOP_TYPE(count) == AOP_LIT &&
12470 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12471 l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
12472 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12474 emitcode ("","!tlabeldef",lbl->key+100);
12475 emitcode ("movx", "@dptr,a");
12476 emitcode ("inc", "dptr");
12477 emitcode ("djnz","b,!tlabel",lbl->key+100);
12479 symbol *lbl1 = newiTempLabel(NULL);
12481 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12482 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12483 emitcode ("","!tlabeldef",lbl->key+100);
12484 MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
12485 emitcode ("movx", "@dptr,a");
12486 emitcode ("inc", "dptr");
12487 emitcode ("mov","a,b");
12488 emitcode ("orl","a,_ap");
12489 emitcode ("jz","!tlabel",lbl1->key+100);
12490 emitcode ("mov","a,_ap");
12491 emitcode ("add","a,#!constbyte",0xFF);
12492 emitcode ("mov","_ap,a");
12493 emitcode ("mov","a,b");
12494 emitcode ("addc","a,#!constbyte",0xFF);
12495 emitcode ("mov","b,a");
12496 emitcode ("sjmp","!tlabel",lbl->key+100);
12497 emitcode ("","!tlabeldef",lbl1->key+100);
12499 freeAsmop (count, NULL, ic, FALSE);
12500 unsavermask(rsave);
12503 /*-----------------------------------------------------------------*/
12504 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12505 /*-----------------------------------------------------------------*/
12506 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12509 operand *pnum, *result;
12512 assert (nparms==1);
12513 /* save registers that need to be saved */
12514 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12515 ds390_rUmaskForOp (IC_RESULT(ic))));
12518 aopOp (pnum, ic, FALSE, FALSE);
12519 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12520 freeAsmop (pnum, NULL, ic, FALSE);
12521 emitcode ("lcall","NatLib_LoadPrimitive");
12522 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12523 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
12524 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12525 for (i = (size-1) ; i >= 0 ; i-- ) {
12526 emitcode ("push","a%s",javaRet[i]);
12528 for (i=0; i < size ; i++ ) {
12529 emitcode ("pop","a%s",
12530 aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12533 for (i = 0 ; i < size ; i++ ) {
12534 aopPut(AOP(result),javaRet[i],i);
12537 freeAsmop (result, NULL, ic, FALSE);
12538 unsavermask(rsave);
12541 /*-----------------------------------------------------------------*/
12542 /* genNatLibLoadPointer - calls TINI api function to load pointer */
12543 /*-----------------------------------------------------------------*/
12544 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12547 operand *pnum, *result;
12551 assert (nparms==1);
12552 /* save registers that need to be saved */
12553 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12554 ds390_rUmaskForOp (IC_RESULT(ic))));
12557 aopOp (pnum, ic, FALSE, FALSE);
12558 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12559 freeAsmop (pnum, NULL, ic, FALSE);
12560 emitcode ("lcall","NatLib_LoadPointer");
12561 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12562 if (AOP_TYPE(result)!=AOP_STR) {
12563 for (i = 0 ; i < size ; i++ ) {
12564 aopPut(AOP(result),fReturn[i],i);
12567 freeAsmop (result, NULL, ic, FALSE);
12568 unsavermask(rsave);
12571 /*-----------------------------------------------------------------*/
12572 /* genNatLibInstallStateBlock - */
12573 /*-----------------------------------------------------------------*/
12574 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
12575 operand **parms, const char *name)
12578 operand *psb, *handle;
12579 assert (nparms==2);
12581 /* save registers that need to be saved */
12582 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12583 ds390_rUmaskForOp (IC_RESULT(ic))));
12587 /* put pointer to state block into DPTR1 */
12588 aopOp (psb, ic, FALSE, FALSE);
12589 if (AOP_TYPE (psb) == AOP_IMMD) {
12590 emitcode ("mov","dps,#1");
12591 emitcode ("mov", "dptr,%s",
12592 aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12593 emitcode ("mov","dps,#0");
12595 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12596 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12597 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12599 freeAsmop (psb, NULL, ic, FALSE);
12601 /* put libraryID into DPTR */
12602 emitcode ("mov","dptr,#LibraryID");
12604 /* put handle into r3:r2 */
12605 aopOp (handle, ic, FALSE, FALSE);
12606 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12607 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12608 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12609 emitcode ("pop","ar3");
12610 emitcode ("pop","ar2");
12612 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12613 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12615 freeAsmop (psb, NULL, ic, FALSE);
12617 /* make the call */
12618 emitcode ("lcall","NatLib_Install%sStateBlock",name);
12620 /* put return value into place*/
12622 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12624 aopPut(AOP(IC_RESULT(ic)),"a",0);
12625 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12626 unsavermask(rsave);
12629 /*-----------------------------------------------------------------*/
12630 /* genNatLibRemoveStateBlock - */
12631 /*-----------------------------------------------------------------*/
12632 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12638 /* save registers that need to be saved */
12639 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12640 ds390_rUmaskForOp (IC_RESULT(ic))));
12642 /* put libraryID into DPTR */
12643 emitcode ("mov","dptr,#LibraryID");
12644 /* make the call */
12645 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12646 unsavermask(rsave);
12649 /*-----------------------------------------------------------------*/
12650 /* genNatLibGetStateBlock - */
12651 /*-----------------------------------------------------------------*/
12652 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12653 operand **parms,const char *name)
12656 symbol *lbl = newiTempLabel(NULL);
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 emitcode ("jnz","!tlabel",lbl->key+100);
12669 /* put return value into place */
12670 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12671 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12672 emitcode ("push","ar3");
12673 emitcode ("push","ar2");
12674 emitcode ("pop","%s",
12675 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12676 emitcode ("pop","%s",
12677 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12679 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12680 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12682 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12683 emitcode ("","!tlabeldef",lbl->key+100);
12684 unsavermask(rsave);
12687 /*-----------------------------------------------------------------*/
12688 /* genMMMalloc - */
12689 /*-----------------------------------------------------------------*/
12690 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12691 int size, const char *name)
12696 symbol *lbl = newiTempLabel(NULL);
12698 assert (nparms == 1);
12699 /* save registers that need to be saved */
12700 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12701 ds390_rUmaskForOp (IC_RESULT(ic))));
12704 aopOp (bsize,ic,FALSE,FALSE);
12706 /* put the size in R4-R2 */
12707 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12708 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12709 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12711 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12712 emitcode("pop","ar4");
12714 emitcode("pop","ar3");
12715 emitcode("pop","ar2");
12717 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12718 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12720 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12723 freeAsmop (bsize, NULL, ic, FALSE);
12725 /* make the call */
12726 emitcode ("lcall","MM_%s",name);
12727 emitcode ("jz","!tlabel",lbl->key+100);
12728 emitcode ("mov","r2,#!constbyte",0xff);
12729 emitcode ("mov","r3,#!constbyte",0xff);
12730 emitcode ("","!tlabeldef",lbl->key+100);
12731 /* we don't care about the pointer : we just save the handle */
12732 rsym = OP_SYMBOL(IC_RESULT(ic));
12733 if (rsym->liveFrom != rsym->liveTo) {
12734 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12735 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12736 emitcode ("push","ar3");
12737 emitcode ("push","ar2");
12738 emitcode ("pop","%s",
12739 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12740 emitcode ("pop","%s",
12741 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12743 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12744 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12746 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12748 unsavermask(rsave);
12751 /*-----------------------------------------------------------------*/
12753 /*-----------------------------------------------------------------*/
12754 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12759 assert (nparms == 1);
12760 /* save registers that need to be saved */
12761 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12762 ds390_rUmaskForOp (IC_RESULT(ic))));
12765 aopOp (handle,ic,FALSE,FALSE);
12767 /* put the size in R4-R2 */
12768 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12769 emitcode("push","%s",
12770 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12771 emitcode("push","%s",
12772 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12773 emitcode("pop","ar3");
12774 emitcode("pop","ar2");
12776 emitcode ("mov","r2,%s",
12777 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12778 emitcode ("mov","r3,%s",
12779 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12781 freeAsmop (handle, NULL, ic, FALSE);
12783 /* make the call */
12784 emitcode ("lcall","MM_Deref");
12787 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12788 if (rsym->liveFrom != rsym->liveTo) {
12789 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12790 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12791 _startLazyDPSEvaluation ();
12793 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12794 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12795 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12797 _endLazyDPSEvaluation ();
12802 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12803 unsavermask(rsave);
12806 /*-----------------------------------------------------------------*/
12807 /* genMMUnrestrictedPersist - */
12808 /*-----------------------------------------------------------------*/
12809 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12814 assert (nparms == 1);
12815 /* save registers that need to be saved */
12816 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12817 ds390_rUmaskForOp (IC_RESULT(ic))));
12820 aopOp (handle,ic,FALSE,FALSE);
12822 /* put the size in R3-R2 */
12823 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12824 emitcode("push","%s",
12825 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12826 emitcode("push","%s",
12827 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12828 emitcode("pop","ar3");
12829 emitcode("pop","ar2");
12831 emitcode ("mov","r2,%s",
12832 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12833 emitcode ("mov","r3,%s",
12834 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12836 freeAsmop (handle, NULL, ic, FALSE);
12838 /* make the call */
12839 emitcode ("lcall","MM_UnrestrictedPersist");
12842 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12843 if (rsym->liveFrom != rsym->liveTo) {
12844 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12845 aopPut(AOP(IC_RESULT(ic)),"a",0);
12846 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12849 unsavermask(rsave);
12852 /*-----------------------------------------------------------------*/
12853 /* genSystemExecJavaProcess - */
12854 /*-----------------------------------------------------------------*/
12855 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12858 operand *handle, *pp;
12860 assert (nparms==2);
12861 /* save registers that need to be saved */
12862 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12863 ds390_rUmaskForOp (IC_RESULT(ic))));
12868 /* put the handle in R3-R2 */
12869 aopOp (handle,ic,FALSE,FALSE);
12870 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12871 emitcode("push","%s",
12872 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12873 emitcode("push","%s",
12874 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12875 emitcode("pop","ar3");
12876 emitcode("pop","ar2");
12878 emitcode ("mov","r2,%s",
12879 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12880 emitcode ("mov","r3,%s",
12881 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12883 freeAsmop (handle, NULL, ic, FALSE);
12885 /* put pointer in DPTR */
12886 aopOp (pp,ic,FALSE,FALSE);
12887 if (AOP_TYPE(pp) == AOP_IMMD) {
12888 emitcode ("mov", "dptr,%s",
12889 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12890 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12891 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12892 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12893 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12895 freeAsmop (handle, NULL, ic, FALSE);
12897 /* make the call */
12898 emitcode ("lcall","System_ExecJavaProcess");
12900 /* put result in place */
12902 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12903 if (rsym->liveFrom != rsym->liveTo) {
12904 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12905 aopPut(AOP(IC_RESULT(ic)),"a",0);
12906 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12910 unsavermask(rsave);
12913 /*-----------------------------------------------------------------*/
12914 /* genSystemRTCRegisters - */
12915 /*-----------------------------------------------------------------*/
12916 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12922 assert (nparms==1);
12923 /* save registers that need to be saved */
12924 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12925 ds390_rUmaskForOp (IC_RESULT(ic))));
12928 /* put pointer in DPTR */
12929 aopOp (pp,ic,FALSE,FALSE);
12930 if (AOP_TYPE (pp) == AOP_IMMD) {
12931 emitcode ("mov","dps,#1");
12932 emitcode ("mov", "dptr,%s",
12933 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12934 emitcode ("mov","dps,#0");
12936 emitcode ("mov","dpl1,%s",
12937 aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12938 emitcode ("mov","dph1,%s",
12939 aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12940 emitcode ("mov","dpx1,%s",
12941 aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12943 freeAsmop (pp, NULL, ic, FALSE);
12945 /* make the call */
12946 emitcode ("lcall","System_%sRTCRegisters",name);
12948 unsavermask(rsave);
12951 /*-----------------------------------------------------------------*/
12952 /* genSystemThreadSleep - */
12953 /*-----------------------------------------------------------------*/
12954 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12959 assert (nparms==1);
12960 /* save registers that need to be saved */
12961 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12962 ds390_rUmaskForOp (IC_RESULT(ic))));
12965 aopOp(to,ic,FALSE,FALSE);
12966 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12967 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12968 emitcode ("push","%s",
12969 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12970 emitcode ("push","%s",
12971 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12972 emitcode ("push","%s",
12973 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12974 emitcode ("push","%s",
12975 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12976 emitcode ("pop","ar3");
12977 emitcode ("pop","ar2");
12978 emitcode ("pop","ar1");
12979 emitcode ("pop","ar0");
12981 emitcode ("mov","r0,%s",
12982 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12983 emitcode ("mov","r1,%s",
12984 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12985 emitcode ("mov","r2,%s",
12986 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12987 emitcode ("mov","r3,%s",
12988 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12990 freeAsmop (to, NULL, ic, FALSE);
12992 /* suspend in acc */
12994 aopOp(s,ic,FALSE,FALSE);
12995 emitcode ("mov","a,%s",
12996 aopGet(AOP(s),0,FALSE,TRUE,NULL));
12997 freeAsmop (s, NULL, ic, FALSE);
12999 /* make the call */
13000 emitcode ("lcall","System_%s",name);
13002 unsavermask(rsave);
13005 /*-----------------------------------------------------------------*/
13006 /* genSystemThreadResume - */
13007 /*-----------------------------------------------------------------*/
13008 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
13013 assert (nparms==2);
13014 /* save registers that need to be saved */
13015 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13016 ds390_rUmaskForOp (IC_RESULT(ic))));
13022 aopOp(pid,ic,FALSE,FALSE);
13023 emitcode ("mov","r0,%s",
13024 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13025 freeAsmop (pid, NULL, ic, FALSE);
13028 aopOp(tid,ic,FALSE,FALSE);
13029 emitcode ("mov","a,%s",
13030 aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
13031 freeAsmop (tid, NULL, ic, FALSE);
13033 emitcode ("lcall","System_ThreadResume");
13035 /* put result into place */
13037 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13038 if (rsym->liveFrom != rsym->liveTo) {
13039 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13040 aopPut(AOP(IC_RESULT(ic)),"a",0);
13041 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13044 unsavermask(rsave);
13047 /*-----------------------------------------------------------------*/
13048 /* genSystemProcessResume - */
13049 /*-----------------------------------------------------------------*/
13050 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
13055 assert (nparms==1);
13056 /* save registers that need to be saved */
13057 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13058 ds390_rUmaskForOp (IC_RESULT(ic))));
13063 aopOp(pid,ic,FALSE,FALSE);
13064 emitcode ("mov","a,%s",
13065 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13066 freeAsmop (pid, NULL, ic, FALSE);
13068 emitcode ("lcall","System_ProcessResume");
13070 unsavermask(rsave);
13073 /*-----------------------------------------------------------------*/
13075 /*-----------------------------------------------------------------*/
13076 static void genSystem (iCode *ic,int nparms,char *name)
13078 assert(nparms == 0);
13080 emitcode ("lcall","System_%s",name);
13083 /*-----------------------------------------------------------------*/
13084 /* genSystemPoll - */
13085 /*-----------------------------------------------------------------*/
13086 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
13091 assert (nparms==1);
13092 /* save registers that need to be saved */
13093 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13094 ds390_rUmaskForOp (IC_RESULT(ic))));
13097 aopOp (fp,ic,FALSE,FALSE);
13098 if (AOP_TYPE (fp) == AOP_IMMD) {
13099 emitcode ("mov", "dptr,%s",
13100 aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
13101 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
13102 emitcode ("mov","dpl,%s",
13103 aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
13104 emitcode ("mov","dph,%s",
13105 aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
13106 emitcode ("mov","dpx,%s",
13107 aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
13109 freeAsmop (fp, NULL, ic, FALSE);
13111 emitcode ("lcall","System_%sPoll",name);
13113 /* put result into place */
13115 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13116 if (rsym->liveFrom != rsym->liveTo) {
13117 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13118 aopPut(AOP(IC_RESULT(ic)),"a",0);
13119 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13122 unsavermask(rsave);
13125 /*-----------------------------------------------------------------*/
13126 /* genSystemGetCurrentID - */
13127 /*-----------------------------------------------------------------*/
13128 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
13130 assert (nparms==0);
13132 emitcode ("lcall","System_GetCurrent%sId",name);
13133 /* put result into place */
13135 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13136 if (rsym->liveFrom != rsym->liveTo) {
13137 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13138 aopPut(AOP(IC_RESULT(ic)),"a",0);
13139 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13144 /*-----------------------------------------------------------------*/
13145 /* genDummyRead - generate code for dummy read of volatiles */
13146 /*-----------------------------------------------------------------*/
13148 genDummyRead (iCode * ic)
13153 D(emitcode("; genDummyRead",""));
13155 op = IC_RIGHT (ic);
13156 if (op && IS_SYMOP (op))
13158 aopOp (op, ic, FALSE, FALSE);
13160 /* if the result is a bit */
13161 if (AOP_TYPE (op) == AOP_CRY)
13162 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13165 /* bit variables done */
13167 size = AOP_SIZE (op);
13171 MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13176 freeAsmop (op, NULL, ic, TRUE);
13180 if (op && IS_SYMOP (op))
13182 aopOp (op, ic, FALSE, FALSE);
13184 /* if the result is a bit */
13185 if (AOP_TYPE (op) == AOP_CRY)
13186 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13189 /* bit variables done */
13191 size = AOP_SIZE (op);
13195 MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13200 freeAsmop (op, NULL, ic, TRUE);
13205 /*-----------------------------------------------------------------*/
13206 /* genCritical - generate code for start of a critical sequence */
13207 /*-----------------------------------------------------------------*/
13209 genCritical (iCode *ic)
13211 symbol *tlbl = newiTempLabel (NULL);
13213 D(emitcode("; genCritical",""));
13215 if (IC_RESULT (ic))
13216 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
13218 emitcode ("setb", "c");
13219 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
13220 emitcode ("clr", "c");
13221 emitcode ("", "%05d$:", (tlbl->key + 100));
13223 if (IC_RESULT (ic))
13224 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
13226 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
13228 if (IC_RESULT (ic))
13229 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13232 /*-----------------------------------------------------------------*/
13233 /* genEndCritical - generate code for end of a critical sequence */
13234 /*-----------------------------------------------------------------*/
13236 genEndCritical (iCode *ic)
13238 D(emitcode("; genEndCritical",""));
13242 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
13243 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
13245 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
13246 emitcode ("mov", "ea,c");
13250 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE));
13251 emitcode ("rrc", "a");
13252 emitcode ("mov", "ea,c");
13254 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
13258 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
13259 emitcode ("mov", "ea,c");
13265 /*-----------------------------------------------------------------*/
13266 /* genBuiltIn - calls the appropriate function to generating code */
13267 /* for a built in function */
13268 /*-----------------------------------------------------------------*/
13269 static void genBuiltIn (iCode *ic)
13271 operand *bi_parms[MAX_BUILTIN_ARGS];
13276 /* get all the arguments for a built in function */
13277 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
13279 /* which function is it */
13280 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
13281 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
13282 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
13283 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
13284 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
13285 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
13286 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
13287 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
13288 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
13289 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
13290 genMemsetX(bi_iCode,nbi_parms,bi_parms);
13291 } else if (strcmp(bif->name,"__builtin_inp")==0) {
13292 genInp(bi_iCode,nbi_parms,bi_parms);
13293 } else if (strcmp(bif->name,"__builtin_outp")==0) {
13294 genOutp(bi_iCode,nbi_parms,bi_parms);
13295 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
13296 genSwapW(bi_iCode,nbi_parms,bi_parms);
13297 /* JavaNative builtIns */
13298 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
13299 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
13300 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
13301 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
13302 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
13303 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
13304 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
13305 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
13306 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
13307 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13308 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
13309 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13310 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
13311 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
13312 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
13313 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
13314 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
13315 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13316 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
13317 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13318 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
13319 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
13320 } else if (strcmp(bif->name,"MM_Malloc")==0) {
13321 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
13322 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
13323 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
13324 } else if (strcmp(bif->name,"MM_Free")==0) {
13325 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
13326 } else if (strcmp(bif->name,"MM_Deref")==0) {
13327 genMMDeref(bi_iCode,nbi_parms,bi_parms);
13328 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
13329 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
13330 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
13331 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
13332 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
13333 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
13334 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
13335 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
13336 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
13337 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
13338 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
13339 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
13340 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
13341 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
13342 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
13343 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
13344 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13345 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13346 } else if (strcmp(bif->name,"System_SaveThread")==0) {
13347 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13348 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13349 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13350 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
13351 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
13352 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
13353 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
13354 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
13355 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
13356 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
13357 genSystem(bi_iCode,nbi_parms,"ProcessYield");
13358 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
13359 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
13360 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
13361 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
13362 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
13363 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
13364 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
13365 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
13366 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
13367 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
13369 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
13375 /*-----------------------------------------------------------------*/
13376 /* gen390Code - generate code for Dallas 390 based controllers */
13377 /*-----------------------------------------------------------------*/
13379 gen390Code (iCode * lic)
13384 lineHead = lineCurr = NULL;
13385 dptrn[1][0] = "dpl1";
13386 dptrn[1][1] = "dph1";
13387 dptrn[1][2] = "dpx1";
13389 if (options.model == MODEL_FLAT24) {
13390 fReturnSizeDS390 = 5;
13391 fReturn = fReturn24;
13393 fReturnSizeDS390 = 4;
13394 fReturn = fReturn16;
13395 options.stack10bit=0;
13398 /* print the allocation information */
13399 if (allocInfo && currFunc)
13400 printAllocInfo (currFunc, codeOutFile);
13402 /* if debug information required */
13403 if (options.debug && currFunc)
13405 debugFile->writeFunction(currFunc);
13407 if (IS_STATIC (currFunc->etype))
13408 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
13410 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
13413 /* stack pointer name */
13414 if (options.useXstack)
13420 for (ic = lic; ic; ic = ic->next)
13423 _G.current_iCode = ic;
13425 if (ic->lineno && cln != ic->lineno)
13430 emitcode ("", "C$%s$%d$%d$%d ==.",
13431 FileBaseName (ic->filename), ic->lineno,
13432 ic->level, ic->block);
13435 if (!options.noCcodeInAsm) {
13436 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
13437 printCLine(ic->filename, ic->lineno));
13441 if (options.iCodeInAsm) {
13442 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
13444 /* if the result is marked as
13445 spilt and rematerializable or code for
13446 this has already been generated then
13448 if (resultRemat (ic) || ic->generated)
13451 /* depending on the operation */
13471 /* IPOP happens only when trying to restore a
13472 spilt live range, if there is an ifx statement
13473 following this pop then the if statement might
13474 be using some of the registers being popped which
13475 would destory the contents of the register so
13476 we need to check for this condition and handle it */
13478 ic->next->op == IFX &&
13479 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
13480 genIfx (ic->next, ic);
13498 genEndFunction (ic);
13518 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
13535 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
13539 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
13546 /* note these two are xlated by algebraic equivalence
13547 during parsing SDCC.y */
13548 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13549 "got '>=' or '<=' shouldn't have come here");
13553 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
13565 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
13569 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
13573 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
13597 genRightShift (ic);
13600 case GET_VALUE_AT_ADDRESS:
13601 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13605 if (POINTER_SET (ic))
13606 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13632 if (ic->builtinSEND) genBuiltIn(ic);
13633 else addSet (&_G.sendSet, ic);
13636 case DUMMY_READ_VOLATILE:
13645 genEndCritical (ic);
13652 #if 0 // obsolete, and buggy for != xdata
13664 /* now we are ready to call the
13665 peep hole optimizer */
13666 if (!options.nopeep)
13667 peepHole (&lineHead);
13669 /* now do the actual printing */
13670 printLine (lineHead, codeOutFile);