1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for DS80C390
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 DS390 adaptation by Kevin Vigor <kevin@vigor.nu>
9 This program is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 In other words, you are welcome to use, share and improve this program.
24 You are forbidden to forbid anyone else to use, share and improve
25 what you give them. Help stamp out software-hoarding!
26 -------------------------------------------------------------------------*/
37 #include "SDCCglobl.h"
40 #define BETTER_LITERAL_SHIFT
42 char *aopLiteral (value * val, int offset);
45 /* this is the down and dirty file with all kinds of
46 kludgy & hacky stuff. This is what it is all about
47 CODE GENERATION for a specific MCU . some of the
48 routines may be reusable, will have to see */
50 static char *zero = "#0";
51 static char *one = "#1";
56 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
57 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
59 short fReturnSizeDS390 = 5;
60 static char *fReturn24[] =
61 {"dpl", "dph", "dpx", "b", "a"};
62 static char *fReturn16[] =
63 {"dpl", "dph", "b", "a"};
64 static char **fReturn = fReturn24;
65 static char *accUse[] =
67 static char *dptrn[2][3];
68 static char *javaRet[] = { "r0","r1","r2","r3"};
69 static short rbank = -1;
87 static char *rb1regs[] = {
88 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
91 static void saveRBank (int, iCode *, bool);
93 #define RESULTONSTACK(x) \
94 (IC_RESULT(x) && IC_RESULT(x)->aop && \
95 IC_RESULT(x)->aop->type == AOP_STK )
97 #define MOVA(x) _movA(x)
98 #define MOVB(x) _movB(x)
100 #define CLRC emitcode("clr","c")
101 #define SETC emitcode("setb","c")
103 // A scratch register which will be used to hold
104 // result bytes from operands in far space via DPTR2.
105 #define DP2_RESULT_REG "_ap"
107 static lineNode *lineHead = NULL;
108 static lineNode *lineCurr = NULL;
110 static unsigned char SLMask[] =
111 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
112 0xE0, 0xC0, 0x80, 0x00};
113 static unsigned char SRMask[] =
114 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
115 0x07, 0x03, 0x01, 0x00};
121 #define PROTECT_SP {if (options.protect_sp_update) { \
122 symbol *lbl = newiTempLabel(NULL); \
123 emitcode ("setb","F1"); \
124 emitcode ("jbc","EA,!tlabel",lbl->key+100); \
125 emitcode ("clr","F1"); \
126 emitcode ("","!tlabeldef",lbl->key+100); \
128 #define UNPROTECT_SP { if (options.protect_sp_update) { \
129 symbol *lbl = newiTempLabel(NULL); \
130 emitcode ("jnb","F1,!tlabel",lbl->key+100); \
131 emitcode ("setb","EA"); \
132 emitcode ("","!tlabeldef",lbl->key+100); \
135 static int _currentDPS; /* Current processor DPS. */
136 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
137 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
139 /*-----------------------------------------------------------------*/
140 /* emitcode - writes the code into a file : for now it is simple */
141 /*-----------------------------------------------------------------*/
143 emitcode (char *inst, const char *fmt,...)
146 char lb[INITIAL_INLINEASM];
155 SNPRINTF (lb, sizeof(lb), "%s\t", inst);
159 SNPRINTF (lb, sizeof(lb), "%s", inst);
162 tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), fmt, ap);
166 tvsprintf (lb, sizeof(lb), fmt, ap);
169 while (isspace ((unsigned char)*lbp))
176 lineCurr = (lineCurr ?
177 connectLine (lineCurr, newLineNode (lb)) :
178 (lineHead = newLineNode (lb)));
181 lineCurr->isInline = _G.inLine;
182 lineCurr->isDebug = _G.debugLine;
183 lineCurr->ic = _G.current_iCode;
184 lineCurr->aln = ds390newAsmLineNode(_currentDPS);
188 /*-----------------------------------------------------------------*/
189 /* ds390_emitDebuggerSymbol - associate the current code location */
190 /* with a debugger symbol */
191 /*-----------------------------------------------------------------*/
193 ds390_emitDebuggerSymbol (char * debugSym)
196 emitcode ("", "%s ==.", debugSym);
201 // Move the passed value into A unless it is already there.
206 if (strcmp(s,"a") && strcmp(s,"acc"))
208 emitcode("mov","a,%s",s);
213 // Move the passed value into B unless it is already there.
220 emitcode("mov","b,%s",s);
224 /*-----------------------------------------------------------------*/
225 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
226 /*-----------------------------------------------------------------*/
228 getFreePtr (iCode * ic, asmop ** aopp, bool result)
233 /* the logic: if r0 & r1 used in the instruction
234 then we are in trouble otherwise */
236 /* first check if r0 & r1 are used by this
237 instruction, in which case we are in trouble */
238 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
239 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
244 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
245 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
247 /* if no usage of r0 then return it */
250 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
251 (*aopp)->type = AOP_R0;
253 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
256 /* if no usage of r1 then return it */
259 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
260 (*aopp)->type = AOP_R1;
262 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
265 /* now we know they both have usage */
266 /* if r0 not used in this instruction */
269 /* push it if not already pushed */
272 emitcode ("push", "%s",
273 ds390_regWithIdx (R0_IDX)->dname);
277 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
278 (*aopp)->type = AOP_R0;
280 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
283 /* if r1 not used then */
287 /* push it if not already pushed */
290 emitcode ("push", "%s",
291 ds390_regWithIdx (R1_IDX)->dname);
295 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
296 (*aopp)->type = AOP_R1;
297 return ds390_regWithIdx (R1_IDX);
301 /* I said end of world but not quite end of world yet */
302 /* if this is a result then we can push it on the stack */
305 (*aopp)->type = AOP_STK;
309 /* other wise this is true end of the world */
310 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
311 "getFreePtr should never reach here");
314 return NULL; // notreached, but makes compiler happy.
317 /*-----------------------------------------------------------------*/
318 /* newAsmop - creates a new asmOp */
319 /*-----------------------------------------------------------------*/
321 newAsmop (short type)
325 aop = Safe_calloc (1, sizeof (asmop));
331 /*-----------------------------------------------------------------*/
332 /* genSetDPTR: generate code to select which DPTR is in use (zero */
333 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
334 /* alternate DPTR (DPL1/DPH1/DPX1). */
335 /*-----------------------------------------------------------------*/
340 /* If we are doing lazy evaluation, simply note the desired
341 * change, but don't emit any code yet.
351 emitcode ("mov", "dps,#0");
356 emitcode ("mov", "dps,#1");
360 /*-----------------------------------------------------------------*/
361 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
363 /* Any code that operates on DPTR (NB: not on the individual */
364 /* components, like DPH) *must* call _flushLazyDPS() before using */
365 /* DPTR within a lazy DPS evaluation block. */
367 /* Note that aopPut and aopGet already contain the proper calls to */
368 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
369 /* DPS evaluation block. */
371 /* Also, _flushLazyDPS must be called before any flow control */
372 /* operations that could potentially branch out of the block. */
374 /* Lazy DPS evaluation is simply an optimization (though an */
375 /* important one), so if in doubt, leave it out. */
376 /*-----------------------------------------------------------------*/
378 _startLazyDPSEvaluation (void)
382 #ifdef BETTER_LITERAL_SHIFT
389 /*-----------------------------------------------------------------*/
390 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
391 /* desired one. Call before using DPTR within a lazy DPS evaluation */
393 /*-----------------------------------------------------------------*/
403 if (_desiredDPS != _currentDPS)
407 emitcode ("inc", "dps");
411 emitcode ("dec", "dps");
413 _currentDPS = _desiredDPS;
417 /*-----------------------------------------------------------------*/
418 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
420 /* Forces us back to the safe state (standard DPTR selected). */
421 /*-----------------------------------------------------------------*/
423 _endLazyDPSEvaluation (void)
425 #ifdef BETTER_LITERAL_SHIFT
444 /*-----------------------------------------------------------------*/
445 /* pointerCode - returns the code for a pointer type */
446 /*-----------------------------------------------------------------*/
448 pointerCode (sym_link * etype)
451 return PTR_TYPE (SPEC_OCLS (etype));
455 /*-----------------------------------------------------------------*/
456 /* leftRightUseAcc - returns size of accumulator use by operands */
457 /*-----------------------------------------------------------------*/
459 leftRightUseAcc(iCode *ic)
468 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
469 "null iCode pointer");
476 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
479 size = getSize (OP_SYMBOL (op)->type);
484 else if (ic->op == JUMPTABLE)
487 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
490 size = getSize (OP_SYMBOL (op)->type);
498 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
501 size = getSize (OP_SYMBOL (op)->type);
506 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
509 size = getSize (OP_SYMBOL (op)->type);
521 /*-----------------------------------------------------------------*/
522 /* aopForSym - for a true symbol */
523 /*-----------------------------------------------------------------*/
525 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
528 memmap *space = SPEC_OCLS (sym->etype);
529 int accuse = leftRightUseAcc (ic);
531 /* if already has one */
534 if ((sym->aop->type == AOP_DPTR && useDP2)
535 || (sym->aop->type == AOP_DPTR2 && !useDP2))
541 /* assign depending on the storage class */
542 /* if it is on the stack or indirectly addressable */
543 /* space we need to assign either r0 or r1 to it */
544 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
546 sym->aop = aop = newAsmop (0);
547 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
548 aop->size = getSize (sym->type);
550 /* now assign the address of the variable to
551 the pointer register */
552 if (aop->type != AOP_STK)
557 if (_G.accInUse || accuse)
558 emitcode ("push", "acc");
560 if (_G.bInUse || (accuse>1))
561 emitcode ("push", "b");
563 emitcode ("mov", "a,_bp");
564 emitcode ("add", "a,#!constbyte",
566 ((char) (sym->stack - _G.nRegsSaved)) :
567 ((char) sym->stack)) & 0xff);
568 emitcode ("mov", "%s,a",
569 aop->aopu.aop_ptr->name);
571 if (_G.bInUse || (accuse>1))
572 emitcode ("pop", "b");
574 if (_G.accInUse || accuse)
575 emitcode ("pop", "acc");
578 emitcode ("mov", "%s,#%s",
579 aop->aopu.aop_ptr->name,
581 aop->paged = space->paged;
584 aop->aopu.aop_stk = sym->stack;
588 if (sym->onStack && options.stack10bit)
590 short stack_val = -((sym->stack < 0) ?
591 ((short) (sym->stack - _G.nRegsSaved)) :
592 ((short) sym->stack)) ;
593 if (useDP2 && _G.dptr1InUse) {
594 emitcode ("push","dpl1");
595 emitcode ("push","dph1");
596 emitcode ("push","dpx1");
597 } else if (_G.dptrInUse ) {
598 emitcode ("push","dpl");
599 emitcode ("push","dph");
600 emitcode ("push","dpx");
602 /* It's on the 10 bit stack, which is located in
605 if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
607 if (options.model == MODEL_FLAT24)
609 emitcode ("mov", "dpx1,#!constbyte",
610 (options.stack_loc >> 16) & 0xff);
612 emitcode ("mov", "dph1,_bpx+1");
614 emitcode ("mov", "dpl1,_bpx");
615 emitcode ("mov","dps,#1");
617 if (options.model == MODEL_FLAT24)
619 emitcode ("mov", "dpx,#!constbyte",
620 (options.stack_loc >> 16) & 0xff);
622 emitcode ("mov", "dph,_bpx+1");
623 emitcode ("mov", "dpl,_bpx");
625 stack_val = -stack_val;
626 while (stack_val--) {
627 emitcode ("inc","dptr");
630 emitcode("mov","dps,#0");
633 if (_G.accInUse || accuse)
634 emitcode ("push", "acc");
636 if (_G.bInUse || (accuse>1))
637 emitcode ("push", "b");
639 emitcode ("mov", "a,_bpx");
640 emitcode ("clr","c");
641 emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
642 emitcode ("mov","b,a");
643 emitcode ("mov","a,_bpx+1");
644 emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
646 if (options.model == MODEL_FLAT24)
648 emitcode ("mov", "dpx1,#!constbyte",
649 (options.stack_loc >> 16) & 0xff);
651 emitcode ("mov", "dph1,a");
652 emitcode ("mov", "dpl1,b");
654 if (options.model == MODEL_FLAT24)
656 emitcode ("mov", "dpx,#!constbyte",
657 (options.stack_loc >> 16) & 0xff);
659 emitcode ("mov", "dph,a");
660 emitcode ("mov", "dpl,b");
663 if (_G.bInUse || (accuse>1))
664 emitcode ("pop", "b");
666 if (_G.accInUse || accuse)
667 emitcode ("pop", "acc");
669 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
670 aop->size = getSize (sym->type);
674 /* if in bit space */
675 if (IN_BITSPACE (space))
677 sym->aop = aop = newAsmop (AOP_CRY);
678 aop->aopu.aop_dir = sym->rname;
679 aop->size = getSize (sym->type);
682 /* if it is in direct space */
683 if (IN_DIRSPACE (space))
685 sym->aop = aop = newAsmop (AOP_DIR);
686 aop->aopu.aop_dir = sym->rname;
687 aop->size = getSize (sym->type);
691 /* special case for a function */
692 if (IS_FUNC (sym->type) && !(sym->isitmp))
694 sym->aop = aop = newAsmop (AOP_IMMD);
695 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
696 aop->size = FPTRSIZE;
700 /* only remaining is far space */
701 /* in which case DPTR gets the address */
702 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
707 emitcode ("mov", "dptr,#%s", sym->rname);
712 emitcode ("mov", "dptr,#%s", sym->rname);
714 aop->size = getSize (sym->type);
716 /* if it is in code space */
717 if (IN_CODESPACE (space))
723 /*-----------------------------------------------------------------*/
724 /* aopForRemat - rematerialzes an object */
725 /*-----------------------------------------------------------------*/
727 aopForRemat (symbol * sym)
729 iCode *ic = sym->rematiCode;
730 asmop *aop = newAsmop (AOP_IMMD);
737 val += (int) operandLitValue (IC_RIGHT (ic));
738 else if (ic->op == '-')
739 val -= (int) operandLitValue (IC_RIGHT (ic));
740 else if (IS_CAST_ICODE(ic)) {
741 sym_link *from_type = operandType(IC_RIGHT(ic));
742 aop->aopu.aop_immd.from_cast_remat = 1;
743 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
744 ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
748 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
753 SNPRINTF (buffer, sizeof(buffer),
755 OP_SYMBOL (IC_LEFT (ic))->rname,
756 val >= 0 ? '+' : '-',
757 abs (val) & 0xffffff);
761 if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
763 SNPRINTF(buffer, sizeof(buffer),
764 "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
768 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
772 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
773 /* set immd2 field if required */
774 if (aop->aopu.aop_immd.from_cast_remat)
776 tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
777 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
783 /*-----------------------------------------------------------------*/
784 /* aopHasRegs - returns true if aop has regs between from-to */
785 /*-----------------------------------------------------------------*/
786 static int aopHasRegs(asmop *aop, int from, int to)
790 if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
792 for (; size < aop->size ; size++) {
794 for (reg = from ; reg <= to ; reg++)
795 if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
800 /*-----------------------------------------------------------------*/
801 /* regsInCommon - two operands have some registers in common */
802 /*-----------------------------------------------------------------*/
804 regsInCommon (operand * op1, operand * op2)
809 /* if they have registers in common */
810 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
813 sym1 = OP_SYMBOL (op1);
814 sym2 = OP_SYMBOL (op2);
816 if (sym1->nRegs == 0 || sym2->nRegs == 0)
819 for (i = 0; i < sym1->nRegs; i++)
825 for (j = 0; j < sym2->nRegs; j++)
830 if (sym2->regs[j] == sym1->regs[i])
838 /*-----------------------------------------------------------------*/
839 /* operandsEqu - equivalent */
840 /*-----------------------------------------------------------------*/
842 operandsEqu (operand * op1, operand * op2)
846 /* if they not symbols */
847 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
850 sym1 = OP_SYMBOL (op1);
851 sym2 = OP_SYMBOL (op2);
853 /* if both are itemps & one is spilt
854 and the other is not then false */
855 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
856 sym1->isspilt != sym2->isspilt)
859 /* if they are the same */
863 if (sym1->rname[0] && sym2->rname[0]
864 && strcmp (sym1->rname, sym2->rname) == 0)
867 /* if left is a tmp & right is not */
868 if (IS_ITEMP (op1) &&
871 (sym1->usl.spillLoc == sym2))
874 if (IS_ITEMP (op2) &&
878 (sym2->usl.spillLoc == sym1))
881 /* are they spilt to the same location */
882 if (IS_ITEMP (op2) &&
886 (sym1->usl.spillLoc == sym2->usl.spillLoc))
892 /*-----------------------------------------------------------------*/
893 /* sameRegs - two asmops have the same registers */
894 /*-----------------------------------------------------------------*/
896 sameRegs (asmop * aop1, asmop * aop2)
902 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
909 if (aop1->type != AOP_REG ||
910 aop2->type != AOP_REG)
913 if (aop1->size != aop2->size)
916 for (i = 0; i < aop1->size; i++)
917 if (aop1->aopu.aop_reg[i] !=
918 aop2->aopu.aop_reg[i])
924 /*-----------------------------------------------------------------*/
925 /* aopOp - allocates an asmop for an operand : */
926 /*-----------------------------------------------------------------*/
928 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
937 /* if this a literal */
938 if (IS_OP_LITERAL (op))
940 op->aop = aop = newAsmop (AOP_LIT);
941 aop->aopu.aop_lit = op->operand.valOperand;
942 aop->size = getSize (operandType (op));
946 /* if already has a asmop then continue */
949 if ((op->aop->type == AOP_DPTR && useDP2)
950 || (op->aop->type == AOP_DPTR2 && !useDP2))
956 /* if the underlying symbol has a aop */
957 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
959 op->aop = OP_SYMBOL (op)->aop;
960 if ((op->aop->type == AOP_DPTR && useDP2)
961 || (op->aop->type == AOP_DPTR2 && !useDP2))
967 /* if this is a true symbol */
968 if (IS_TRUE_SYMOP (op))
970 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
974 /* this is a temporary : this has
980 e) can be a return use only */
982 sym = OP_SYMBOL (op);
984 /* if the type is a conditional */
985 if (sym->regType == REG_CND)
987 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
992 /* if it is spilt then two situations
994 b) has a spill location */
995 if (sym->isspilt || sym->nRegs == 0)
998 /* rematerialize it NOW */
1001 sym->aop = op->aop = aop =
1003 aop->size = getSize (sym->type);
1010 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
1011 aop->size = getSize (sym->type);
1012 for (i = 0; i < 2; i++)
1013 aop->aopu.aop_str[i] = accUse[i];
1023 /* a AOP_STR uses DPTR, but DPTR is already in use;
1026 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
1029 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1030 aop->size = getSize (sym->type);
1031 for (i = 0; i < fReturnSizeDS390; i++)
1032 aop->aopu.aop_str[i] = fReturn[i];
1036 if (sym->dptr) { /* has been allocated to a DPTRn */
1037 aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
1038 aop->size = getSize (sym->type);
1039 aop->aopu.dptr = sym->dptr;
1043 if (sym->usl.spillLoc)
1045 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1047 /* force a new aop if sizes differ */
1048 sym->usl.spillLoc->aop = NULL;
1050 sym->aop = op->aop = aop =
1051 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
1052 aop->size = getSize (sym->type);
1056 /* else must be a dummy iTemp */
1057 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1058 aop->size = getSize (sym->type);
1062 /* must be in a register */
1063 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1064 aop->size = sym->nRegs;
1065 for (i = 0; i < sym->nRegs; i++)
1066 aop->aopu.aop_reg[i] = sym->regs[i];
1069 /*-----------------------------------------------------------------*/
1070 /* freeAsmop - free up the asmop given to an operand */
1071 /*----------------------------------------------------------------*/
1073 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1090 /* depending on the asmop type only three cases need work AOP_RO
1091 , AOP_R1 && AOP_STK */
1099 emitcode ("pop", "ar0");
1103 bitVectUnSetBit (ic->rUsed, R0_IDX);
1111 emitcode ("pop", "ar1");
1115 bitVectUnSetBit (ic->rUsed, R1_IDX);
1121 int stk = aop->aopu.aop_stk + aop->size;
1122 bitVectUnSetBit (ic->rUsed, R0_IDX);
1123 bitVectUnSetBit (ic->rUsed, R1_IDX);
1125 getFreePtr (ic, &aop, FALSE);
1127 if (options.stack10bit)
1129 /* I'm not sure what to do here yet... */
1132 "*** Warning: probably generating bad code for "
1133 "10 bit stack mode.\n");
1138 emitcode ("mov", "a,_bp");
1139 emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1140 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1144 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1149 emitcode ("pop", "acc");
1150 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1153 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1156 freeAsmop (op, NULL, ic, TRUE);
1159 emitcode ("pop", "ar0");
1165 emitcode ("pop", "ar1");
1170 if (_G.dptr1InUse) {
1171 emitcode ("pop","dpx1");
1172 emitcode ("pop","dph1");
1173 emitcode ("pop","dpl1");
1178 emitcode ("pop","dpx");
1179 emitcode ("pop","dph");
1180 emitcode ("pop","dpl");
1185 /* all other cases just dealloc */
1191 OP_SYMBOL (op)->aop = NULL;
1192 /* if the symbol has a spill */
1194 SPIL_LOC (op)->aop = NULL;
1199 #define DEFAULT_ACC_WARNING 0
1200 static int saveAccWarn = DEFAULT_ACC_WARNING;
1202 /*-------------------------------------------------------------------*/
1203 /* aopGet - for fetching value of the aop */
1205 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1206 /* in the accumulator. Set it to the name of a free register */
1207 /* if acc must be preserved; the register will be used to preserve */
1208 /* acc temporarily and to return the result byte. */
1209 /*-------------------------------------------------------------------*/
1218 /* offset is greater than
1220 if (offset > (aop->size - 1) &&
1221 aop->type != AOP_LIT)
1224 /* depending on type */
1232 /* if we need to increment it */
1233 while (offset > aop->coff)
1235 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1239 while (offset < aop->coff)
1241 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1248 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1249 return (dname ? "acc" : "a");
1251 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1252 return Safe_strdup(buffer);
1255 assert(offset <= 3);
1256 return dptrn[aop->aopu.dptr][offset];
1261 if (aop->type == AOP_DPTR2)
1269 // if (aop->type != AOP_DPTR2)
1271 // if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1272 // emitcode(";", "spanky: saveAcc for DPTR");
1275 emitcode ("xch", "a, %s", saveAcc);
1280 while (offset > aop->coff)
1282 emitcode ("inc", "dptr");
1286 while (offset < aop->coff)
1288 emitcode ("lcall", "__decdptr");
1295 emitcode ("clr", "a");
1296 emitcode ("movc", "a,@a+dptr");
1300 emitcode ("movx", "a,@dptr");
1303 if (aop->type == AOP_DPTR2)
1311 emitcode ("xch", "a, %s", saveAcc);
1312 // if (strcmp(saveAcc, "_ap"))
1314 // emitcode(";", "spiffy: non _ap return from aopGet.");
1319 return (dname ? "acc" : "a");
1322 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1324 SNPRINTF(buffer, sizeof(buffer),
1325 "%s",aop->aopu.aop_immd.aop_immd2);
1329 SNPRINTF(buffer, sizeof(buffer),
1330 "#%s", aop->aopu.aop_immd.aop_immd1);
1336 tsprintf(buffer, sizeof(buffer),
1337 "#!his",aop->aopu.aop_immd.aop_immd1);
1340 tsprintf(buffer, sizeof(buffer),
1341 "#!hihis",aop->aopu.aop_immd.aop_immd1);
1344 tsprintf(buffer, sizeof(buffer),
1345 "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1347 default: /* should not need this (just in case) */
1348 SNPRINTF (buffer, sizeof(buffer),
1350 aop->aopu.aop_immd.aop_immd1,
1356 SNPRINTF (buffer, sizeof(buffer),
1357 "#%s", aop->aopu.aop_immd.aop_immd1);
1359 return Safe_strdup(buffer);
1364 SNPRINTF (buffer, sizeof(buffer),
1371 SNPRINTF(buffer, sizeof(buffer),
1372 "%s", aop->aopu.aop_dir);
1375 return Safe_strdup(buffer);
1379 return aop->aopu.aop_reg[offset]->dname;
1381 return aop->aopu.aop_reg[offset]->name;
1384 emitcode ("clr", "a");
1385 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1386 emitcode ("rlc", "a");
1387 return (dname ? "acc" : "a");
1390 if (!offset && dname)
1392 return aop->aopu.aop_str[offset];
1395 return aopLiteral (aop->aopu.aop_lit, offset);
1399 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1403 return aop->aopu.aop_str[offset];
1407 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1408 "aopget got unsupported aop->type");
1411 return NULL; // not reached, but makes compiler happy.
1413 /*-----------------------------------------------------------------*/
1414 /* aopPut - puts a string for a aop */
1415 /*-----------------------------------------------------------------*/
1417 aopPut (asmop * aop, char *s, int offset)
1419 if (aop->size && offset > (aop->size - 1))
1421 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1422 "aopPut got offset > aop->size");
1426 /* will assign value to value */
1427 /* depending on where it is ofcourse */
1431 MOVA (s); /* read s in case it was volatile */
1437 SNPRINTF (buffer, sizeof(buffer),
1439 aop->aopu.aop_dir, offset);
1443 SNPRINTF (buffer, sizeof(buffer),
1444 "%s", aop->aopu.aop_dir);
1448 if (strcmp (buffer, s))
1450 emitcode ("mov", "%s,%s", buffer, s);
1455 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1456 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1459 strcmp (s, "r0") == 0 ||
1460 strcmp (s, "r1") == 0 ||
1461 strcmp (s, "r2") == 0 ||
1462 strcmp (s, "r3") == 0 ||
1463 strcmp (s, "r4") == 0 ||
1464 strcmp (s, "r5") == 0 ||
1465 strcmp (s, "r6") == 0 ||
1466 strcmp (s, "r7") == 0)
1468 emitcode ("mov", "%s,%s",
1469 aop->aopu.aop_reg[offset]->dname, s);
1473 emitcode ("mov", "%s,%s",
1474 aop->aopu.aop_reg[offset]->name, s);
1480 emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1486 if (aop->type == AOP_DPTR2)
1494 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1495 "aopPut writting to code space");
1499 while (offset > aop->coff)
1502 emitcode ("inc", "dptr");
1505 while (offset < aop->coff)
1508 emitcode ("lcall", "__decdptr");
1513 /* if not in accumulater */
1516 emitcode ("movx", "@dptr,a");
1518 if (aop->type == AOP_DPTR2)
1526 while (offset > aop->coff)
1529 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1531 while (offset < aop->coff)
1534 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1541 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1547 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1549 else if (strcmp (s, "r0") == 0 ||
1550 strcmp (s, "r1") == 0 ||
1551 strcmp (s, "r2") == 0 ||
1552 strcmp (s, "r3") == 0 ||
1553 strcmp (s, "r4") == 0 ||
1554 strcmp (s, "r5") == 0 ||
1555 strcmp (s, "r6") == 0 ||
1556 strcmp (s, "r7") == 0)
1559 SNPRINTF(buff, sizeof(buff),
1561 emitcode ("mov", "@%s,%s",
1562 aop->aopu.aop_ptr->name, buff);
1566 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1571 if (strcmp (s, "a") == 0)
1572 emitcode ("push", "acc");
1576 emitcode ("push", "acc");
1578 emitcode ("push", s);
1584 /* if bit variable */
1585 if (!aop->aopu.aop_dir)
1587 emitcode ("clr", "a");
1588 emitcode ("rlc", "a");
1593 emitcode ("clr", "%s", aop->aopu.aop_dir);
1595 emitcode ("setb", "%s", aop->aopu.aop_dir);
1596 else if (!strcmp (s, "c"))
1597 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1600 if (strcmp (s, "a"))
1605 /* set C, if a >= 1 */
1606 emitcode ("add", "a,#!constbyte",0xff);
1607 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1615 if (strcmp (aop->aopu.aop_str[offset], s))
1616 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1621 if (!offset && (strcmp (s, "acc") == 0))
1624 if (strcmp (aop->aopu.aop_str[offset], s))
1625 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1629 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1630 "aopPut got unsupported aop->type");
1637 /*--------------------------------------------------------------------*/
1638 /* reAdjustPreg - points a register back to where it should (coff==0) */
1639 /*--------------------------------------------------------------------*/
1641 reAdjustPreg (asmop * aop)
1643 if ((aop->coff==0) || (aop->size <= 1)) {
1652 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1656 if (aop->type == AOP_DPTR2)
1663 emitcode ("lcall", "__decdptr");
1666 if (aop->type == AOP_DPTR2)
1676 #define AOP(op) op->aop
1677 #define AOP_TYPE(op) AOP(op)->type
1678 #define AOP_SIZE(op) AOP(op)->size
1679 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1680 AOP_TYPE(x) == AOP_R0))
1682 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1683 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1686 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1687 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1688 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1689 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1690 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1691 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1693 // The following two macros can be used even if the aop has not yet been aopOp'd.
1694 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1695 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1697 /* Workaround for DS80C390 bug: div ab may return bogus results
1698 * if A is accessed in instruction immediately before the div.
1700 * Will be fixed in B4 rev of processor, Dallas claims.
1703 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1704 if (!AOP_NEEDSACC(RIGHT)) \
1706 /* We can load A first, then B, since \
1707 * B (the RIGHT operand) won't clobber A, \
1708 * thus avoiding touching A right before the div. \
1710 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1711 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1713 L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1718 /* Just stuff in a nop after loading A. */ \
1719 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1720 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1722 emitcode("nop", "; workaround for DS80C390 div bug."); \
1726 /*-----------------------------------------------------------------*/
1727 /* opIsGptr: returns non-zero if the passed operand is */
1728 /* a generic pointer type. */
1729 /*-----------------------------------------------------------------*/
1731 opIsGptr (operand * op)
1733 sym_link *type = operandType (op);
1735 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1742 /*-----------------------------------------------------------------*/
1743 /* getDataSize - get the operand data size */
1744 /*-----------------------------------------------------------------*/
1746 getDataSize (operand * op)
1749 size = AOP_SIZE (op);
1750 if (size == GPTRSIZE)
1752 sym_link *type = operandType (op);
1753 if (IS_GENPTR (type))
1755 /* generic pointer; arithmetic operations
1756 * should ignore the high byte (pointer type).
1764 /*-----------------------------------------------------------------*/
1765 /* outAcc - output Acc */
1766 /*-----------------------------------------------------------------*/
1768 outAcc (operand * result)
1771 size = getDataSize (result);
1774 aopPut (AOP (result), "a", 0);
1777 /* unsigned or positive */
1780 aopPut (AOP (result), zero, offset++);
1785 /*-----------------------------------------------------------------*/
1786 /* outBitC - output a bit C */
1787 /*-----------------------------------------------------------------*/
1789 outBitC (operand * result)
1791 /* if the result is bit */
1792 if (AOP_TYPE (result) == AOP_CRY)
1794 aopPut (AOP (result), "c", 0);
1798 emitcode ("clr", "a");
1799 emitcode ("rlc", "a");
1804 /*-----------------------------------------------------------------*/
1805 /* toBoolean - emit code for orl a,operator(sizeop) */
1806 /*-----------------------------------------------------------------*/
1808 toBoolean (operand * oper)
1810 int size = AOP_SIZE (oper) - 1;
1814 /* The generic part of a generic pointer should
1815 * not participate in it's truth value.
1817 * i.e. 0x10000000 is zero.
1819 if (opIsGptr (oper))
1821 D (emitcode (";", "toBoolean: generic ptr special case."););
1825 _startLazyDPSEvaluation ();
1826 if (AOP_NEEDSACC (oper) && size)
1831 emitcode ("push", "b");
1833 MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1837 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1844 emitcode ("orl", "b,%s",
1845 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1849 emitcode ("orl", "a,%s",
1850 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1853 _endLazyDPSEvaluation ();
1857 emitcode ("mov", "a,b");
1860 emitcode ("pop", "b");
1867 /*-----------------------------------------------------------------*/
1868 /* genNot - generate code for ! operation */
1869 /*-----------------------------------------------------------------*/
1875 D (emitcode (";", "genNot "););
1877 /* assign asmOps to operand & result */
1878 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1879 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1881 /* if in bit space then a special case */
1882 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1884 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1885 emitcode ("cpl", "c");
1886 outBitC (IC_RESULT (ic));
1890 toBoolean (IC_LEFT (ic));
1892 tlbl = newiTempLabel (NULL);
1893 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1894 emitcode ("", "!tlabeldef", tlbl->key + 100);
1895 outBitC (IC_RESULT (ic));
1898 /* release the aops */
1899 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1900 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1904 /*-----------------------------------------------------------------*/
1905 /* genCpl - generate code for complement */
1906 /*-----------------------------------------------------------------*/
1913 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1915 D(emitcode (";", "genCpl"));
1917 /* assign asmOps to operand & result */
1918 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1919 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1921 /* special case if in bit space */
1922 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1926 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1927 (SPEC_USIGN (letype) && IS_CHAR (letype)))
1929 /* promotion rules are responsible for this strange result:
1930 bit -> int -> ~int -> bit
1931 uchar -> int -> ~int -> bit
1933 werror(W_COMPLEMENT);
1934 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1937 tlbl=newiTempLabel(NULL);
1938 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, FALSE, NULL);
1939 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC ||
1940 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1941 IS_AOP_PREG (IC_LEFT (ic)))
1943 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1948 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1950 emitcode ("", "%05d$:", tlbl->key+100);
1951 outBitC (IC_RESULT(ic));
1955 size = AOP_SIZE (IC_RESULT (ic));
1956 _startLazyDPSEvaluation ();
1959 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1960 emitcode ("cpl", "a");
1961 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1963 _endLazyDPSEvaluation ();
1967 /* release the aops */
1968 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1969 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1972 /*-----------------------------------------------------------------*/
1973 /* genUminusFloat - unary minus for floating points */
1974 /*-----------------------------------------------------------------*/
1976 genUminusFloat (operand * op, operand * result)
1978 int size, offset = 0;
1980 D(emitcode (";", "genUminusFloat"););
1982 /* for this we just copy and then flip the bit */
1984 _startLazyDPSEvaluation ();
1985 size = AOP_SIZE (op) - 1;
1989 aopPut (AOP (result),
1990 aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1995 MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1997 emitcode ("cpl", "acc.7");
1998 aopPut (AOP (result), "a", offset);
1999 _endLazyDPSEvaluation ();
2002 /*-----------------------------------------------------------------*/
2003 /* genUminus - unary minus code generation */
2004 /*-----------------------------------------------------------------*/
2006 genUminus (iCode * ic)
2011 D (emitcode (";", "genUminus "););
2014 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2015 aopOp (IC_RESULT (ic), ic, TRUE, (AOP_TYPE(IC_LEFT (ic)) == AOP_DPTR));
2017 /* if both in bit space then special
2019 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2020 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2023 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2024 emitcode ("cpl", "c");
2025 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2029 optype = operandType (IC_LEFT (ic));
2031 /* if float then do float stuff */
2032 if (IS_FLOAT (optype))
2034 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2038 /* otherwise subtract from zero */
2039 size = AOP_SIZE (IC_LEFT (ic));
2041 _startLazyDPSEvaluation ();
2044 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
2045 if (!strcmp (l, "a"))
2049 emitcode ("cpl", "a");
2050 emitcode ("addc", "a,#0");
2056 emitcode ("clr", "a");
2057 emitcode ("subb", "a,%s", l);
2059 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2061 _endLazyDPSEvaluation ();
2063 /* if any remaining bytes in the result */
2064 /* we just need to propagate the sign */
2065 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
2067 emitcode ("rlc", "a");
2068 emitcode ("subb", "a,acc");
2070 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2074 /* release the aops */
2075 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2076 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2079 /*-----------------------------------------------------------------*/
2080 /* savermask - saves registers in the mask */
2081 /*-----------------------------------------------------------------*/
2082 static void savermask(bitVect *rs_mask)
2085 if (options.useXstack) {
2086 if (bitVectBitValue (rs_mask, R0_IDX))
2087 emitcode ("mov", "b,r0");
2088 emitcode ("mov", "r0,%s", spname);
2089 for (i = 0; i < ds390_nRegs; i++) {
2090 if (bitVectBitValue (rs_mask, i)) {
2092 emitcode ("mov", "a,b");
2094 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2095 emitcode ("movx", "@r0,a");
2096 emitcode ("inc", "r0");
2099 emitcode ("mov", "%s,r0", spname);
2100 if (bitVectBitValue (rs_mask, R0_IDX))
2101 emitcode ("mov", "r0,b");
2103 for (i = 0; i < ds390_nRegs; i++) {
2104 if (bitVectBitValue (rs_mask, i))
2105 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2110 /*-----------------------------------------------------------------*/
2111 /* saveRegisters - will look for a call and save the registers */
2112 /*-----------------------------------------------------------------*/
2114 saveRegisters (iCode * lic)
2120 for (ic = lic; ic; ic = ic->next)
2121 if (ic->op == CALL || ic->op == PCALL)
2126 fprintf (stderr, "found parameter push with no function call\n");
2130 /* if the registers have been saved already then
2133 || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2136 /* special case if DPTR alive across a function call then must save it
2137 even though callee saves */
2138 if (IS_SYMOP(IC_LEFT(ic)) &&
2139 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2141 rsave = newBitVect(ic->rMask->size);
2142 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2143 if (bitVectBitValue(ic->rMask,i))
2144 rsave = bitVectSetBit(rsave,i);
2146 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2148 /* safe the registers in use at this time but skip the
2149 ones for the result */
2150 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2151 ds390_rUmaskForOp (IC_RESULT(ic)));
2157 /*-----------------------------------------------------------------*/
2158 /* usavermask - restore registers with mask */
2159 /*-----------------------------------------------------------------*/
2160 static void unsavermask(bitVect *rs_mask)
2163 if (options.useXstack) {
2164 emitcode ("mov", "r0,%s", spname);
2165 for (i = ds390_nRegs; i >= 0; i--) {
2166 if (bitVectBitValue (rs_mask, i)) {
2167 emitcode ("dec", "r0");
2168 emitcode ("movx", "a,@r0");
2170 emitcode ("mov", "b,a");
2172 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2175 emitcode ("mov", "%s,r0", spname);
2176 if (bitVectBitValue (rs_mask, R0_IDX))
2177 emitcode ("mov", "r0,b");
2179 for (i = ds390_nRegs; i >= 0; i--) {
2180 if (bitVectBitValue (rs_mask, i))
2181 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2186 /*-----------------------------------------------------------------*/
2187 /* unsaveRegisters - pop the pushed registers */
2188 /*-----------------------------------------------------------------*/
2190 unsaveRegisters (iCode * ic)
2194 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2196 rsave = newBitVect(ic->rMask->size);
2197 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2198 if (bitVectBitValue(ic->rMask,i))
2199 rsave = bitVectSetBit(rsave,i);
2201 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2203 /* restore the registers in use at this time but skip the
2204 ones for the result */
2205 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2206 ds390_rUmaskForOp (IC_RESULT(ic)));
2212 /*-----------------------------------------------------------------*/
2214 /*-----------------------------------------------------------------*/
2216 pushSide (operand * oper, int size)
2219 _startLazyDPSEvaluation ();
2222 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2223 if (AOP_TYPE (oper) != AOP_REG &&
2224 AOP_TYPE (oper) != AOP_DIR &&
2227 emitcode ("mov", "a,%s", l);
2228 emitcode ("push", "acc");
2231 emitcode ("push", "%s", l);
2233 _endLazyDPSEvaluation ();
2236 /*-----------------------------------------------------------------*/
2237 /* assignResultValue - */
2238 /*-----------------------------------------------------------------*/
2240 assignResultValue (operand * oper)
2243 int size = AOP_SIZE (oper);
2244 bool pushedAcc = FALSE;
2246 if (size == fReturnSizeDS390)
2248 /* I don't think this case can ever happen... */
2249 /* ACC is the last part of this. If writing the result
2250 * uses AC, we must preserve it.
2252 if (AOP_NEEDSACC(oper))
2254 emitcode(";", "assignResultValue special case for ACC.");
2255 emitcode("push", "acc");
2262 _startLazyDPSEvaluation ();
2265 aopPut (AOP (oper), fReturn[offset], offset);
2268 _endLazyDPSEvaluation ();
2272 emitcode("pop", "acc");
2273 aopPut(AOP(oper), "a", offset);
2278 /*-----------------------------------------------------------------*/
2279 /* genXpush - pushes onto the external stack */
2280 /*-----------------------------------------------------------------*/
2282 genXpush (iCode * ic)
2284 asmop *aop = newAsmop (0);
2286 int size, offset = 0;
2288 D (emitcode (";", "genXpush ");
2291 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2292 r = getFreePtr (ic, &aop, FALSE);
2295 emitcode ("mov", "%s,_spx", r->name);
2297 size = AOP_SIZE (IC_LEFT (ic));
2298 _startLazyDPSEvaluation ();
2302 MOVA (aopGet (AOP (IC_LEFT (ic)),
2303 offset++, FALSE, FALSE, NULL));
2304 emitcode ("movx", "@%s,a", r->name);
2305 emitcode ("inc", "%s", r->name);
2308 _endLazyDPSEvaluation ();
2311 emitcode ("mov", "_spx,%s", r->name);
2313 freeAsmop (NULL, aop, ic, TRUE);
2314 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2317 /*-----------------------------------------------------------------*/
2318 /* genIpush - generate code for pushing this gets a little complex */
2319 /*-----------------------------------------------------------------*/
2321 genIpush (iCode * ic)
2323 int size, offset = 0;
2326 D (emitcode (";", "genIpush ");
2329 /* if this is not a parm push : ie. it is spill push
2330 and spill push is always done on the local stack */
2334 /* and the item is spilt then do nothing */
2335 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2338 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2339 size = AOP_SIZE (IC_LEFT (ic));
2340 /* push it on the stack */
2341 _startLazyDPSEvaluation ();
2344 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2350 emitcode ("push", "%s", l);
2352 _endLazyDPSEvaluation ();
2356 /* this is a paramter push: in this case we call
2357 the routine to find the call and save those
2358 registers that need to be saved */
2361 /* if use external stack then call the external
2362 stack pushing routine */
2363 if (options.useXstack)
2369 /* then do the push */
2370 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2372 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2373 size = AOP_SIZE (IC_LEFT (ic));
2375 _startLazyDPSEvaluation ();
2378 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2379 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2380 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2383 emitcode ("mov", "a,%s", l);
2384 emitcode ("push", "acc");
2388 emitcode ("push", "%s", l);
2391 _endLazyDPSEvaluation ();
2393 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2396 /*-----------------------------------------------------------------*/
2397 /* genIpop - recover the registers: can happen only for spilling */
2398 /*-----------------------------------------------------------------*/
2400 genIpop (iCode * ic)
2404 D (emitcode (";", "genIpop ");
2408 /* if the temp was not pushed then */
2409 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2412 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2413 size = AOP_SIZE (IC_LEFT (ic));
2414 offset = (size - 1);
2415 _startLazyDPSEvaluation ();
2418 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2419 FALSE, TRUE, NULL));
2421 _endLazyDPSEvaluation ();
2423 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2426 /*-----------------------------------------------------------------*/
2427 /* unsaveRBank - restores the resgister bank from stack */
2428 /*-----------------------------------------------------------------*/
2430 unsaveRBank (int bank, iCode * ic, bool popPsw)
2436 if (options.useXstack)
2440 /* Assume r0 is available for use. */
2441 r = ds390_regWithIdx (R0_IDX);;
2446 r = getFreePtr (ic, &aop, FALSE);
2448 emitcode ("mov", "%s,_spx", r->name);
2453 if (options.useXstack)
2455 emitcode ("movx", "a,@%s", r->name);
2456 emitcode ("mov", "psw,a");
2457 emitcode ("dec", "%s", r->name);
2461 emitcode ("pop", "psw");
2465 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2467 if (options.useXstack)
2469 emitcode ("movx", "a,@%s", r->name);
2470 emitcode ("mov", "(%s+%d),a",
2471 regs390[i].base, 8 * bank + regs390[i].offset);
2472 emitcode ("dec", "%s", r->name);
2476 emitcode ("pop", "(%s+%d)",
2477 regs390[i].base, 8 * bank + regs390[i].offset);
2480 if (options.useXstack)
2482 emitcode ("mov", "_spx,%s", r->name);
2487 freeAsmop (NULL, aop, ic, TRUE);
2491 /*-----------------------------------------------------------------*/
2492 /* saveRBank - saves an entire register bank on the stack */
2493 /*-----------------------------------------------------------------*/
2495 saveRBank (int bank, iCode * ic, bool pushPsw)
2501 if (options.useXstack)
2505 /* Assume r0 is available for use. */
2506 r = ds390_regWithIdx (R0_IDX);;
2511 r = getFreePtr (ic, &aop, FALSE);
2513 emitcode ("mov", "%s,_spx", r->name);
2516 for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2518 if (options.useXstack)
2520 emitcode ("inc", "%s", r->name);
2521 emitcode ("mov", "a,(%s+%d)",
2522 regs390[i].base, 8 * bank + regs390[i].offset);
2523 emitcode ("movx", "@%s,a", r->name);
2526 emitcode ("push", "(%s+%d)",
2527 regs390[i].base, 8 * bank + regs390[i].offset);
2532 if (options.useXstack)
2534 emitcode ("mov", "a,psw");
2535 emitcode ("movx", "@%s,a", r->name);
2536 emitcode ("inc", "%s", r->name);
2537 emitcode ("mov", "_spx,%s", r->name);
2541 emitcode ("push", "psw");
2544 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2549 freeAsmop (NULL, aop, ic, TRUE);
2558 /*-----------------------------------------------------------------*/
2559 /* genSend - gen code for SEND */
2560 /*-----------------------------------------------------------------*/
2561 static void genSend(set *sendSet)
2565 static int rb1_count = 0;
2567 for (sic = setFirstItem (sendSet); sic;
2568 sic = setNextItem (sendSet)) {
2569 int size, offset = 0;
2571 size=getSize(operandType(IC_LEFT(sic)));
2572 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2573 if (sendCount == 0) { /* first parameter */
2574 // we know that dpl(hxb) is the result, so
2576 _startLazyDPSEvaluation ();
2578 aopOp (IC_LEFT (sic), sic, FALSE,
2579 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2581 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2584 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2585 FALSE, FALSE, NULL);
2586 if (strcmp (l, fReturn[offset])) {
2587 emitcode ("mov", "%s,%s",
2593 _endLazyDPSEvaluation ();
2594 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2596 } else { /* if more parameter in registers */
2597 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2599 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2600 FALSE, FALSE, NULL));
2602 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2609 adjustEsp(const char *reg)
2611 emitcode ("anl","%s,#3", reg);
2612 if (TARGET_IS_DS400)
2614 emitcode ("orl","%s,#!constbyte",
2616 (options.stack_loc >> 8) & 0xff);
2620 /*-----------------------------------------------------------------*/
2621 /* genCall - generates a call statement */
2622 /*-----------------------------------------------------------------*/
2624 genCall (iCode * ic)
2627 bool restoreBank = FALSE;
2628 bool swapBanks = FALSE;
2630 D (emitcode (";", "genCall "););
2632 /* if we are calling a not _naked function that is not using
2633 the same register bank then we need to save the
2634 destination registers on the stack */
2635 dtype = operandType (IC_LEFT (ic));
2636 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2637 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2638 IFFUNC_ISISR (currFunc->type))
2642 /* This is unexpected; the bank should have been saved in
2645 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2651 /* if caller saves & we have not saved then */
2655 /* if send set is not empty then assign */
2656 /* We've saved all the registers we care about;
2657 * therefore, we may clobber any register not used
2658 * in the calling convention (i.e. anything not in
2663 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2664 genSend(reverseSet(_G.sendSet));
2666 genSend(_G.sendSet);
2673 emitcode ("mov", "psw,#!constbyte",
2674 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2678 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2679 OP_SYMBOL (IC_LEFT (ic))->rname :
2680 OP_SYMBOL (IC_LEFT (ic))->name));
2684 emitcode ("mov", "psw,#!constbyte",
2685 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2688 /* if we need assign a result value */
2689 if ((IS_ITEMP (IC_RESULT (ic)) &&
2690 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2691 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2692 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2693 IS_TRUE_SYMOP (IC_RESULT (ic)))
2695 if (isOperandInFarSpace (IC_RESULT (ic))
2696 && getSize (operandType (IC_RESULT (ic))) <= 2)
2698 int size = getSize (operandType (IC_RESULT (ic)));
2700 /* Special case for 1 or 2 byte return in far space. */
2704 emitcode ("mov", "b,%s", fReturn[1]);
2709 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2715 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2719 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2721 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2726 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2729 assignResultValue (IC_RESULT (ic));
2731 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2735 /* adjust the stack for parameters if
2737 if (ic->parmBytes) {
2739 if (options.stack10bit) {
2740 if (ic->parmBytes <= 10) {
2741 emitcode(";","stack adjustment for parms");
2742 for (i=0; i < ic->parmBytes ; i++) {
2743 emitcode("pop","acc");
2747 emitcode ("clr","c");
2748 emitcode ("mov","a,sp");
2749 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2750 emitcode ("mov","sp,a");
2751 emitcode ("mov","a,esp");
2753 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2754 emitcode ("mov","esp,a");
2758 if (ic->parmBytes > 3) {
2759 emitcode ("mov", "a,%s", spname);
2760 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2761 emitcode ("mov", "%s,a", spname);
2763 for (i = 0; i < ic->parmBytes; i++)
2764 emitcode ("dec", "%s", spname);
2768 /* if we hade saved some registers then unsave them */
2770 unsaveRegisters (ic);
2772 /* if register bank was saved then pop them */
2774 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2777 /*-----------------------------------------------------------------*/
2778 /* genPcall - generates a call by pointer statement */
2779 /*-----------------------------------------------------------------*/
2781 genPcall (iCode * ic)
2784 symbol *rlbl = newiTempLabel (NULL);
2785 bool restoreBank=FALSE;
2787 D (emitcode (";", "genPcall ");
2791 /* if caller saves & we have not saved then */
2795 /* if we are calling a function that is not using
2796 the same register bank then we need to save the
2797 destination registers on the stack */
2798 dtype = operandType (IC_LEFT (ic));
2799 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2800 IFFUNC_ISISR (currFunc->type) &&
2801 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2802 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2806 /* push the return address on to the stack */
2807 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2808 emitcode ("push", "acc");
2809 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2810 emitcode ("push", "acc");
2812 if (options.model == MODEL_FLAT24)
2814 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2815 emitcode ("push", "acc");
2818 /* now push the calling address */
2819 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2821 pushSide (IC_LEFT (ic), FPTRSIZE);
2823 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2825 /* if send set is not empty the assign */
2828 genSend(reverseSet(_G.sendSet));
2832 emitcode ("ret", "");
2833 emitcode ("", "!tlabeldef", (rlbl->key + 100));
2836 /* if we need assign a result value */
2837 if ((IS_ITEMP (IC_RESULT (ic)) &&
2838 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2839 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2840 IS_TRUE_SYMOP (IC_RESULT (ic)))
2844 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2847 assignResultValue (IC_RESULT (ic));
2849 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2852 /* adjust the stack for parameters if
2857 if (options.stack10bit) {
2858 if (ic->parmBytes <= 10) {
2859 emitcode(";","stack adjustment for parms");
2860 for (i=0; i < ic->parmBytes ; i++) {
2861 emitcode("pop","acc");
2865 emitcode ("clr","c");
2866 emitcode ("mov","a,sp");
2867 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2868 emitcode ("mov","sp,a");
2869 emitcode ("mov","a,esp");
2871 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2872 emitcode ("mov","esp,a");
2876 if (ic->parmBytes > 3) {
2877 emitcode ("mov", "a,%s", spname);
2878 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2879 emitcode ("mov", "%s,a", spname);
2882 for (i = 0; i < ic->parmBytes; i++)
2883 emitcode ("dec", "%s", spname);
2887 /* if register bank was saved then unsave them */
2889 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2891 /* if we hade saved some registers then
2894 unsaveRegisters (ic);
2898 /*-----------------------------------------------------------------*/
2899 /* resultRemat - result is rematerializable */
2900 /*-----------------------------------------------------------------*/
2902 resultRemat (iCode * ic)
2904 if (SKIP_IC (ic) || ic->op == IFX)
2907 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2909 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2910 if (sym->remat && !POINTER_SET (ic))
2917 #if defined(__BORLANDC__) || defined(_MSC_VER)
2918 #define STRCASECMP stricmp
2920 #define STRCASECMP strcasecmp
2923 /*-----------------------------------------------------------------*/
2924 /* inExcludeList - return 1 if the string is in exclude Reg list */
2925 /*-----------------------------------------------------------------*/
2927 regsCmp(void *p1, void *p2)
2929 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2933 inExcludeList (char *s)
2935 const char *p = setFirstItem(options.excludeRegsSet);
2937 if (p == NULL || STRCASECMP(p, "none") == 0)
2941 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2944 /*-----------------------------------------------------------------*/
2945 /* genFunction - generated code for function entry */
2946 /*-----------------------------------------------------------------*/
2948 genFunction (iCode * ic)
2952 bool switchedPSW = FALSE;
2954 D (emitcode (";", "genFunction "););
2957 /* create the function header */
2958 emitcode (";", "-----------------------------------------");
2959 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2960 emitcode (";", "-----------------------------------------");
2962 emitcode ("", "%s:", sym->rname);
2963 ftype = operandType (IC_LEFT (ic));
2965 if (IFFUNC_ISNAKED(ftype))
2967 emitcode(";", "naked function: no prologue.");
2971 if (options.stack_probe)
2972 emitcode ("lcall","__stack_probe");
2974 /* here we need to generate the equates for the
2975 register bank if required */
2976 if (FUNC_REGBANK (ftype) != rbank)
2980 rbank = FUNC_REGBANK (ftype);
2981 for (i = 0; i < ds390_nRegs; i++)
2983 if (regs390[i].print) {
2984 if (strcmp (regs390[i].base, "0") == 0)
2985 emitcode ("", "%s !equ !constbyte",
2987 8 * rbank + regs390[i].offset);
2989 emitcode ("", "%s !equ %s + !constbyte",
2992 8 * rbank + regs390[i].offset);
2997 /* if this is an interrupt service routine then
2998 save acc, b, dpl, dph */
2999 if (IFFUNC_ISISR (sym->type))
3001 if (!inExcludeList ("acc"))
3002 emitcode ("push", "acc");
3003 if (!inExcludeList ("b"))
3004 emitcode ("push", "b");
3005 if (!inExcludeList ("dpl"))
3006 emitcode ("push", "dpl");
3007 if (!inExcludeList ("dph"))
3008 emitcode ("push", "dph");
3009 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3011 emitcode ("push", "dpx");
3012 /* Make sure we're using standard DPTR */
3013 emitcode ("push", "dps");
3014 emitcode ("mov", "dps,#0");
3015 if (options.stack10bit)
3017 /* This ISR could conceivably use DPTR2. Better save it. */
3018 emitcode ("push", "dpl1");
3019 emitcode ("push", "dph1");
3020 emitcode ("push", "dpx1");
3021 emitcode ("push", DP2_RESULT_REG);
3024 /* if this isr has no bank i.e. is going to
3025 run with bank 0 , then we need to save more
3027 if (!FUNC_REGBANK (sym->type))
3031 /* if this function does not call any other
3032 function then we can be economical and
3033 save only those registers that are used */
3034 if (!IFFUNC_HASFCALL(sym->type))
3037 /* if any registers used */
3040 /* save the registers used */
3041 for (i = 0; i < sym->regsUsed->size; i++)
3043 if (bitVectBitValue (sym->regsUsed, i))
3044 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3050 /* this function has a function call cannot
3051 determines register usage so we will have to push the
3053 saveRBank (0, ic, FALSE);
3054 if (options.parms_in_bank1) {
3055 for (i=0; i < 8 ; i++ ) {
3056 emitcode ("push","%s",rb1regs[i]);
3063 /* This ISR uses a non-zero bank.
3065 * We assume that the bank is available for our
3068 * However, if this ISR calls a function which uses some
3069 * other bank, we must save that bank entirely.
3071 unsigned long banksToSave = 0;
3073 if (IFFUNC_HASFCALL(sym->type))
3076 #define MAX_REGISTER_BANKS 4
3081 for (i = ic; i; i = i->next)
3083 if (i->op == ENDFUNCTION)
3085 /* we got to the end OK. */
3093 dtype = operandType (IC_LEFT(i));
3095 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3097 /* Mark this bank for saving. */
3098 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3100 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3104 banksToSave |= (1 << FUNC_REGBANK(dtype));
3107 /* And note that we don't need to do it in
3115 /* This is a mess; we have no idea what
3116 * register bank the called function might
3119 * The only thing I can think of to do is
3120 * throw a warning and hope.
3122 werror(W_FUNCPTR_IN_USING_ISR);
3126 if (banksToSave && options.useXstack)
3128 /* Since we aren't passing it an ic,
3129 * saveRBank will assume r0 is available to abuse.
3131 * So switch to our (trashable) bank now, so
3132 * the caller's R0 isn't trashed.
3134 emitcode ("push", "psw");
3135 emitcode ("mov", "psw,#!constbyte",
3136 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3140 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3142 if (banksToSave & (1 << ix))
3144 saveRBank(ix, NULL, FALSE);
3148 // TODO: this needs a closer look
3149 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3154 /* if callee-save to be used for this function
3155 then save the registers being used in this function */
3156 if (IFFUNC_CALLEESAVES(sym->type))
3160 /* if any registers used */
3163 /* save the registers used */
3164 for (i = 0; i < sym->regsUsed->size; i++)
3166 if (bitVectBitValue (sym->regsUsed, i))
3168 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3176 /* set the register bank to the desired value */
3177 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3180 emitcode ("push", "psw");
3181 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3184 if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3185 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3186 if (options.stack10bit) {
3187 emitcode ("push","_bpx");
3188 emitcode ("push","_bpx+1");
3189 emitcode ("mov","_bpx,%s",spname);
3190 emitcode ("mov","_bpx+1,esp");
3191 adjustEsp("_bpx+1");
3193 if (options.useXstack) {
3194 emitcode ("mov", "r0,%s", spname);
3195 emitcode ("mov", "a,_bp");
3196 emitcode ("movx", "@r0,a");
3197 emitcode ("inc", "%s", spname);
3199 /* set up the stack */
3200 emitcode ("push", "_bp"); /* save the callers stack */
3202 emitcode ("mov", "_bp,%s", spname);
3206 /* adjust the stack for the function */
3209 if (options.stack10bit) {
3210 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3211 assert (sym->recvSize <= 4);
3212 if (sym->stack <= 8) {
3213 while (i--) emitcode ("push","acc");
3216 emitcode ("mov","a,sp");
3217 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3218 emitcode ("mov","sp,a");
3219 emitcode ("mov","a,esp");
3221 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3222 emitcode ("mov","esp,a");
3227 werror (W_STACK_OVERFLOW, sym->name);
3229 if (i > 3 && sym->recvSize < 4) {
3231 emitcode ("mov", "a,sp");
3232 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3233 emitcode ("mov", "sp,a");
3237 emitcode ("inc", "sp");
3244 emitcode ("mov", "a,_spx");
3245 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3246 emitcode ("mov", "_spx,a");
3249 /* if critical function then turn interrupts off */
3250 if (IFFUNC_ISCRITICAL (ftype))
3252 symbol *tlbl = newiTempLabel (NULL);
3253 emitcode ("setb", "c");
3254 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3255 emitcode ("clr", "c");
3256 emitcode ("", "%05d$:", (tlbl->key + 100));
3257 emitcode ("push", "psw"); /* save old ea via c in psw */
3262 /*-----------------------------------------------------------------*/
3263 /* genEndFunction - generates epilogue for functions */
3264 /*-----------------------------------------------------------------*/
3266 genEndFunction (iCode * ic)
3268 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3269 lineNode *lnp = lineCurr;
3271 bitVect *regsUsedPrologue;
3272 bitVect *regsUnneeded;
3275 D (emitcode (";", "genEndFunction "););
3277 if (IFFUNC_ISNAKED(sym->type))
3279 emitcode(";", "naked function: no epilogue.");
3280 if (options.debug && currFunc)
3281 debugFile->writeEndFunction (currFunc, ic, 0);
3285 if (IFFUNC_ISCRITICAL (sym->type))
3287 emitcode ("pop", "psw"); /* restore ea via c in psw */
3288 emitcode ("mov", "ea,c");
3291 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3292 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3294 if (options.stack10bit) {
3296 emitcode ("mov", "sp,_bpx", spname);
3297 emitcode ("mov", "esp,_bpx+1", spname);
3300 emitcode ("mov", "%s,_bp", spname);
3304 /* if use external stack but some variables were
3305 added to the local stack then decrement the
3307 if (options.useXstack && sym->stack) {
3308 emitcode ("mov", "a,sp");
3309 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3310 emitcode ("mov", "sp,a");
3314 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3315 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3317 if (options.useXstack) {
3318 emitcode ("mov", "r0,%s", spname);
3319 emitcode ("movx", "a,@r0");
3320 emitcode ("mov", "_bp,a");
3321 emitcode ("dec", "%s", spname);
3323 if (options.stack10bit) {
3324 emitcode ("pop", "_bpx+1");
3325 emitcode ("pop", "_bpx");
3327 emitcode ("pop", "_bp");
3332 /* restore the register bank */
3333 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3335 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3336 || !options.useXstack)
3338 /* Special case of ISR using non-zero bank with useXstack
3341 emitcode ("pop", "psw");
3345 if (IFFUNC_ISISR (sym->type))
3348 /* now we need to restore the registers */
3349 /* if this isr has no bank i.e. is going to
3350 run with bank 0 , then we need to save more
3352 if (!FUNC_REGBANK (sym->type))
3355 /* if this function does not call any other
3356 function then we can be economical and
3357 save only those registers that are used */
3358 if (!IFFUNC_HASFCALL(sym->type))
3361 /* if any registers used */
3364 /* save the registers used */
3365 for (i = sym->regsUsed->size; i >= 0; i--)
3367 if (bitVectBitValue (sym->regsUsed, i))
3368 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3374 /* this function has a function call cannot
3375 determines register usage so we will have to pop the
3377 if (options.parms_in_bank1) {
3378 for (i = 7 ; i >= 0 ; i-- ) {
3379 emitcode ("pop","%s",rb1regs[i]);
3382 unsaveRBank (0, ic, FALSE);
3387 /* This ISR uses a non-zero bank.
3389 * Restore any register banks saved by genFunction
3392 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3395 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3397 if (savedBanks & (1 << ix))
3399 unsaveRBank(ix, NULL, FALSE);
3403 if (options.useXstack)
3405 /* Restore bank AFTER calling unsaveRBank,
3406 * since it can trash r0.
3408 emitcode ("pop", "psw");
3412 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3414 if (options.stack10bit)
3416 emitcode ("pop", DP2_RESULT_REG);
3417 emitcode ("pop", "dpx1");
3418 emitcode ("pop", "dph1");
3419 emitcode ("pop", "dpl1");
3421 emitcode ("pop", "dps");
3422 emitcode ("pop", "dpx");
3424 if (!inExcludeList ("dph"))
3425 emitcode ("pop", "dph");
3426 if (!inExcludeList ("dpl"))
3427 emitcode ("pop", "dpl");
3428 if (!inExcludeList ("b"))
3429 emitcode ("pop", "b");
3430 if (!inExcludeList ("acc"))
3431 emitcode ("pop", "acc");
3433 /* if debug then send end of function */
3434 if (options.debug && currFunc) {
3435 debugFile->writeEndFunction (currFunc, ic, 1);
3438 emitcode ("reti", "");
3442 if (IFFUNC_CALLEESAVES(sym->type))
3446 /* if any registers used */
3449 /* save the registers used */
3450 for (i = sym->regsUsed->size; i >= 0; i--)
3452 if (bitVectBitValue (sym->regsUsed, i))
3453 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3458 /* if debug then send end of function */
3459 if (options.debug && currFunc)
3461 debugFile->writeEndFunction (currFunc, ic, 1);
3464 emitcode ("ret", "");
3467 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3470 /* If this was an interrupt handler using bank 0 that called another */
3471 /* function, then all registers must be saved; nothing to optimized. */
3472 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3473 && !FUNC_REGBANK(sym->type))
3476 /* There are no push/pops to optimize if not callee-saves or ISR */
3477 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3480 /* If there were stack parameters, we cannot optimize without also */
3481 /* fixing all of the stack offsets; this is too dificult to consider. */
3482 if (FUNC_HASSTACKPARM(sym->type))
3485 /* Compute the registers actually used */
3486 regsUsed = newBitVect (ds390_nRegs);
3487 regsUsedPrologue = newBitVect (ds390_nRegs);
3490 if (lnp->ic && lnp->ic->op == FUNCTION)
3491 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3493 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3495 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3496 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3503 if (bitVectBitValue (regsUsedPrologue, DPS_IDX)
3504 && !bitVectBitValue (regsUsed, DPS_IDX))
3506 bitVectUnSetBit (regsUsedPrologue, DPS_IDX);
3509 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3510 && !bitVectBitValue (regsUsed, CND_IDX))
3512 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3513 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3514 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3515 bitVectUnSetBit (regsUsed, CND_IDX);
3518 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3520 /* If this was an interrupt handler that called another function */
3521 /* function, then assume working registers may be modified by it. */
3522 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3524 regsUsed = bitVectSetBit (regsUsed, AP_IDX);
3525 regsUsed = bitVectSetBit (regsUsed, DPX1_IDX);
3526 regsUsed = bitVectSetBit (regsUsed, DPL1_IDX);
3527 regsUsed = bitVectSetBit (regsUsed, DPH1_IDX);
3528 regsUsed = bitVectSetBit (regsUsed, DPX_IDX);
3529 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3530 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3531 regsUsed = bitVectSetBit (regsUsed, DPS_IDX);
3532 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3533 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3534 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3537 /* Remove the unneeded push/pops */
3538 regsUnneeded = newBitVect (ds390_nRegs);
3541 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3543 if (!strncmp(lnp->line, "push", 4))
3545 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3546 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3548 connectLine (lnp->prev, lnp->next);
3549 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3552 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3554 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3555 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3557 connectLine (lnp->prev, lnp->next);
3558 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3565 for (idx = 0; idx < regsUnneeded->size; idx++)
3566 if (bitVectBitValue (regsUnneeded, idx))
3567 emitcode ("", ";\teliminated unneeded push/pop %s", ds390_regWithIdx (idx)->dname);
3569 freeBitVect (regsUnneeded);
3570 freeBitVect (regsUsed);
3571 freeBitVect (regsUsedPrologue);
3574 /*-----------------------------------------------------------------*/
3575 /* genJavaNativeRet - generate code for return JavaNative */
3576 /*-----------------------------------------------------------------*/
3577 static void genJavaNativeRet(iCode *ic)
3581 aopOp (IC_LEFT (ic), ic, FALSE,
3582 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3583 size = AOP_SIZE (IC_LEFT (ic));
3587 /* it is assigned to GPR0-R3 then push them */
3588 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3589 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3590 for (i = 0 ; i < size ; i++ ) {
3591 emitcode ("push","%s",
3592 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3594 for (i = (size-1) ; i >= 0 ; i--) {
3595 emitcode ("pop","a%s",javaRet[i]);
3598 for (i = 0 ; i < size ; i++)
3599 emitcode ("mov","%s,%s",javaRet[i],
3600 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3602 for (i = size ; i < 4 ; i++ )
3603 emitcode ("mov","%s,#0",javaRet[i]);
3607 /*-----------------------------------------------------------------*/
3608 /* genRet - generate code for return statement */
3609 /*-----------------------------------------------------------------*/
3613 int size, offset = 0, pushed = 0;
3615 D (emitcode (";", "genRet "););
3617 /* if we have no return value then
3618 just generate the "ret" */
3622 /* if this is a JavaNative function then return
3623 value in different register */
3624 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3625 genJavaNativeRet(ic);
3628 /* we have something to return then
3629 move the return value into place */
3630 aopOp (IC_LEFT (ic), ic, FALSE,
3631 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3632 size = AOP_SIZE (IC_LEFT (ic));
3634 _startLazyDPSEvaluation ();
3638 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3640 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3642 emitcode ("push", "%s", l);
3647 /* Since A is the last element of fReturn,
3648 * is is OK to clobber it in the aopGet.
3650 l = aopGet (AOP (IC_LEFT (ic)), offset,
3651 FALSE, FALSE, NULL);
3652 if (strcmp (fReturn[offset], l))
3653 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3656 _endLazyDPSEvaluation ();
3663 if (strcmp (fReturn[pushed], "a"))
3664 emitcode ("pop", fReturn[pushed]);
3666 emitcode ("pop", "acc");
3669 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3672 /* generate a jump to the return label
3673 if the next is not the return statement */
3674 if (!(ic->next && ic->next->op == LABEL &&
3675 IC_LABEL (ic->next) == returnLabel))
3677 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3681 /*-----------------------------------------------------------------*/
3682 /* genLabel - generates a label */
3683 /*-----------------------------------------------------------------*/
3685 genLabel (iCode * ic)
3687 /* special case never generate */
3688 if (IC_LABEL (ic) == entryLabel)
3691 D (emitcode (";", "genLabel ");
3694 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3697 /*-----------------------------------------------------------------*/
3698 /* genGoto - generates a ljmp */
3699 /*-----------------------------------------------------------------*/
3701 genGoto (iCode * ic)
3703 D (emitcode (";", "genGoto ");
3705 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3708 /*-----------------------------------------------------------------*/
3709 /* findLabelBackwards: walks back through the iCode chain looking */
3710 /* for the given label. Returns number of iCode instructions */
3711 /* between that label and given ic. */
3712 /* Returns zero if label not found. */
3713 /*-----------------------------------------------------------------*/
3715 findLabelBackwards (iCode * ic, int key)
3724 /* If we have any pushes or pops, we cannot predict the distance.
3725 I don't like this at all, this should be dealt with in the
3727 if (ic->op == IPUSH || ic->op == IPOP) {
3731 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3733 /* printf("findLabelBackwards = %d\n", count); */
3741 /*-----------------------------------------------------------------*/
3742 /* genPlusIncr :- does addition with increment if possible */
3743 /*-----------------------------------------------------------------*/
3745 genPlusIncr (iCode * ic)
3747 unsigned int icount;
3748 unsigned int size = getDataSize (IC_RESULT (ic));
3750 /* will try to generate an increment */
3751 /* if the right side is not a literal
3753 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3756 /* if the literal value of the right hand side
3757 is greater than 4 then it is not worth it */
3758 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3761 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3762 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3764 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3768 /* if increment 16 bits in register */
3770 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3771 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3772 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3781 /* If the next instruction is a goto and the goto target
3782 * is <= 5 instructions previous to this, we can generate
3783 * jumps straight to that target.
3785 if (ic->next && ic->next->op == GOTO
3786 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3789 D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3790 tlbl = IC_LABEL (ic->next);
3795 tlbl = newiTempLabel (NULL);
3799 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3800 emitcode ("inc", "%s", l);
3802 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3803 IS_AOP_PREG (IC_RESULT (ic)))
3805 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3809 emitcode ("clr", "a");
3810 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3813 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
3814 emitcode ("inc", "%s", l);
3817 if (!strcmp(l, "acc"))
3819 emitcode("jnz", "!tlabel", tlbl->key + 100);
3821 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3822 IS_AOP_PREG (IC_RESULT (ic)))
3824 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3828 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3831 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3832 emitcode ("inc", "%s", l);
3836 if (!strcmp(l, "acc"))
3838 emitcode("jnz", "!tlabel", tlbl->key + 100);
3840 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3841 IS_AOP_PREG (IC_RESULT (ic)))
3843 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3847 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3850 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3851 emitcode ("inc", "%s", l);
3856 emitcode ("", "!tlabeldef", tlbl->key + 100);
3861 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3862 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
3863 options.model == MODEL_FLAT24 )
3865 if (IC_RESULT(ic)->isGptr)
3867 emitcode ("mov","b,%s",aopGet(AOP (IC_LEFT (ic)), 3, FALSE, FALSE, NULL));
3871 emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3873 emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3875 emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3878 while (icount--) emitcode ("inc","dptr");
3882 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3883 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3885 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3886 while (icount--) emitcode ("inc","dptr");
3887 emitcode ("mov","dps,#0");
3891 /* if the sizes are greater than 1 then we cannot */
3892 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3893 AOP_SIZE (IC_LEFT (ic)) > 1)
3896 /* we can if the aops of the left & result match or
3897 if they are in registers and the registers are the
3900 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3901 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3902 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3907 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3908 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3909 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3914 _startLazyDPSEvaluation ();
3917 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3919 _endLazyDPSEvaluation ();
3928 /*-----------------------------------------------------------------*/
3929 /* outBitAcc - output a bit in acc */
3930 /*-----------------------------------------------------------------*/
3932 outBitAcc (operand * result)
3934 symbol *tlbl = newiTempLabel (NULL);
3935 /* if the result is a bit */
3936 if (AOP_TYPE (result) == AOP_CRY)
3938 aopPut (AOP (result), "a", 0);
3942 emitcode ("jz", "!tlabel", tlbl->key + 100);
3943 emitcode ("mov", "a,%s", one);
3944 emitcode ("", "!tlabeldef", tlbl->key + 100);
3949 /*-----------------------------------------------------------------*/
3950 /* genPlusBits - generates code for addition of two bits */
3951 /*-----------------------------------------------------------------*/
3953 genPlusBits (iCode * ic)
3955 D (emitcode (";", "genPlusBits "););
3957 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3959 symbol *lbl = newiTempLabel (NULL);
3960 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3961 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3962 emitcode ("cpl", "c");
3963 emitcode ("", "!tlabeldef", (lbl->key + 100));
3964 outBitC (IC_RESULT (ic));
3968 emitcode ("clr", "a");
3969 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3970 emitcode ("rlc", "a");
3971 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3972 emitcode ("addc", "a,#0");
3973 outAcc (IC_RESULT (ic));
3978 adjustArithmeticResult (iCode * ic)
3980 if (opIsGptr (IC_RESULT (ic)) &&
3981 opIsGptr (IC_LEFT (ic)) &&
3982 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3984 aopPut (AOP (IC_RESULT (ic)),
3985 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3989 if (opIsGptr (IC_RESULT (ic)) &&
3990 opIsGptr (IC_RIGHT (ic)) &&
3991 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3993 aopPut (AOP (IC_RESULT (ic)),
3994 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3998 if (opIsGptr (IC_RESULT (ic)) &&
3999 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4000 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4001 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4002 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4005 SNPRINTF (buff, sizeof(buff),
4006 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4007 aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
4011 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
4012 // generates the result if possible. If result is generated, returns TRUE; otherwise
4013 // returns false and caller must deal with fact that result isn't aopOp'd.
4014 bool aopOp3(iCode * ic)
4016 bool dp1InUse, dp2InUse;
4019 // First, generate the right opcode. DPTR may be used if neither left nor result are
4022 // D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
4023 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
4024 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
4025 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
4027 // D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
4028 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
4029 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
4030 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
4033 // Right uses DPTR unless left or result is an AOP_STR; however,
4034 // if right is an AOP_STR, it must use DPTR regardless.
4035 if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
4036 && !AOP_IS_STR(IC_RIGHT(ic)))
4045 aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
4047 // if the right used DPTR, left MUST use DPTR2.
4048 // if the right used DPTR2, left MUST use DPTR.
4049 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
4050 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
4051 // enabling us to assign DPTR to result.
4053 if (AOP_USESDPTR(IC_RIGHT(ic)))
4057 else if (AOP_USESDPTR2(IC_RIGHT(ic)))
4063 if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
4073 aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
4076 // We've op'd the left & right. So, if left or right are the same operand as result,
4077 // we know aopOp will succeed, and we can just do it & bail.
4078 if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))
4080 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4083 if (isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
4085 // D(emitcode(";", "aopOp3: (left | right) & result equal"););
4086 aopOp(IC_RESULT(ic),ic,TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4090 // Operands may be equivalent (but not equal) if they share a spill location. If
4091 // so, use the same DPTR or DPTR2.
4092 if (operandsEqu (IC_LEFT(ic), IC_RESULT(ic)))
4094 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4097 if (operandsEqu (IC_RIGHT(ic), IC_RESULT(ic)))
4099 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4103 // Note which dptrs are currently in use.
4104 dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
4105 dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
4107 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
4109 if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
4114 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
4115 if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
4120 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
4121 if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
4126 aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
4128 // Some sanity checking...
4129 if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
4132 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
4133 __FILE__, __LINE__, ic->filename, ic->lineno);
4134 emitcode(";", ">>> unexpected DPTR here.");
4137 if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
4140 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
4141 __FILE__, __LINE__, ic->filename, ic->lineno);
4142 emitcode(";", ">>> unexpected DPTR2 here.");
4148 // Macro to aopOp all three operands of an ic. If this cannot be done,
4149 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
4150 // will be set TRUE. The caller must then handle the case specially, noting
4151 // that the IC_RESULT operand is not aopOp'd.
4153 #define AOP_OP_3_NOFATAL(ic, rc) \
4154 do { rc = !aopOp3(ic); } while (0)
4156 // aopOp the left & right operands of an ic.
4157 #define AOP_OP_2(ic) \
4158 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
4159 aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
4161 // convienience macro.
4162 #define AOP_SET_LOCALS(ic) \
4163 left = IC_LEFT(ic); \
4164 right = IC_RIGHT(ic); \
4165 result = IC_RESULT(ic);
4168 // Given an integer value of pushedSize bytes on the stack,
4169 // adjust it to be resultSize bytes, either by discarding
4170 // the most significant bytes or by zero-padding.
4172 // On exit from this macro, pushedSize will have been adjusted to
4173 // equal resultSize, and ACC may be trashed.
4174 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
4175 /* If the pushed data is bigger than the result, \
4176 * simply discard unused bytes. Icky, but works. \
4178 while (pushedSize > resultSize) \
4180 D (emitcode (";", "discarding unused result byte."););\
4181 emitcode ("pop", "acc"); \
4184 if (pushedSize < resultSize) \
4186 emitcode ("clr", "a"); \
4187 /* Conversly, we haven't pushed enough here. \
4188 * just zero-pad, and all is well. \
4190 while (pushedSize < resultSize) \
4192 emitcode("push", "acc"); \
4196 assert(pushedSize == resultSize);
4198 /*-----------------------------------------------------------------*/
4199 /* genPlus - generates code for addition */
4200 /*-----------------------------------------------------------------*/
4202 genPlus (iCode * ic)
4204 int size, offset = 0;
4208 D (emitcode (";", "genPlus "););
4210 /* special cases :- */
4211 if ( AOP_IS_STR(IC_LEFT(ic)) &&
4212 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4213 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4214 size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4216 while (size--) emitcode ("inc","dptr");
4218 emitcode ("mov","a,dpl");
4219 emitcode ("add","a,#!constbyte",size & 0xff);
4220 emitcode ("mov","dpl,a");
4221 emitcode ("mov","a,dph");
4222 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4223 emitcode ("mov","dph,a");
4224 emitcode ("mov","a,dpx");
4225 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4226 emitcode ("mov","dpx,a");
4228 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4231 if ( IS_SYMOP(IC_LEFT(ic)) &&
4232 OP_SYMBOL(IC_LEFT(ic))->remat &&
4233 isOperandInFarSpace(IC_RIGHT(ic))) {
4234 operand *op = IC_RIGHT(ic);
4235 IC_RIGHT(ic) = IC_LEFT(ic);
4239 AOP_OP_3_NOFATAL (ic, pushResult);
4243 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4248 /* if literal, literal on the right or
4249 if left requires ACC or right is already
4251 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4252 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4253 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4255 operand *t = IC_RIGHT (ic);
4256 IC_RIGHT (ic) = IC_LEFT (ic);
4258 emitcode (";", "Swapped plus args.");
4261 /* if both left & right are in bit
4263 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4264 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4270 /* if left in bit space & right literal */
4271 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4272 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4274 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4275 /* if result in bit space */
4276 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4278 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4279 emitcode ("cpl", "c");
4280 outBitC (IC_RESULT (ic));
4284 size = getDataSize (IC_RESULT (ic));
4285 _startLazyDPSEvaluation ();
4288 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4289 emitcode ("addc", "a,#0");
4290 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4292 _endLazyDPSEvaluation ();
4297 /* if I can do an increment instead
4298 of add then GOOD for ME */
4299 if (genPlusIncr (ic) == TRUE)
4301 emitcode (";", "did genPlusIncr");
4306 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4308 _startLazyDPSEvaluation ();
4311 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4313 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4315 emitcode ("add", "a,%s",
4316 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4318 emitcode ("addc", "a,%s",
4319 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4323 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4325 /* right is going to use ACC or we would have taken the
4328 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4330 D(emitcode(";", "+ AOP_ACC special case."););
4331 emitcode("xch", "a, %s", DP2_RESULT_REG);
4333 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4336 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4339 emitcode("add", "a, %s", DP2_RESULT_REG);
4343 emitcode ("add", "a,%s",
4344 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4350 emitcode ("addc", "a,%s",
4351 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4357 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4361 emitcode ("push", "acc");
4365 _endLazyDPSEvaluation ();
4369 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4371 size = getDataSize (IC_LEFT (ic));
4372 rSize = getDataSize (IC_RESULT (ic));
4374 ADJUST_PUSHED_RESULT(size, rSize);
4376 _startLazyDPSEvaluation ();
4379 emitcode ("pop", "acc");
4380 aopPut (AOP (IC_RESULT (ic)), "a", size);
4382 _endLazyDPSEvaluation ();
4385 adjustArithmeticResult (ic);
4388 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4389 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4390 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4393 /*-----------------------------------------------------------------*/
4394 /* genMinusDec :- does subtraction with deccrement if possible */
4395 /*-----------------------------------------------------------------*/
4397 genMinusDec (iCode * ic)
4399 unsigned int icount;
4400 unsigned int size = getDataSize (IC_RESULT (ic));
4402 /* will try to generate an increment */
4403 /* if the right side is not a literal
4405 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4408 /* if the literal value of the right hand side
4409 is greater than 4 then it is not worth it */
4410 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4413 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4414 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4416 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4420 /* if decrement 16 bits in register */
4421 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4422 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4423 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4432 /* If the next instruction is a goto and the goto target
4433 * is <= 5 instructions previous to this, we can generate
4434 * jumps straight to that target.
4436 if (ic->next && ic->next->op == GOTO
4437 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4440 emitcode (";", "tail decrement optimized (range %d)", labelRange);
4441 tlbl = IC_LABEL (ic->next);
4446 tlbl = newiTempLabel (NULL);
4450 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4451 emitcode ("dec", "%s", l);
4453 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4454 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4455 IS_AOP_PREG (IC_RESULT (ic)))
4457 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4461 emitcode ("mov", "a,#!constbyte",0xff);
4462 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4464 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4465 emitcode ("dec", "%s", l);
4468 if (!strcmp(l, "acc"))
4470 emitcode("jnz", "!tlabel", tlbl->key + 100);
4472 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4473 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4474 IS_AOP_PREG (IC_RESULT (ic)))
4476 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4480 emitcode ("mov", "a,#!constbyte",0xff);
4481 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4483 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4484 emitcode ("dec", "%s", l);
4488 if (!strcmp(l, "acc"))
4490 emitcode("jnz", "!tlabel", tlbl->key + 100);
4492 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4493 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4494 IS_AOP_PREG (IC_RESULT (ic)))
4496 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4500 emitcode ("mov", "a,#!constbyte",0xff);
4501 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4503 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4504 emitcode ("dec", "%s", l);
4508 emitcode ("", "!tlabeldef", tlbl->key + 100);
4513 /* if the sizes are greater than 1 then we cannot */
4514 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4515 AOP_SIZE (IC_LEFT (ic)) > 1)
4518 /* we can if the aops of the left & result match or
4519 if they are in registers and the registers are the
4522 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4523 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4524 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4527 _startLazyDPSEvaluation ();
4530 emitcode ("dec", "%s",
4531 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4533 _endLazyDPSEvaluation ();
4541 /*-----------------------------------------------------------------*/
4542 /* addSign - complete with sign */
4543 /*-----------------------------------------------------------------*/
4545 addSign (operand * result, int offset, int sign)
4547 int size = (getDataSize (result) - offset);
4550 _startLazyDPSEvaluation();
4553 emitcode ("rlc", "a");
4554 emitcode ("subb", "a,acc");
4557 aopPut (AOP (result), "a", offset++);
4564 aopPut (AOP (result), zero, offset++);
4567 _endLazyDPSEvaluation();
4571 /*-----------------------------------------------------------------*/
4572 /* genMinusBits - generates code for subtraction of two bits */
4573 /*-----------------------------------------------------------------*/
4575 genMinusBits (iCode * ic)
4577 symbol *lbl = newiTempLabel (NULL);
4579 D (emitcode (";", "genMinusBits "););
4581 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4583 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4584 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4585 emitcode ("cpl", "c");
4586 emitcode ("", "!tlabeldef", (lbl->key + 100));
4587 outBitC (IC_RESULT (ic));
4591 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4592 emitcode ("subb", "a,acc");
4593 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4594 emitcode ("inc", "a");
4595 emitcode ("", "!tlabeldef", (lbl->key + 100));
4596 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4597 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4601 /*-----------------------------------------------------------------*/
4602 /* genMinus - generates code for subtraction */
4603 /*-----------------------------------------------------------------*/
4605 genMinus (iCode * ic)
4607 int size, offset = 0;
4612 D (emitcode (";", "genMinus "););
4614 AOP_OP_3_NOFATAL(ic, pushResult);
4618 /* special cases :- */
4619 /* if both left & right are in bit space */
4620 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4621 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4627 /* if I can do an decrement instead
4628 of subtract then GOOD for ME */
4629 if (genMinusDec (ic) == TRUE)
4634 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4636 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4642 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4647 /* if literal, add a,#-lit, else normal subb */
4648 _startLazyDPSEvaluation ();
4650 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4651 if (AOP_USESDPTR(IC_RIGHT(ic))) {
4652 emitcode ("mov","b,%s",
4653 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4654 MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4655 emitcode ("subb","a,b");
4657 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4658 emitcode ("subb", "a,%s",
4659 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE,
4663 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4664 /* first add without previous c */
4666 if (!size && lit==-1) {
4667 emitcode ("dec", "a");
4669 emitcode ("add", "a,#!constbyte",
4670 (unsigned int) (lit & 0x0FFL));
4673 emitcode ("addc", "a,#!constbyte",
4674 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4679 emitcode ("push", "acc");
4681 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4685 _endLazyDPSEvaluation ();
4689 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4691 size = getDataSize (IC_LEFT (ic));
4692 rSize = getDataSize (IC_RESULT (ic));
4694 ADJUST_PUSHED_RESULT(size, rSize);
4696 _startLazyDPSEvaluation ();
4699 emitcode ("pop", "acc");
4700 aopPut (AOP (IC_RESULT (ic)), "a", size);
4702 _endLazyDPSEvaluation ();
4705 adjustArithmeticResult (ic);
4708 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4709 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4710 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4714 /*-----------------------------------------------------------------*/
4715 /* genMultbits :- multiplication of bits */
4716 /*-----------------------------------------------------------------*/
4718 genMultbits (operand * left,
4723 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4724 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4725 aopOp(result, ic, TRUE, FALSE);
4730 /*-----------------------------------------------------------------*/
4731 /* genMultOneByte : 8*8=8/16 bit multiplication */
4732 /*-----------------------------------------------------------------*/
4734 genMultOneByte (operand * left,
4741 bool runtimeSign, compiletimeSign;
4742 bool lUnsigned, rUnsigned;
4745 /* (if two literals: the value is computed before) */
4746 /* if one literal, literal on the right */
4747 if (AOP_TYPE (left) == AOP_LIT)
4752 emitcode (";", "swapped left and right");
4755 /* (if two literals: the value is computed before) */
4756 /* if one literal, literal on the right */
4757 if (AOP_TYPE (left) == AOP_LIT)
4762 /* emitcode (";", "swapped left and right"); */
4764 /* if no literal, unsigned on the right: shorter code */
4765 if ( AOP_TYPE (right) != AOP_LIT
4766 && SPEC_USIGN (getSpec (operandType (left))))
4773 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4774 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4776 if ((lUnsigned && rUnsigned)
4777 /* sorry, I don't know how to get size
4778 without calling aopOp (result,...);
4779 see Feature Request */
4780 /* || size == 1 */ ) /* no, this is not a bug; with a 1 byte result there's
4781 no need to take care about the signedness! */
4783 /* just an unsigned 8 * 8 = 8 multiply
4785 /* emitcode (";","unsigned"); */
4786 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4787 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4788 emitcode ("mul", "ab");
4790 _G.accInUse++; _G.bInUse++;
4791 aopOp (result, ic, TRUE, FALSE);
4792 size = AOP_SIZE (result);
4794 if (size < 1 || size > 2)
4796 /* this should never happen */
4797 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4798 size, __FILE__, lineno);
4802 aopPut (AOP (result), "a", 0);
4803 _G.accInUse--; _G.bInUse--;
4805 aopPut (AOP (result), "b", 1);
4809 /* we have to do a signed multiply */
4810 /* emitcode (";", "signed"); */
4812 /* now sign adjust for both left & right */
4814 /* let's see what's needed: */
4815 /* apply negative sign during runtime */
4816 runtimeSign = FALSE;
4817 /* negative sign from literals */
4818 compiletimeSign = FALSE;
4822 if (AOP_TYPE(left) == AOP_LIT)
4824 /* signed literal */
4825 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4827 compiletimeSign = TRUE;
4830 /* signed but not literal */
4836 if (AOP_TYPE(right) == AOP_LIT)
4838 /* signed literal */
4839 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4841 compiletimeSign ^= TRUE;
4844 /* signed but not literal */
4848 /* initialize F0, which stores the runtime sign */
4851 if (compiletimeSign)
4852 emitcode ("setb", "F0"); /* set sign flag */
4854 emitcode ("clr", "F0"); /* reset sign flag */
4857 /* save the signs of the operands */
4858 if (AOP_TYPE(right) == AOP_LIT)
4860 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4862 if (!rUnsigned && val < 0)
4863 emitcode ("mov", "b,#!constbyte", -val);
4865 emitcode ("mov", "b,#!constbyte", (unsigned char) val);
4867 else /* ! literal */
4869 if (rUnsigned) /* emitcode (";", "signed"); */
4870 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4873 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4874 lbl = newiTempLabel (NULL);
4875 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
4876 emitcode ("cpl", "F0"); /* complement sign flag */
4877 emitcode ("cpl", "a"); /* 2's complement */
4878 emitcode ("inc", "a");
4879 emitcode ("", "!tlabeldef", lbl->key + 100);
4880 emitcode ("mov", "b,a");
4884 if (AOP_TYPE(left) == AOP_LIT)
4886 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4888 if (!lUnsigned && val < 0)
4889 emitcode ("mov", "a,#!constbyte", -val);
4891 emitcode ("mov", "a,#!constbyte", (unsigned char) val);
4893 else /* ! literal */
4895 if (lUnsigned) /* emitcode (";", "signed"); */
4897 emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4900 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4901 lbl = newiTempLabel (NULL);
4902 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
4903 emitcode ("cpl", "F0"); /* complement sign flag */
4904 emitcode ("cpl", "a"); /* 2's complement */
4905 emitcode ("inc", "a");
4906 emitcode ("", "!tlabeldef", lbl->key + 100);
4910 /* now the multiplication */
4911 emitcode ("mul", "ab");
4912 _G.accInUse++;_G.bInUse++;
4913 aopOp(result, ic, TRUE, FALSE);
4914 size = AOP_SIZE (result);
4916 if (size < 1 || size > 2)
4918 /* this should never happen */
4919 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4920 size, __FILE__, lineno);
4924 if (runtimeSign || compiletimeSign)
4926 lbl = newiTempLabel (NULL);
4928 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
4929 emitcode ("cpl", "a"); /* lsb 2's complement */
4931 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4934 emitcode ("add", "a,#1"); /* this sets carry flag */
4935 emitcode ("xch", "a,b");
4936 emitcode ("cpl", "a"); /* msb 2's complement */
4937 emitcode ("addc", "a,#0");
4938 emitcode ("xch", "a,b");
4940 emitcode ("", "!tlabeldef", lbl->key + 100);
4942 aopPut (AOP (result), "a", 0);
4943 _G.accInUse--;_G.bInUse--;
4945 aopPut (AOP (result), "b", 1);
4948 /*-----------------------------------------------------------------*/
4949 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4950 /*-----------------------------------------------------------------*/
4951 static void genMultTwoByte (operand *left, operand *right,
4952 operand *result, iCode *ic)
4954 sym_link *retype = getSpec(operandType(right));
4955 sym_link *letype = getSpec(operandType(left));
4956 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4959 if (AOP_TYPE (left) == AOP_LIT) {
4964 /* save EA bit in F1 */
4965 lbl = newiTempLabel(NULL);
4966 emitcode ("setb","F1");
4967 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4968 emitcode ("clr","F1");
4969 emitcode("","!tlabeldef",lbl->key+100);
4971 /* load up MB with right */
4973 emitcode("clr","F0");
4974 if (AOP_TYPE(right) == AOP_LIT) {
4975 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4977 emitcode("setb","F0");
4980 emitcode ("mov","mb,#!constbyte",val & 0xff);
4981 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4983 lbl = newiTempLabel(NULL);
4984 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4985 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4986 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4987 emitcode ("xch", "a,b");
4988 emitcode ("cpl","a");
4989 emitcode ("add", "a,#1");
4990 emitcode ("xch", "a,b");
4991 emitcode ("cpl", "a"); // msb
4992 emitcode ("addc", "a,#0");
4993 emitcode ("setb","F0");
4994 emitcode ("","!tlabeldef",lbl->key+100);
4995 emitcode ("mov","mb,b");
4996 emitcode ("mov","mb,a");
4999 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5000 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5002 /* load up MA with left */
5004 lbl = newiTempLabel(NULL);
5005 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5006 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5007 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5008 emitcode ("xch", "a,b");
5009 emitcode ("cpl","a");
5010 emitcode ("add", "a,#1");
5011 emitcode ("xch", "a,b");
5012 emitcode ("cpl", "a"); // msb
5013 emitcode ("addc","a,#0");
5014 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5015 emitcode ("setb","F0");
5016 emitcode ("","!tlabeldef",lbl->key+100);
5017 emitcode ("mov","ma,b");
5018 emitcode ("mov","ma,a");
5020 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5021 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5023 /* wait for multiplication to finish */
5024 lbl = newiTempLabel(NULL);
5025 emitcode("","!tlabeldef", lbl->key+100);
5026 emitcode("mov","a,mcnt1");
5027 emitcode("anl","a,#!constbyte",0x80);
5028 emitcode("jnz","!tlabel",lbl->key+100);
5030 freeAsmop (left, NULL, ic, TRUE);
5031 freeAsmop (right, NULL, ic,TRUE);
5032 aopOp(result, ic, TRUE, FALSE);
5034 /* if unsigned then simple */
5036 emitcode ("mov","a,ma");
5037 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
5038 emitcode ("mov","a,ma");
5039 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
5040 aopPut(AOP(result),"ma",1);
5041 aopPut(AOP(result),"ma",0);
5043 emitcode("push","ma");
5044 emitcode("push","ma");
5045 emitcode("push","ma");
5047 /* negate result if needed */
5048 lbl = newiTempLabel(NULL);
5049 emitcode("jnb","F0,!tlabel",lbl->key+100);
5050 emitcode("cpl","a");
5051 emitcode("add","a,#1");
5052 emitcode("","!tlabeldef", lbl->key+100);
5053 if (AOP_TYPE(result) == AOP_ACC)
5055 D(emitcode(";", "ACC special case."););
5056 /* We know result is the only live aop, and
5057 * it's obviously not a DPTR2, so AP is available.
5059 emitcode("mov", "%s,acc", DP2_RESULT_REG);
5063 aopPut(AOP(result),"a",0);
5066 emitcode("pop","acc");
5067 lbl = newiTempLabel(NULL);
5068 emitcode("jnb","F0,!tlabel",lbl->key+100);
5069 emitcode("cpl","a");
5070 emitcode("addc","a,#0");
5071 emitcode("","!tlabeldef", lbl->key+100);
5072 aopPut(AOP(result),"a",1);
5073 emitcode("pop","acc");
5074 if (AOP_SIZE(result) >= 3) {
5075 lbl = newiTempLabel(NULL);
5076 emitcode("jnb","F0,!tlabel",lbl->key+100);
5077 emitcode("cpl","a");
5078 emitcode("addc","a,#0");
5079 emitcode("","!tlabeldef", lbl->key+100);
5080 aopPut(AOP(result),"a",2);
5082 emitcode("pop","acc");
5083 if (AOP_SIZE(result) >= 4) {
5084 lbl = newiTempLabel(NULL);
5085 emitcode("jnb","F0,!tlabel",lbl->key+100);
5086 emitcode("cpl","a");
5087 emitcode("addc","a,#0");
5088 emitcode("","!tlabeldef", lbl->key+100);
5089 aopPut(AOP(result),"a",3);
5091 if (AOP_TYPE(result) == AOP_ACC)
5093 /* We stashed the result away above. */
5094 emitcode("mov", "acc,%s", DP2_RESULT_REG);
5098 freeAsmop (result, NULL, ic, TRUE);
5100 /* restore EA bit in F1 */
5101 lbl = newiTempLabel(NULL);
5102 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5103 emitcode ("setb","EA");
5104 emitcode("","!tlabeldef",lbl->key+100);
5108 /*-----------------------------------------------------------------*/
5109 /* genMult - generates code for multiplication */
5110 /*-----------------------------------------------------------------*/
5112 genMult (iCode * ic)
5114 operand *left = IC_LEFT (ic);
5115 operand *right = IC_RIGHT (ic);
5116 operand *result = IC_RESULT (ic);
5118 D (emitcode (";", "genMult "););
5120 /* assign the amsops */
5123 /* special cases first */
5125 if (AOP_TYPE (left) == AOP_CRY &&
5126 AOP_TYPE (right) == AOP_CRY)
5128 genMultbits (left, right, result, ic);
5132 /* if both are of size == 1 */
5133 if (AOP_SIZE (left) == 1 &&
5134 AOP_SIZE (right) == 1)
5136 genMultOneByte (left, right, result, ic);
5140 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5141 /* use the ds390 ARITHMETIC accel UNIT */
5142 genMultTwoByte (left, right, result, ic);
5145 /* should have been converted to function call */
5149 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5150 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5151 freeAsmop (result, NULL, ic, TRUE);
5154 /*-----------------------------------------------------------------*/
5155 /* genDivbits :- division of bits */
5156 /*-----------------------------------------------------------------*/
5158 genDivbits (operand * left,
5166 /* the result must be bit */
5167 LOAD_AB_FOR_DIV (left, right, l);
5168 emitcode ("div", "ab");
5169 emitcode ("rrc", "a");
5170 aopOp(result, ic, TRUE, FALSE);
5172 aopPut (AOP (result), "c", 0);
5175 /*-----------------------------------------------------------------*/
5176 /* genDivOneByte : 8 bit division */
5177 /*-----------------------------------------------------------------*/
5179 genDivOneByte (operand * left,
5184 bool lUnsigned, rUnsigned;
5185 bool runtimeSign, compiletimeSign;
5191 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5192 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5194 /* signed or unsigned */
5195 if (lUnsigned && rUnsigned)
5197 /* unsigned is easy */
5198 LOAD_AB_FOR_DIV (left, right, l);
5199 emitcode ("div", "ab");
5202 aopOp (result, ic, TRUE, FALSE);
5203 aopPut (AOP (result), "a", 0);
5206 size = AOP_SIZE (result) - 1;
5209 aopPut (AOP (result), zero, offset++);
5213 /* signed is a little bit more difficult */
5215 /* now sign adjust for both left & right */
5217 /* let's see what's needed: */
5218 /* apply negative sign during runtime */
5219 runtimeSign = FALSE;
5220 /* negative sign from literals */
5221 compiletimeSign = FALSE;
5225 if (AOP_TYPE(left) == AOP_LIT)
5227 /* signed literal */
5228 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5230 compiletimeSign = TRUE;
5233 /* signed but not literal */
5239 if (AOP_TYPE(right) == AOP_LIT)
5241 /* signed literal */
5242 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5244 compiletimeSign ^= TRUE;
5247 /* signed but not literal */
5251 /* initialize F0, which stores the runtime sign */
5254 if (compiletimeSign)
5255 emitcode ("setb", "F0"); /* set sign flag */
5257 emitcode ("clr", "F0"); /* reset sign flag */
5260 /* save the signs of the operands */
5261 if (AOP_TYPE(right) == AOP_LIT)
5263 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5265 if (!rUnsigned && val < 0)
5266 emitcode ("mov", "b,#0x%02x", -val);
5268 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5270 else /* ! literal */
5273 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5276 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5277 lbl = newiTempLabel (NULL);
5278 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5279 emitcode ("cpl", "F0"); /* complement sign flag */
5280 emitcode ("cpl", "a"); /* 2's complement */
5281 emitcode ("inc", "a");
5282 emitcode ("", "!tlabeldef", lbl->key + 100);
5283 emitcode ("mov", "b,a");
5287 if (AOP_TYPE(left) == AOP_LIT)
5289 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5291 if (!lUnsigned && val < 0)
5292 emitcode ("mov", "a,#0x%02x", -val);
5294 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5296 else /* ! literal */
5299 emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5302 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5303 lbl = newiTempLabel (NULL);
5304 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5305 emitcode ("cpl", "F0"); /* complement sign flag */
5306 emitcode ("cpl", "a"); /* 2's complement */
5307 emitcode ("inc", "a");
5308 emitcode ("", "!tlabeldef", lbl->key + 100);
5312 /* now the division */
5313 emitcode ("nop", "; workaround for DS80C390 div bug.");
5314 emitcode ("div", "ab");
5316 if (runtimeSign || compiletimeSign)
5318 lbl = newiTempLabel (NULL);
5320 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5321 emitcode ("cpl", "a"); /* lsb 2's complement */
5322 emitcode ("inc", "a");
5323 emitcode ("", "!tlabeldef", lbl->key + 100);
5325 _G.accInUse++; _G.bInUse++;
5326 aopOp (result, ic, TRUE, FALSE);
5327 size = AOP_SIZE (result) - 1;
5331 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5332 then the result will be in b, a */
5333 emitcode ("mov", "b,a"); /* 1 */
5334 /* msb is 0x00 or 0xff depending on the sign */
5337 emitcode ("mov", "c,F0");
5338 emitcode ("subb", "a,acc");
5339 emitcode ("xch", "a,b"); /* 2 */
5341 aopPut (AOP (result), "b", offset++); /* write msb's */
5343 else /* compiletimeSign */
5345 aopPut (AOP (result), "#0xff", offset++); /* write msb's */
5347 aopPut (AOP (result), "a", 0); /* 3: write lsb */
5351 _G.accInUse++; _G.bInUse++;
5352 aopOp(result, ic, TRUE, FALSE);
5353 size = AOP_SIZE (result) - 1;
5355 aopPut (AOP (result), "a", 0);
5357 aopPut (AOP (result), zero, offset++);
5359 _G.accInUse--; _G.bInUse--;
5363 /*-----------------------------------------------------------------*/
5364 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
5365 /*-----------------------------------------------------------------*/
5366 static void genDivTwoByte (operand *left, operand *right,
5367 operand *result, iCode *ic)
5369 sym_link *retype = getSpec(operandType(right));
5370 sym_link *letype = getSpec(operandType(left));
5371 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5374 /* save EA bit in F1 */
5375 lbl = newiTempLabel(NULL);
5376 emitcode ("setb","F1");
5377 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5378 emitcode ("clr","F1");
5379 emitcode("","!tlabeldef",lbl->key+100);
5381 /* load up MA with left */
5383 emitcode("clr","F0");
5384 lbl = newiTempLabel(NULL);
5385 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5386 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5387 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5388 emitcode ("xch", "a,b");
5389 emitcode ("cpl","a");
5390 emitcode ("add", "a,#1");
5391 emitcode ("xch", "a,b");
5392 emitcode ("cpl", "a"); // msb
5393 emitcode ("addc","a,#0");
5394 emitcode ("setb","F0");
5395 emitcode ("","!tlabeldef",lbl->key+100);
5396 emitcode ("mov","ma,b");
5397 emitcode ("mov","ma,a");
5399 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5400 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5403 /* load up MB with right */
5405 if (AOP_TYPE(right) == AOP_LIT) {
5406 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5408 lbl = newiTempLabel(NULL);
5409 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5410 emitcode("setb","F0");
5411 emitcode ("","!tlabeldef",lbl->key+100);
5414 emitcode ("mov","mb,#!constbyte",val & 0xff);
5415 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5417 lbl = newiTempLabel(NULL);
5418 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5419 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5420 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5421 emitcode ("xch", "a,b");
5422 emitcode ("cpl","a");
5423 emitcode ("add", "a,#1");
5424 emitcode ("xch", "a,b");
5425 emitcode ("cpl", "a"); // msb
5426 emitcode ("addc", "a,#0");
5427 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5428 emitcode ("setb","F0");
5429 emitcode ("","!tlabeldef",lbl->key+100);
5430 emitcode ("mov","mb,b");
5431 emitcode ("mov","mb,a");
5434 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5435 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5438 /* wait for multiplication to finish */
5439 lbl = newiTempLabel(NULL);
5440 emitcode("","!tlabeldef", lbl->key+100);
5441 emitcode("mov","a,mcnt1");
5442 emitcode("anl","a,#!constbyte",0x80);
5443 emitcode("jnz","!tlabel",lbl->key+100);
5445 freeAsmop (left, NULL, ic, TRUE);
5446 freeAsmop (right, NULL, ic,TRUE);
5447 aopOp(result, ic, TRUE, FALSE);
5449 /* if unsigned then simple */
5451 aopPut(AOP(result),"ma",1);
5452 aopPut(AOP(result),"ma",0);
5454 emitcode("push","ma");
5456 /* negate result if needed */
5457 lbl = newiTempLabel(NULL);
5458 emitcode("jnb","F0,!tlabel",lbl->key+100);
5459 emitcode("cpl","a");
5460 emitcode("add","a,#1");
5461 emitcode("","!tlabeldef", lbl->key+100);
5462 aopPut(AOP(result),"a",0);
5463 emitcode("pop","acc");
5464 lbl = newiTempLabel(NULL);
5465 emitcode("jnb","F0,!tlabel",lbl->key+100);
5466 emitcode("cpl","a");
5467 emitcode("addc","a,#0");
5468 emitcode("","!tlabeldef", lbl->key+100);
5469 aopPut(AOP(result),"a",1);
5471 freeAsmop (result, NULL, ic, TRUE);
5472 /* restore EA bit in F1 */
5473 lbl = newiTempLabel(NULL);
5474 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5475 emitcode ("setb","EA");
5476 emitcode("","!tlabeldef",lbl->key+100);
5480 /*-----------------------------------------------------------------*/
5481 /* genDiv - generates code for division */
5482 /*-----------------------------------------------------------------*/
5486 operand *left = IC_LEFT (ic);
5487 operand *right = IC_RIGHT (ic);
5488 operand *result = IC_RESULT (ic);
5490 D (emitcode (";", "genDiv "););
5492 /* assign the amsops */
5495 /* special cases first */
5497 if (AOP_TYPE (left) == AOP_CRY &&
5498 AOP_TYPE (right) == AOP_CRY)
5500 genDivbits (left, right, result, ic);
5504 /* if both are of size == 1 */
5505 if (AOP_SIZE (left) == 1 &&
5506 AOP_SIZE (right) == 1)
5508 genDivOneByte (left, right, result, ic);
5512 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5513 /* use the ds390 ARITHMETIC accel UNIT */
5514 genDivTwoByte (left, right, result, ic);
5517 /* should have been converted to function call */
5520 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5521 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5522 freeAsmop (result, NULL, ic, TRUE);
5525 /*-----------------------------------------------------------------*/
5526 /* genModbits :- modulus of bits */
5527 /*-----------------------------------------------------------------*/
5529 genModbits (operand * left,
5537 /* the result must be bit */
5538 LOAD_AB_FOR_DIV (left, right, l);
5539 emitcode ("div", "ab");
5540 emitcode ("mov", "a,b");
5541 emitcode ("rrc", "a");
5542 aopOp(result, ic, TRUE, FALSE);
5543 aopPut (AOP (result), "c", 0);
5546 /*-----------------------------------------------------------------*/
5547 /* genModOneByte : 8 bit modulus */
5548 /*-----------------------------------------------------------------*/
5550 genModOneByte (operand * left,
5555 bool lUnsigned, rUnsigned;
5556 bool runtimeSign, compiletimeSign;
5562 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5563 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5565 /* signed or unsigned */
5566 if (lUnsigned && rUnsigned)
5568 /* unsigned is easy */
5569 LOAD_AB_FOR_DIV (left, right, l);
5570 emitcode ("div", "ab");
5571 aopOp (result, ic, TRUE, FALSE);
5572 aopPut (AOP (result), "b", 0);
5574 for (size = AOP_SIZE (result) - 1; size--;)
5575 aopPut (AOP (result), zero, offset++);
5579 /* signed is a little bit more difficult */
5581 /* now sign adjust for both left & right */
5583 /* modulus: sign of the right operand has no influence on the result! */
5584 if (AOP_TYPE(right) == AOP_LIT)
5586 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5588 if (!rUnsigned && val < 0)
5589 emitcode ("mov", "b,#0x%02x", -val);
5591 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5593 else /* ! literal */
5596 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5599 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5600 lbl = newiTempLabel (NULL);
5601 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5602 emitcode ("cpl", "a"); /* 2's complement */
5603 emitcode ("inc", "a");
5604 emitcode ("", "!tlabeldef", lbl->key + 100);
5605 emitcode ("mov", "b,a");
5609 /* let's see what's needed: */
5610 /* apply negative sign during runtime */
5611 runtimeSign = FALSE;
5612 /* negative sign from literals */
5613 compiletimeSign = FALSE;
5615 /* sign adjust left side */
5616 if (AOP_TYPE(left) == AOP_LIT)
5618 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5620 if (!lUnsigned && val < 0)
5622 compiletimeSign = TRUE; /* set sign flag */
5623 emitcode ("mov", "a,#0x%02x", -val);
5626 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5628 else /* ! literal */
5630 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5635 emitcode ("clr", "F0"); /* clear sign flag */
5637 lbl = newiTempLabel (NULL);
5638 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5639 emitcode ("setb", "F0"); /* set sign flag */
5640 emitcode ("cpl", "a"); /* 2's complement */
5641 emitcode ("inc", "a");
5642 emitcode ("", "!tlabeldef", lbl->key + 100);
5646 /* now the modulus */
5647 emitcode ("nop", "; workaround for DS80C390 div bug.");
5648 emitcode ("div", "ab");
5650 if (runtimeSign || compiletimeSign)
5652 emitcode ("mov", "a,b");
5653 lbl = newiTempLabel (NULL);
5655 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5656 emitcode ("cpl", "a"); /* lsb 2's complement */
5657 emitcode ("inc", "a");
5658 emitcode ("", "!tlabeldef", lbl->key + 100);
5660 _G.accInUse++; _G.bInUse++;
5661 aopOp (result, ic, TRUE, FALSE);
5662 size = AOP_SIZE (result) - 1;
5666 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5667 then the result will be in b, a */
5668 emitcode ("mov", "b,a"); /* 1 */
5669 /* msb is 0x00 or 0xff depending on the sign */
5672 emitcode ("mov", "c,F0");
5673 emitcode ("subb", "a,acc");
5674 emitcode ("xch", "a,b"); /* 2 */
5676 aopPut (AOP (result), "b", offset++); /* write msb's */
5678 else /* compiletimeSign */
5680 aopPut (AOP (result), "#0xff", offset++); /* write msb's */
5682 aopPut (AOP (result), "a", 0); /* 3: write lsb */
5686 _G.accInUse++; _G.bInUse++;
5687 aopOp(result, ic, TRUE, FALSE);
5688 size = AOP_SIZE (result) - 1;
5690 aopPut (AOP (result), "b", 0);
5692 aopPut (AOP (result), zero, offset++);
5694 _G.accInUse--; _G.bInUse--;
5698 /*-----------------------------------------------------------------*/
5699 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
5700 /*-----------------------------------------------------------------*/
5701 static void genModTwoByte (operand *left, operand *right,
5702 operand *result, iCode *ic)
5704 sym_link *retype = getSpec(operandType(right));
5705 sym_link *letype = getSpec(operandType(left));
5706 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5709 /* load up MA with left */
5710 /* save EA bit in F1 */
5711 lbl = newiTempLabel(NULL);
5712 emitcode ("setb","F1");
5713 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5714 emitcode ("clr","F1");
5715 emitcode("","!tlabeldef",lbl->key+100);
5718 lbl = newiTempLabel(NULL);
5719 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5720 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5721 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5722 emitcode ("xch", "a,b");
5723 emitcode ("cpl","a");
5724 emitcode ("add", "a,#1");
5725 emitcode ("xch", "a,b");
5726 emitcode ("cpl", "a"); // msb
5727 emitcode ("addc","a,#0");
5728 emitcode ("","!tlabeldef",lbl->key+100);
5729 emitcode ("mov","ma,b");
5730 emitcode ("mov","ma,a");
5732 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5733 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5736 /* load up MB with right */
5738 if (AOP_TYPE(right) == AOP_LIT) {
5739 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5743 emitcode ("mov","mb,#!constbyte",val & 0xff);
5744 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5746 lbl = newiTempLabel(NULL);
5747 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5748 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5749 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5750 emitcode ("xch", "a,b");
5751 emitcode ("cpl","a");
5752 emitcode ("add", "a,#1");
5753 emitcode ("xch", "a,b");
5754 emitcode ("cpl", "a"); // msb
5755 emitcode ("addc", "a,#0");
5756 emitcode ("","!tlabeldef",lbl->key+100);
5757 emitcode ("mov","mb,b");
5758 emitcode ("mov","mb,a");
5761 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5762 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5765 /* wait for multiplication to finish */
5766 lbl = newiTempLabel(NULL);
5767 emitcode("","!tlabeldef", lbl->key+100);
5768 emitcode("mov","a,mcnt1");
5769 emitcode("anl","a,#!constbyte",0x80);
5770 emitcode("jnz","!tlabel",lbl->key+100);
5772 freeAsmop (left, NULL, ic, TRUE);
5773 freeAsmop (right, NULL, ic,TRUE);
5774 aopOp(result, ic, TRUE, FALSE);
5776 aopPut(AOP(result),"mb",1);
5777 aopPut(AOP(result),"mb",0);
5778 freeAsmop (result, NULL, ic, TRUE);
5780 /* restore EA bit in F1 */
5781 lbl = newiTempLabel(NULL);
5782 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5783 emitcode ("setb","EA");
5784 emitcode("","!tlabeldef",lbl->key+100);
5788 /*-----------------------------------------------------------------*/
5789 /* genMod - generates code for division */
5790 /*-----------------------------------------------------------------*/
5794 operand *left = IC_LEFT (ic);
5795 operand *right = IC_RIGHT (ic);
5796 operand *result = IC_RESULT (ic);
5798 D (emitcode (";", "genMod "); );
5800 /* assign the amsops */
5803 /* special cases first */
5805 if (AOP_TYPE (left) == AOP_CRY &&
5806 AOP_TYPE (right) == AOP_CRY)
5808 genModbits (left, right, result, ic);
5812 /* if both are of size == 1 */
5813 if (AOP_SIZE (left) == 1 &&
5814 AOP_SIZE (right) == 1)
5816 genModOneByte (left, right, result, ic);
5820 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5821 /* use the ds390 ARITHMETIC accel UNIT */
5822 genModTwoByte (left, right, result, ic);
5826 /* should have been converted to function call */
5830 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5831 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5832 freeAsmop (result, NULL, ic, TRUE);
5835 /*-----------------------------------------------------------------*/
5836 /* genIfxJump :- will create a jump depending on the ifx */
5837 /*-----------------------------------------------------------------*/
5839 genIfxJump (iCode * ic, char *jval)
5842 symbol *tlbl = newiTempLabel (NULL);
5845 D (emitcode (";", "genIfxJump"););
5847 /* if true label then we jump if condition
5851 jlbl = IC_TRUE (ic);
5852 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5853 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5857 /* false label is present */
5858 jlbl = IC_FALSE (ic);
5859 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5860 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5862 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5863 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5865 emitcode (inst, "!tlabel", tlbl->key + 100);
5866 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5867 emitcode ("", "!tlabeldef", tlbl->key + 100);
5869 /* mark the icode as generated */
5873 /*-----------------------------------------------------------------*/
5874 /* genCmp :- greater or less than comparison */
5875 /*-----------------------------------------------------------------*/
5877 genCmp (operand * left, operand * right,
5878 iCode * ic, iCode * ifx, int sign)
5880 int size, offset = 0;
5881 unsigned long lit = 0L;
5884 D (emitcode (";", "genCmp"););
5886 result = IC_RESULT (ic);
5888 /* if left & right are bit variables */
5889 if (AOP_TYPE (left) == AOP_CRY &&
5890 AOP_TYPE (right) == AOP_CRY)
5892 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5893 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5897 /* subtract right from left if at the
5898 end the carry flag is set then we know that
5899 left is greater than right */
5900 size = max (AOP_SIZE (left), AOP_SIZE (right));
5902 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5903 if ((size == 1) && !sign
5904 && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5906 symbol *lbl = newiTempLabel (NULL);
5907 emitcode ("cjne", "%s,%s,!tlabel",
5908 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5909 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5911 emitcode ("", "!tlabeldef", lbl->key + 100);
5915 if (AOP_TYPE (right) == AOP_LIT)
5917 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5918 /* optimize if(x < 0) or if(x >= 0) */
5927 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5929 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5930 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5932 aopOp (result, ic, FALSE, FALSE);
5934 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5936 freeAsmop (result, NULL, ic, TRUE);
5937 genIfxJump (ifx, "acc.7");
5942 emitcode ("rlc", "a");
5944 goto release_freedLR;
5952 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5953 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5954 // emitcode (";", "genCmp #2");
5955 if (sign && (size == 0))
5957 // emitcode (";", "genCmp #3");
5958 emitcode ("xrl", "a,#!constbyte",0x80);
5959 if (AOP_TYPE (right) == AOP_LIT)
5961 unsigned long lit = (unsigned long)
5962 floatFromVal (AOP (right)->aopu.aop_lit);
5963 // emitcode (";", "genCmp #3.1");
5964 emitcode ("subb", "a,#!constbyte",
5965 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5969 // emitcode (";", "genCmp #3.2");
5971 MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5972 saveAccWarn = DEFAULT_ACC_WARNING;
5973 emitcode ("xrl", "b,#!constbyte",0x80);
5974 emitcode ("subb", "a,b");
5981 // emitcode (";", "genCmp #4");
5983 s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5984 saveAccWarn = DEFAULT_ACC_WARNING;
5986 emitcode ("subb", "a,%s", s);
5993 /* Don't need the left & right operands any more; do need the result. */
5994 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5995 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5997 aopOp (result, ic, FALSE, FALSE);
6001 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6007 /* if the result is used in the next
6008 ifx conditional branch then generate
6009 code a little differently */
6012 genIfxJump (ifx, "c");
6018 /* leave the result in acc */
6020 freeAsmop (result, NULL, ic, TRUE);
6023 /*-----------------------------------------------------------------*/
6024 /* genCmpGt :- greater than comparison */
6025 /*-----------------------------------------------------------------*/
6027 genCmpGt (iCode * ic, iCode * ifx)
6029 operand *left, *right;
6030 sym_link *letype, *retype;
6033 D (emitcode (";", "genCmpGt ");
6036 left = IC_LEFT (ic);
6037 right = IC_RIGHT (ic);
6039 letype = getSpec (operandType (left));
6040 retype = getSpec (operandType (right));
6041 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6043 /* assign the left & right amsops */
6046 genCmp (right, left, ic, ifx, sign);
6049 /*-----------------------------------------------------------------*/
6050 /* genCmpLt - less than comparisons */
6051 /*-----------------------------------------------------------------*/
6053 genCmpLt (iCode * ic, iCode * ifx)
6055 operand *left, *right;
6056 sym_link *letype, *retype;
6059 D (emitcode (";", "genCmpLt "););
6061 left = IC_LEFT (ic);
6062 right = IC_RIGHT (ic);
6064 letype = getSpec (operandType (left));
6065 retype = getSpec (operandType (right));
6066 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6068 /* assign the left & right amsops */
6071 genCmp (left, right, ic, ifx, sign);
6074 /*-----------------------------------------------------------------*/
6075 /* gencjneshort - compare and jump if not equal */
6076 /*-----------------------------------------------------------------*/
6078 gencjneshort (operand * left, operand * right, symbol * lbl)
6080 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6082 unsigned long lit = 0L;
6084 D (emitcode (";", "gencjneshort");
6087 /* if the left side is a literal or
6088 if the right is in a pointer register and left
6090 if ((AOP_TYPE (left) == AOP_LIT) ||
6091 (AOP_TYPE (left) == AOP_IMMD) ||
6092 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6099 if (AOP_TYPE (right) == AOP_LIT)
6100 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6102 if (opIsGptr (left) || opIsGptr (right))
6104 /* We are comparing a generic pointer to something.
6105 * Exclude the generic type byte from the comparison.
6108 D (emitcode (";", "cjneshort: generic ptr special case."););
6112 /* if the right side is a literal then anything goes */
6113 if (AOP_TYPE (right) == AOP_LIT &&
6114 AOP_TYPE (left) != AOP_DIR)
6118 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6119 emitcode ("cjne", "a,%s,!tlabel",
6120 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
6126 /* if the right side is in a register or in direct space or
6127 if the left is a pointer register & right is not */
6128 else if (AOP_TYPE (right) == AOP_REG ||
6129 AOP_TYPE (right) == AOP_DIR ||
6130 AOP_TYPE (right) == AOP_LIT ||
6131 AOP_TYPE (right) == AOP_IMMD ||
6132 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6133 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6137 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6138 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6139 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6140 emitcode ("jnz", "!tlabel", lbl->key + 100);
6142 emitcode ("cjne", "a,%s,!tlabel",
6143 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
6150 /* right is a pointer reg need both a & b */
6153 MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6154 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6155 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
6161 /*-----------------------------------------------------------------*/
6162 /* gencjne - compare and jump if not equal */
6163 /*-----------------------------------------------------------------*/
6165 gencjne (operand * left, operand * right, symbol * lbl)
6167 symbol *tlbl = newiTempLabel (NULL);
6169 D (emitcode (";", "gencjne");
6172 gencjneshort (left, right, lbl);
6174 emitcode ("mov", "a,%s", one);
6175 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
6176 emitcode ("", "!tlabeldef", lbl->key + 100);
6177 emitcode ("clr", "a");
6178 emitcode ("", "!tlabeldef", tlbl->key + 100);
6181 /*-----------------------------------------------------------------*/
6182 /* genCmpEq - generates code for equal to */
6183 /*-----------------------------------------------------------------*/
6185 genCmpEq (iCode * ic, iCode * ifx)
6187 operand *left, *right, *result;
6189 D (emitcode (";", "genCmpEq ");
6193 AOP_SET_LOCALS (ic);
6195 /* if literal, literal on the right or
6196 if the right is in a pointer register and left
6198 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6199 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6201 operand *t = IC_RIGHT (ic);
6202 IC_RIGHT (ic) = IC_LEFT (ic);
6206 if (ifx && /* !AOP_SIZE(result) */
6207 OP_SYMBOL (result) &&
6208 OP_SYMBOL (result)->regType == REG_CND)
6211 /* if they are both bit variables */
6212 if (AOP_TYPE (left) == AOP_CRY &&
6213 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6215 if (AOP_TYPE (right) == AOP_LIT)
6217 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6220 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6221 emitcode ("cpl", "c");
6225 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6229 emitcode ("clr", "c");
6231 /* AOP_TYPE(right) == AOP_CRY */
6235 symbol *lbl = newiTempLabel (NULL);
6236 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6237 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6238 emitcode ("cpl", "c");
6239 emitcode ("", "!tlabeldef", (lbl->key + 100));
6241 /* if true label then we jump if condition
6243 tlbl = newiTempLabel (NULL);
6246 emitcode ("jnc", "!tlabel", tlbl->key + 100);
6247 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6251 emitcode ("jc", "!tlabel", tlbl->key + 100);
6252 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6254 emitcode ("", "!tlabeldef", tlbl->key + 100);
6258 tlbl = newiTempLabel (NULL);
6259 gencjneshort (left, right, tlbl);
6262 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6263 emitcode ("", "!tlabeldef", tlbl->key + 100);
6267 symbol *lbl = newiTempLabel (NULL);
6268 emitcode ("sjmp", "!tlabel", lbl->key + 100);
6269 emitcode ("", "!tlabeldef", tlbl->key + 100);
6270 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6271 emitcode ("", "!tlabeldef", lbl->key + 100);
6274 /* mark the icode as generated */
6277 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6278 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6282 /* if they are both bit variables */
6283 if (AOP_TYPE (left) == AOP_CRY &&
6284 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6286 if (AOP_TYPE (right) == AOP_LIT)
6288 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6291 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6292 emitcode ("cpl", "c");
6296 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6300 emitcode ("clr", "c");
6302 /* AOP_TYPE(right) == AOP_CRY */
6306 symbol *lbl = newiTempLabel (NULL);
6307 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6308 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6309 emitcode ("cpl", "c");
6310 emitcode ("", "!tlabeldef", (lbl->key + 100));
6313 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6314 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6316 aopOp (result, ic, TRUE, FALSE);
6319 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6326 genIfxJump (ifx, "c");
6329 /* if the result is used in an arithmetic operation
6330 then put the result in place */
6335 gencjne (left, right, newiTempLabel (NULL));
6337 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6338 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6340 aopOp (result, ic, TRUE, FALSE);
6342 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6344 aopPut (AOP (result), "a", 0);
6349 genIfxJump (ifx, "a");
6352 /* if the result is used in an arithmetic operation
6353 then put the result in place */
6354 if (AOP_TYPE (result) != AOP_CRY)
6356 /* leave the result in acc */
6360 freeAsmop (result, NULL, ic, TRUE);
6363 /*-----------------------------------------------------------------*/
6364 /* ifxForOp - returns the icode containing the ifx for operand */
6365 /*-----------------------------------------------------------------*/
6367 ifxForOp (operand * op, iCode * ic)
6369 /* if true symbol then needs to be assigned */
6370 if (IS_TRUE_SYMOP (op))
6373 /* if this has register type condition and
6374 the next instruction is ifx with the same operand
6375 and live to of the operand is upto the ifx only then */
6377 ic->next->op == IFX &&
6378 IC_COND (ic->next)->key == op->key &&
6379 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6384 /*-----------------------------------------------------------------*/
6385 /* hasInc - operand is incremented before any other use */
6386 /*-----------------------------------------------------------------*/
6388 hasInc (operand *op, iCode *ic, int osize)
6390 sym_link *type = operandType(op);
6391 sym_link *retype = getSpec (type);
6392 iCode *lic = ic->next;
6395 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6396 if (!IS_SYMOP(op)) return NULL;
6398 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6399 if (IS_AGGREGATE(type->next)) return NULL;
6400 if (osize != (isize = getSize(type->next))) return NULL;
6403 /* if operand of the form op = op + <sizeof *op> */
6404 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6405 isOperandEqual(IC_RESULT(lic),op) &&
6406 isOperandLiteral(IC_RIGHT(lic)) &&
6407 operandLitValue(IC_RIGHT(lic)) == isize) {
6410 /* if the operand used or deffed */
6411 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6414 /* if GOTO or IFX */
6415 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6421 /*-----------------------------------------------------------------*/
6422 /* genAndOp - for && operation */
6423 /*-----------------------------------------------------------------*/
6425 genAndOp (iCode * ic)
6427 operand *left, *right, *result;
6430 D (emitcode (";", "genAndOp "););
6432 /* note here that && operations that are in an
6433 if statement are taken away by backPatchLabels
6434 only those used in arthmetic operations remain */
6436 AOP_SET_LOCALS (ic);
6438 /* if both are bit variables */
6439 if (AOP_TYPE (left) == AOP_CRY &&
6440 AOP_TYPE (right) == AOP_CRY)
6442 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6443 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6444 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6445 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6447 aopOp (result,ic,FALSE, FALSE);
6452 tlbl = newiTempLabel (NULL);
6454 emitcode ("jz", "!tlabel", tlbl->key + 100);
6456 emitcode ("", "!tlabeldef", tlbl->key + 100);
6457 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6458 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6460 aopOp (result,ic,FALSE, FALSE);
6463 freeAsmop (result, NULL, ic, TRUE);
6467 /*-----------------------------------------------------------------*/
6468 /* genOrOp - for || operation */
6469 /*-----------------------------------------------------------------*/
6471 genOrOp (iCode * ic)
6473 operand *left, *right, *result;
6476 D (emitcode (";", "genOrOp "););
6478 /* note here that || operations that are in an
6479 if statement are taken away by backPatchLabels
6480 only those used in arthmetic operations remain */
6482 AOP_SET_LOCALS (ic);
6484 /* if both are bit variables */
6485 if (AOP_TYPE (left) == AOP_CRY &&
6486 AOP_TYPE (right) == AOP_CRY)
6488 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6489 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6490 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6491 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6493 aopOp (result,ic,FALSE, FALSE);
6499 tlbl = newiTempLabel (NULL);
6501 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6503 emitcode ("", "!tlabeldef", tlbl->key + 100);
6504 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6505 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6507 aopOp (result,ic,FALSE, FALSE);
6512 freeAsmop (result, NULL, ic, TRUE);
6515 /*-----------------------------------------------------------------*/
6516 /* isLiteralBit - test if lit == 2^n */
6517 /*-----------------------------------------------------------------*/
6519 isLiteralBit (unsigned long lit)
6521 unsigned long pw[32] =
6522 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6523 0x100L, 0x200L, 0x400L, 0x800L,
6524 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6525 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6526 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6527 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6528 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6531 for (idx = 0; idx < 32; idx++)
6537 /*-----------------------------------------------------------------*/
6538 /* continueIfTrue - */
6539 /*-----------------------------------------------------------------*/
6541 continueIfTrue (iCode * ic)
6544 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6548 /*-----------------------------------------------------------------*/
6550 /*-----------------------------------------------------------------*/
6552 jumpIfTrue (iCode * ic)
6555 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6559 /*-----------------------------------------------------------------*/
6560 /* jmpTrueOrFalse - */
6561 /*-----------------------------------------------------------------*/
6563 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6565 // ugly but optimized by peephole
6568 symbol *nlbl = newiTempLabel (NULL);
6569 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6570 emitcode ("", "!tlabeldef", tlbl->key + 100);
6571 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6572 emitcode ("", "!tlabeldef", nlbl->key + 100);
6576 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6577 emitcode ("", "!tlabeldef", tlbl->key + 100);
6582 // Generate code to perform a bit-wise logic operation
6583 // on two operands in far space (assumed to already have been
6584 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6585 // in far space. This requires pushing the result on the stack
6586 // then popping it into the result.
6588 genFarFarLogicOp(iCode *ic, char *logicOp)
6590 int size, resultSize, compSize;
6594 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6595 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
6596 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6598 _startLazyDPSEvaluation();
6599 for (size = compSize; (size--); offset++)
6601 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6602 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6603 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6605 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6606 emitcode ("push", "acc");
6608 _endLazyDPSEvaluation();
6610 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6611 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6612 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6614 resultSize = AOP_SIZE(IC_RESULT(ic));
6616 ADJUST_PUSHED_RESULT(compSize, resultSize);
6618 _startLazyDPSEvaluation();
6621 emitcode ("pop", "acc");
6622 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6624 _endLazyDPSEvaluation();
6625 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6629 /*-----------------------------------------------------------------*/
6630 /* genAnd - code for and */
6631 /*-----------------------------------------------------------------*/
6633 genAnd (iCode * ic, iCode * ifx)
6635 operand *left, *right, *result;
6636 int size, offset = 0;
6637 unsigned long lit = 0L;
6642 D (emitcode (";", "genAnd "););
6644 AOP_OP_3_NOFATAL (ic, pushResult);
6645 AOP_SET_LOCALS (ic);
6649 genFarFarLogicOp(ic, "anl");
6654 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6656 AOP_TYPE (left), AOP_TYPE (right));
6657 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6659 AOP_SIZE (left), AOP_SIZE (right));
6662 /* if left is a literal & right is not then exchange them */
6663 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6664 #ifdef LOGIC_OPS_BROKEN
6665 || AOP_NEEDSACC (left)
6669 operand *tmp = right;
6674 /* if result = right then exchange left and right */
6675 if (sameRegs (AOP (result), AOP (right)))
6677 operand *tmp = right;
6682 /* if right is bit then exchange them */
6683 if (AOP_TYPE (right) == AOP_CRY &&
6684 AOP_TYPE (left) != AOP_CRY)
6686 operand *tmp = right;
6690 if (AOP_TYPE (right) == AOP_LIT)
6691 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6693 size = AOP_SIZE (result);
6696 // result = bit & yy;
6697 if (AOP_TYPE (left) == AOP_CRY)
6699 // c = bit & literal;
6700 if (AOP_TYPE (right) == AOP_LIT)
6704 if (size && sameRegs (AOP (result), AOP (left)))
6707 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6712 if (size && (AOP_TYPE (result) == AOP_CRY))
6714 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6717 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6722 emitcode ("clr", "c");
6727 if (AOP_TYPE (right) == AOP_CRY)
6730 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6731 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6736 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6738 emitcode ("rrc", "a");
6739 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6747 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6748 genIfxJump (ifx, "c");
6752 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6753 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6754 if ((AOP_TYPE (right) == AOP_LIT) &&
6755 (AOP_TYPE (result) == AOP_CRY) &&
6756 (AOP_TYPE (left) != AOP_CRY))
6758 int posbit = isLiteralBit (lit);
6763 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6766 emitcode ("mov", "c,acc.%d", posbit & 0x07);
6772 SNPRINTF (buff, sizeof(buff),
6773 "acc.%d", posbit & 0x07);
6774 genIfxJump (ifx, buff);
6778 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6785 symbol *tlbl = newiTempLabel (NULL);
6786 int sizel = AOP_SIZE (left);
6788 emitcode ("setb", "c");
6791 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6793 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6795 if ((posbit = isLiteralBit (bytelit)) != 0)
6796 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6799 if (bytelit != 0x0FFL)
6800 emitcode ("anl", "a,%s",
6801 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6802 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6807 // bit = left & literal
6810 emitcode ("clr", "c");
6811 emitcode ("", "!tlabeldef", tlbl->key + 100);
6813 // if(left & literal)
6817 jmpTrueOrFalse (ifx, tlbl);
6819 emitcode ("", "!tlabeldef", tlbl->key + 100);
6827 /* if left is same as result */
6828 if (sameRegs (AOP (result), AOP (left)))
6830 for (; size--; offset++)
6832 if (AOP_TYPE (right) == AOP_LIT)
6834 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6835 if (bytelit == 0x0FF)
6837 /* dummy read of volatile operand */
6838 if (isOperandVolatile (left, FALSE))
6839 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6843 else if (bytelit == 0)
6845 aopPut (AOP (result), zero, offset);
6847 else if (IS_AOP_PREG (result))
6849 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6850 emitcode ("anl", "a,%s",
6851 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6852 aopPut (AOP (result), "a", offset);
6855 emitcode ("anl", "%s,%s",
6856 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6857 aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6861 if (AOP_TYPE (left) == AOP_ACC)
6862 emitcode ("anl", "a,%s",
6863 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6866 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6867 if (IS_AOP_PREG (result))
6869 emitcode ("anl", "a,%s",
6870 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6871 aopPut (AOP (result), "a", offset);
6874 emitcode ("anl", "%s,a",
6875 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6882 // left & result in different registers
6883 if (AOP_TYPE (result) == AOP_CRY)
6886 // if(size), result in bit
6887 // if(!size && ifx), conditional oper: if(left & right)
6888 symbol *tlbl = newiTempLabel (NULL);
6889 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6891 emitcode ("setb", "c");
6894 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6895 emitcode ("anl", "a,%s",
6896 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6898 if (AOP_TYPE(left)==AOP_ACC) {
6899 emitcode("mov", "b,a");
6900 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6901 emitcode("anl", "a,b");
6903 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6904 emitcode ("anl", "a,%s",
6905 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6908 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6914 emitcode ("", "!tlabeldef", tlbl->key + 100);
6918 jmpTrueOrFalse (ifx, tlbl);
6920 emitcode ("", "!tlabeldef", tlbl->key + 100);
6924 for (; (size--); offset++)
6927 // result = left & right
6928 if (AOP_TYPE (right) == AOP_LIT)
6930 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6931 if (bytelit == 0x0FF)
6933 aopPut (AOP (result),
6934 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6938 else if (bytelit == 0)
6940 /* dummy read of volatile operand */
6941 if (isOperandVolatile (left, FALSE))
6942 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6943 aopPut (AOP (result), zero, offset);
6946 D (emitcode (";", "better literal AND."););
6947 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6948 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6949 FALSE, FALSE, DP2_RESULT_REG));
6954 // faster than result <- left, anl result,right
6955 // and better if result is SFR
6956 if (AOP_TYPE (left) == AOP_ACC)
6958 emitcode ("anl", "a,%s",
6959 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6963 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6964 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6966 emitcode("mov", "b,a");
6970 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6971 emitcode ("anl", "a,%s", rOp);
6974 aopPut (AOP (result), "a", offset);
6980 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6981 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6982 freeAsmop (result, NULL, ic, TRUE);
6986 /*-----------------------------------------------------------------*/
6987 /* genOr - code for or */
6988 /*-----------------------------------------------------------------*/
6990 genOr (iCode * ic, iCode * ifx)
6992 operand *left, *right, *result;
6993 int size, offset = 0;
6994 unsigned long lit = 0L;
6998 D (emitcode (";", "genOr "););
7000 AOP_OP_3_NOFATAL (ic, pushResult);
7001 AOP_SET_LOCALS (ic);
7005 genFarFarLogicOp(ic, "orl");
7011 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7013 AOP_TYPE (left), AOP_TYPE (right));
7014 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7016 AOP_SIZE (left), AOP_SIZE (right));
7019 /* if left is a literal & right is not then exchange them */
7020 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7021 #ifdef LOGIC_OPS_BROKEN
7022 || AOP_NEEDSACC (left) // I think this is a net loss now.
7026 operand *tmp = right;
7031 /* if result = right then exchange them */
7032 if (sameRegs (AOP (result), AOP (right)))
7034 operand *tmp = right;
7039 /* if right is bit then exchange them */
7040 if (AOP_TYPE (right) == AOP_CRY &&
7041 AOP_TYPE (left) != AOP_CRY)
7043 operand *tmp = right;
7047 if (AOP_TYPE (right) == AOP_LIT)
7048 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7050 size = AOP_SIZE (result);
7054 if (AOP_TYPE (left) == AOP_CRY)
7056 if (AOP_TYPE (right) == AOP_LIT)
7058 // c = bit & literal;
7061 // lit != 0 => result = 1
7062 if (AOP_TYPE (result) == AOP_CRY)
7065 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7067 continueIfTrue (ifx);
7070 emitcode ("setb", "c");
7074 // lit == 0 => result = left
7075 if (size && sameRegs (AOP (result), AOP (left)))
7077 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7082 if (AOP_TYPE (right) == AOP_CRY)
7085 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7086 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7091 symbol *tlbl = newiTempLabel (NULL);
7092 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7093 emitcode ("setb", "c");
7094 emitcode ("jb", "%s,!tlabel",
7095 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7097 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7098 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7100 jmpTrueOrFalse (ifx, tlbl);
7106 emitcode ("", "!tlabeldef", tlbl->key + 100);
7115 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7116 genIfxJump (ifx, "c");
7120 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7121 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7122 if ((AOP_TYPE (right) == AOP_LIT) &&
7123 (AOP_TYPE (result) == AOP_CRY) &&
7124 (AOP_TYPE (left) != AOP_CRY))
7130 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7132 continueIfTrue (ifx);
7137 // lit = 0, result = boolean(left)
7139 emitcode ("setb", "c");
7143 symbol *tlbl = newiTempLabel (NULL);
7144 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7146 emitcode ("", "!tlabeldef", tlbl->key + 100);
7150 genIfxJump (ifx, "a");
7158 /* if left is same as result */
7159 if (sameRegs (AOP (result), AOP (left)))
7161 for (; size--; offset++)
7163 if (AOP_TYPE (right) == AOP_LIT)
7165 bytelit = (int)((lit >> (offset * 8)) & 0x0FFL);
7166 if (bytelit == 0x00L)
7168 /* dummy read of volatile operand */
7169 if (isOperandVolatile (left, FALSE))
7170 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7174 else if (bytelit == 0x0FF)
7176 aopPut (AOP (result), "#0xFF", offset);
7178 else if (IS_AOP_PREG (left))
7180 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7181 emitcode ("orl", "a,%s",
7182 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7183 aopPut (AOP (result), "a", offset);
7187 emitcode ("orl", "%s,%s",
7188 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7189 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7194 if (AOP_TYPE (left) == AOP_ACC)
7196 emitcode ("orl", "a,%s",
7197 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7201 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7202 if (IS_AOP_PREG (left))
7204 emitcode ("orl", "a,%s",
7205 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7206 aopPut (AOP (result), "a", offset);
7210 emitcode ("orl", "%s,a",
7211 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7219 // left & result in different registers
7220 if (AOP_TYPE (result) == AOP_CRY)
7223 // if(size), result in bit
7224 // if(!size && ifx), conditional oper: if(left | right)
7225 symbol *tlbl = newiTempLabel (NULL);
7226 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7228 emitcode ("setb", "c");
7231 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7232 emitcode ("orl", "a,%s",
7233 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7235 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7236 emitcode ("orl", "a,%s",
7237 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
7239 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7245 emitcode ("", "!tlabeldef", tlbl->key + 100);
7249 jmpTrueOrFalse (ifx, tlbl);
7251 emitcode ("", "!tlabeldef", tlbl->key + 100);
7255 _startLazyDPSEvaluation();
7256 for (; (size--); offset++)
7259 // result = left & right
7260 if (AOP_TYPE (right) == AOP_LIT)
7262 bytelit = (int)((lit >> (offset * 8)) & 0x0FFL);
7263 if (bytelit == 0x00L)
7265 aopPut (AOP (result),
7266 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7270 else if (bytelit == 0x0FF)
7272 /* dummy read of volatile operand */
7273 if (isOperandVolatile (left, FALSE))
7274 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7275 aopPut (AOP (result), "#0xFF", offset);
7278 D (emitcode (";", "better literal OR."););
7279 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7280 emitcode ("orl", "a, %s",
7281 aopGet (AOP (right), offset,
7282 FALSE, FALSE, DP2_RESULT_REG));
7287 // faster than result <- left, anl result,right
7288 // and better if result is SFR
7289 if (AOP_TYPE (left) == AOP_ACC)
7291 emitcode ("orl", "a,%s",
7292 aopGet (AOP (right), offset,
7293 FALSE, FALSE, DP2_RESULT_REG));
7297 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7299 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7301 emitcode("mov", "b,a");
7305 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7306 emitcode ("orl", "a,%s", rOp);
7309 aopPut (AOP (result), "a", offset);
7311 _endLazyDPSEvaluation();
7316 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7317 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7318 freeAsmop (result, NULL, ic, TRUE);
7321 /*-----------------------------------------------------------------*/
7322 /* genXor - code for xclusive or */
7323 /*-----------------------------------------------------------------*/
7325 genXor (iCode * ic, iCode * ifx)
7327 operand *left, *right, *result;
7328 int size, offset = 0;
7329 unsigned long lit = 0L;
7333 D (emitcode (";", "genXor "););
7335 AOP_OP_3_NOFATAL (ic, pushResult);
7336 AOP_SET_LOCALS (ic);
7340 genFarFarLogicOp(ic, "xrl");
7345 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7347 AOP_TYPE (left), AOP_TYPE (right));
7348 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7350 AOP_SIZE (left), AOP_SIZE (right));
7353 /* if left is a literal & right is not ||
7354 if left needs acc & right does not */
7355 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7356 #ifdef LOGIC_OPS_BROKEN
7357 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
7361 operand *tmp = right;
7366 /* if result = right then exchange them */
7367 if (sameRegs (AOP (result), AOP (right)))
7369 operand *tmp = right;
7374 /* if right is bit then exchange them */
7375 if (AOP_TYPE (right) == AOP_CRY &&
7376 AOP_TYPE (left) != AOP_CRY)
7378 operand *tmp = right;
7382 if (AOP_TYPE (right) == AOP_LIT)
7383 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7385 size = AOP_SIZE (result);
7389 if (AOP_TYPE (left) == AOP_CRY)
7391 if (AOP_TYPE (right) == AOP_LIT)
7393 // c = bit & literal;
7396 // lit>>1 != 0 => result = 1
7397 if (AOP_TYPE (result) == AOP_CRY)
7400 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7402 continueIfTrue (ifx);
7405 emitcode ("setb", "c");
7412 // lit == 0, result = left
7413 if (size && sameRegs (AOP (result), AOP (left)))
7415 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7419 // lit == 1, result = not(left)
7420 if (size && sameRegs (AOP (result), AOP (left)))
7422 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7427 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7428 emitcode ("cpl", "c");
7437 symbol *tlbl = newiTempLabel (NULL);
7438 if (AOP_TYPE (right) == AOP_CRY)
7441 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7445 int sizer = AOP_SIZE (right);
7447 // if val>>1 != 0, result = 1
7448 emitcode ("setb", "c");
7451 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
7453 // test the msb of the lsb
7454 emitcode ("anl", "a,#!constbyte",0xfe);
7455 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7459 emitcode ("rrc", "a");
7461 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7462 emitcode ("cpl", "c");
7463 emitcode ("", "!tlabeldef", (tlbl->key + 100));
7470 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7471 genIfxJump (ifx, "c");
7475 /* if left is same as result */
7476 if (sameRegs (AOP (result), AOP (left)))
7478 for (; size--; offset++)
7480 if (AOP_TYPE (right) == AOP_LIT)
7482 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7483 if (bytelit == 0x00L)
7485 /* dummy read of volatile operand */
7486 if (isOperandVolatile (left, FALSE))
7487 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7491 else if (IS_AOP_PREG (left))
7493 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7494 emitcode ("xrl", "a,%s",
7495 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7496 aopPut (AOP (result), "a", offset);
7500 emitcode ("xrl", "%s,%s",
7501 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7502 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7507 if (AOP_TYPE (left) == AOP_ACC)
7508 emitcode ("xrl", "a,%s",
7509 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7512 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7513 if (IS_AOP_PREG (left))
7515 emitcode ("xrl", "a,%s",
7516 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7517 aopPut (AOP (result), "a", offset);
7520 emitcode ("xrl", "%s,a",
7521 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7528 // left & result in different registers
7529 if (AOP_TYPE (result) == AOP_CRY)
7532 // if(size), result in bit
7533 // if(!size && ifx), conditional oper: if(left ^ right)
7534 symbol *tlbl = newiTempLabel (NULL);
7535 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7538 emitcode ("setb", "c");
7541 if ((AOP_TYPE (right) == AOP_LIT) &&
7542 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7544 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7548 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7549 emitcode ("xrl", "a,%s",
7550 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7552 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7553 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7555 emitcode("mov", "b,a");
7559 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7560 emitcode ("xrl", "a,%s", rOp);
7563 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7569 emitcode ("", "!tlabeldef", tlbl->key + 100);
7573 jmpTrueOrFalse (ifx, tlbl);
7577 for (; (size--); offset++)
7580 // result = left & right
7581 if (AOP_TYPE (right) == AOP_LIT)
7583 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7585 aopPut (AOP (result),
7586 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7590 D (emitcode (";", "better literal XOR."););
7591 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7592 emitcode ("xrl", "a, %s",
7593 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7597 // faster than result <- left, anl result,right
7598 // and better if result is SFR
7599 if (AOP_TYPE (left) == AOP_ACC)
7601 emitcode ("xrl", "a,%s",
7602 aopGet (AOP (right), offset,
7603 FALSE, FALSE, DP2_RESULT_REG));
7607 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7608 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7610 emitcode("mov", "b,a");
7614 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7615 emitcode ("xrl", "a,%s", rOp);
7618 aopPut (AOP (result), "a", offset);
7625 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7626 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7627 freeAsmop (result, NULL, ic, TRUE);
7630 /*-----------------------------------------------------------------*/
7631 /* genInline - write the inline code out */
7632 /*-----------------------------------------------------------------*/
7634 genInline (iCode * ic)
7636 char *buffer, *bp, *bp1;
7638 D (emitcode (";", "genInline "); );
7640 _G.inLine += (!options.asmpeep);
7642 buffer = Safe_strdup(IC_INLINE(ic));
7646 /* emit each line as a code */
7671 /* emitcode("",buffer); */
7672 _G.inLine -= (!options.asmpeep);
7675 /*-----------------------------------------------------------------*/
7676 /* genRRC - rotate right with carry */
7677 /*-----------------------------------------------------------------*/
7681 operand *left, *result;
7684 D (emitcode (";", "genRRC "););
7686 /* rotate right with carry */
7687 left = IC_LEFT (ic);
7688 result = IC_RESULT (ic);
7689 aopOp (left, ic, FALSE, FALSE);
7690 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7692 /* move it to the result */
7693 size = AOP_SIZE (result);
7697 _startLazyDPSEvaluation ();
7700 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7701 emitcode ("rrc", "a");
7702 if (AOP_SIZE (result) > 1)
7703 aopPut (AOP (result), "a", offset--);
7705 _endLazyDPSEvaluation ();
7707 /* now we need to put the carry into the
7708 highest order byte of the result */
7709 if (AOP_SIZE (result) > 1)
7711 MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7713 emitcode ("mov", "acc.7,c");
7714 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7715 freeAsmop (left, NULL, ic, TRUE);
7716 freeAsmop (result, NULL, ic, TRUE);
7719 /*-----------------------------------------------------------------*/
7720 /* genRLC - generate code for rotate left with carry */
7721 /*-----------------------------------------------------------------*/
7725 operand *left, *result;
7729 D (emitcode (";", "genRLC "););
7731 /* rotate right with carry */
7732 left = IC_LEFT (ic);
7733 result = IC_RESULT (ic);
7734 aopOp (left, ic, FALSE, FALSE);
7735 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7737 /* move it to the result */
7738 size = AOP_SIZE (result);
7742 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7744 emitcode ("add", "a,acc");
7745 if (AOP_SIZE (result) > 1)
7747 aopPut (AOP (result), "a", offset++);
7750 _startLazyDPSEvaluation ();
7753 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7755 emitcode ("rlc", "a");
7756 if (AOP_SIZE (result) > 1)
7757 aopPut (AOP (result), "a", offset++);
7759 _endLazyDPSEvaluation ();
7761 /* now we need to put the carry into the
7762 highest order byte of the result */
7763 if (AOP_SIZE (result) > 1)
7765 l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7768 emitcode ("mov", "acc.0,c");
7769 aopPut (AOP (result), "a", 0);
7770 freeAsmop (left, NULL, ic, TRUE);
7771 freeAsmop (result, NULL, ic, TRUE);
7774 /*-----------------------------------------------------------------*/
7775 /* genGetHbit - generates code get highest order bit */
7776 /*-----------------------------------------------------------------*/
7778 genGetHbit (iCode * ic)
7780 operand *left, *result;
7781 left = IC_LEFT (ic);
7782 result = IC_RESULT (ic);
7783 aopOp (left, ic, FALSE, FALSE);
7784 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7786 D (emitcode (";", "genGetHbit "););
7788 /* get the highest order byte into a */
7789 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7790 if (AOP_TYPE (result) == AOP_CRY)
7792 emitcode ("rlc", "a");
7797 emitcode ("rl", "a");
7798 emitcode ("anl", "a,#1");
7803 freeAsmop (left, NULL, ic, TRUE);
7804 freeAsmop (result, NULL, ic, TRUE);
7807 /*-----------------------------------------------------------------*/
7808 /* genSwap - generates code to swap nibbles or bytes */
7809 /*-----------------------------------------------------------------*/
7811 genSwap (iCode * ic)
7813 operand *left, *result;
7815 D(emitcode ("; genSwap",""));
7817 left = IC_LEFT (ic);
7818 result = IC_RESULT (ic);
7819 aopOp (left, ic, FALSE, FALSE);
7820 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7822 _startLazyDPSEvaluation ();
7823 switch (AOP_SIZE (left))
7825 case 1: /* swap nibbles in byte */
7826 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7827 emitcode ("swap", "a");
7828 aopPut (AOP (result), "a", 0);
7830 case 2: /* swap bytes in word */
7831 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7833 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7834 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7835 aopPut (AOP (result), "a", 1);
7837 else if (operandsEqu (left, result))
7840 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7841 if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
7843 emitcode ("mov", "b,a");
7847 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7848 aopPut (AOP (result), reg, 1);
7853 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7854 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE, NULL), 1);
7858 wassertl(FALSE, "unsupported SWAP operand size");
7860 _endLazyDPSEvaluation ();
7862 freeAsmop (left, NULL, ic, TRUE);
7863 freeAsmop (result, NULL, ic, TRUE);
7866 /*-----------------------------------------------------------------*/
7867 /* AccRol - rotate left accumulator by known count */
7868 /*-----------------------------------------------------------------*/
7870 AccRol (int shCount)
7872 shCount &= 0x0007; // shCount : 0..7
7879 emitcode ("rl", "a");
7882 emitcode ("rl", "a");
7883 emitcode ("rl", "a");
7886 emitcode ("swap", "a");
7887 emitcode ("rr", "a");
7890 emitcode ("swap", "a");
7893 emitcode ("swap", "a");
7894 emitcode ("rl", "a");
7897 emitcode ("rr", "a");
7898 emitcode ("rr", "a");
7901 emitcode ("rr", "a");
7906 /*-----------------------------------------------------------------*/
7907 /* AccLsh - left shift accumulator by known count */
7908 /*-----------------------------------------------------------------*/
7910 AccLsh (int shCount)
7915 emitcode ("add", "a,acc");
7916 else if (shCount == 2)
7918 emitcode ("add", "a,acc");
7919 emitcode ("add", "a,acc");
7923 /* rotate left accumulator */
7925 /* and kill the lower order bits */
7926 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7931 /*-----------------------------------------------------------------*/
7932 /* AccRsh - right shift accumulator by known count */
7933 /*-----------------------------------------------------------------*/
7935 AccRsh (int shCount)
7942 emitcode ("rrc", "a");
7946 /* rotate right accumulator */
7947 AccRol (8 - shCount);
7948 /* and kill the higher order bits */
7949 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7954 #ifdef BETTER_LITERAL_SHIFT
7955 /*-----------------------------------------------------------------*/
7956 /* AccSRsh - signed right shift accumulator by known count */
7957 /*-----------------------------------------------------------------*/
7959 AccSRsh (int shCount)
7966 emitcode ("mov", "c,acc.7");
7967 emitcode ("rrc", "a");
7969 else if (shCount == 2)
7971 emitcode ("mov", "c,acc.7");
7972 emitcode ("rrc", "a");
7973 emitcode ("mov", "c,acc.7");
7974 emitcode ("rrc", "a");
7978 tlbl = newiTempLabel (NULL);
7979 /* rotate right accumulator */
7980 AccRol (8 - shCount);
7981 /* and kill the higher order bits */
7982 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7983 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7984 emitcode ("orl", "a,#!constbyte",
7985 (unsigned char) ~SRMask[shCount]);
7986 emitcode ("", "!tlabeldef", tlbl->key + 100);
7992 #ifdef BETTER_LITERAL_SHIFT
7993 /*-----------------------------------------------------------------*/
7994 /* shiftR1Left2Result - shift right one byte from left to result */
7995 /*-----------------------------------------------------------------*/
7997 shiftR1Left2Result (operand * left, int offl,
7998 operand * result, int offr,
7999 int shCount, int sign)
8001 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8002 /* shift right accumulator */
8007 aopPut (AOP (result), "a", offr);
8011 #ifdef BETTER_LITERAL_SHIFT
8012 /*-----------------------------------------------------------------*/
8013 /* shiftL1Left2Result - shift left one byte from left to result */
8014 /*-----------------------------------------------------------------*/
8016 shiftL1Left2Result (operand * left, int offl,
8017 operand * result, int offr, int shCount)
8019 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8020 /* shift left accumulator */
8022 aopPut (AOP (result), "a", offr);
8026 #ifdef BETTER_LITERAL_SHIFT
8027 /*-----------------------------------------------------------------*/
8028 /* movLeft2Result - move byte from left to result */
8029 /*-----------------------------------------------------------------*/
8031 movLeft2Result (operand * left, int offl,
8032 operand * result, int offr, int sign)
8035 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8037 l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
8039 if (*l == '@' && (IS_AOP_PREG (result)))
8041 emitcode ("mov", "a,%s", l);
8042 aopPut (AOP (result), "a", offr);
8048 aopPut (AOP (result), l, offr);
8052 /* MSB sign in acc.7 ! */
8053 if (getDataSize (left) == offl + 1)
8055 emitcode ("mov", "a,%s", l);
8056 aopPut (AOP (result), "a", offr);
8064 #ifdef BETTER_LITERAL_SHIFT
8065 /*-----------------------------------------------------------------*/
8066 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8067 /*-----------------------------------------------------------------*/
8071 emitcode ("rrc", "a");
8072 emitcode ("xch", "a,%s", x);
8073 emitcode ("rrc", "a");
8074 emitcode ("xch", "a,%s", x);
8078 #ifdef BETTER_LITERAL_SHIFT
8080 /*-----------------------------------------------------------------*/
8081 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8082 /*-----------------------------------------------------------------*/
8086 emitcode ("xch", "a,%s", x);
8087 emitcode ("rlc", "a");
8088 emitcode ("xch", "a,%s", x);
8089 emitcode ("rlc", "a");
8093 #ifdef BETTER_LITERAL_SHIFT
8094 /*-----------------------------------------------------------------*/
8095 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8096 /*-----------------------------------------------------------------*/
8100 emitcode ("xch", "a,%s", x);
8101 emitcode ("add", "a,acc");
8102 emitcode ("xch", "a,%s", x);
8103 emitcode ("rlc", "a");
8107 #ifdef BETTER_LITERAL_SHIFT
8108 /*-----------------------------------------------------------------*/
8109 /* AccAXLsh - left shift a:x by known count (0..7) */
8110 /*-----------------------------------------------------------------*/
8112 AccAXLsh (char *x, int shCount)
8127 case 5: // AAAAABBB:CCCCCDDD
8129 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8131 emitcode ("anl", "a,#!constbyte",
8132 SLMask[shCount]); // BBB00000:CCCCCDDD
8134 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8136 AccRol (shCount); // DDDCCCCC:BBB00000
8138 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8140 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8142 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8144 emitcode ("anl", "a,#!constbyte",
8145 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8147 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8149 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8152 case 6: // AAAAAABB:CCCCCCDD
8153 emitcode ("anl", "a,#!constbyte",
8154 SRMask[shCount]); // 000000BB:CCCCCCDD
8155 emitcode ("mov", "c,acc.0"); // c = B
8156 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8158 AccAXRrl1 (x); // BCCCCCCD:D000000B
8159 AccAXRrl1 (x); // BBCCCCCC:DD000000
8161 emitcode("rrc","a");
8162 emitcode("xch","a,%s", x);
8163 emitcode("rrc","a");
8164 emitcode("mov","c,acc.0"); //<< get correct bit
8165 emitcode("xch","a,%s", x);
8167 emitcode("rrc","a");
8168 emitcode("xch","a,%s", x);
8169 emitcode("rrc","a");
8170 emitcode("xch","a,%s", x);
8173 case 7: // a:x <<= 7
8175 emitcode ("anl", "a,#!constbyte",
8176 SRMask[shCount]); // 0000000B:CCCCCCCD
8178 emitcode ("mov", "c,acc.0"); // c = B
8180 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8182 AccAXRrl1 (x); // BCCCCCCC:D0000000
8191 #ifdef BETTER_LITERAL_SHIFT
8193 /*-----------------------------------------------------------------*/
8194 /* AccAXRsh - right shift a:x known count (0..7) */
8195 /*-----------------------------------------------------------------*/
8197 AccAXRsh (char *x, int shCount)
8205 AccAXRrl1 (x); // 0->a:x
8210 AccAXRrl1 (x); // 0->a:x
8213 AccAXRrl1 (x); // 0->a:x
8218 case 5: // AAAAABBB:CCCCCDDD = a:x
8220 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8222 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8224 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8226 emitcode ("anl", "a,#!constbyte",
8227 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8229 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8231 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8233 emitcode ("anl", "a,#!constbyte",
8234 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8236 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8238 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8240 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8243 case 6: // AABBBBBB:CCDDDDDD
8245 emitcode ("mov", "c,acc.7");
8246 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8248 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8250 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8252 emitcode ("anl", "a,#!constbyte",
8253 SRMask[shCount]); // 000000AA:BBBBBBCC
8256 case 7: // ABBBBBBB:CDDDDDDD
8258 emitcode ("mov", "c,acc.7"); // c = A
8260 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8262 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8264 emitcode ("anl", "a,#!constbyte",
8265 SRMask[shCount]); // 0000000A:BBBBBBBC
8274 #ifdef BETTER_LITERAL_SHIFT
8275 /*-----------------------------------------------------------------*/
8276 /* AccAXRshS - right shift signed a:x known count (0..7) */
8277 /*-----------------------------------------------------------------*/
8279 AccAXRshS (char *x, int shCount)
8287 emitcode ("mov", "c,acc.7");
8288 AccAXRrl1 (x); // s->a:x
8292 emitcode ("mov", "c,acc.7");
8293 AccAXRrl1 (x); // s->a:x
8295 emitcode ("mov", "c,acc.7");
8296 AccAXRrl1 (x); // s->a:x
8301 case 5: // AAAAABBB:CCCCCDDD = a:x
8303 tlbl = newiTempLabel (NULL);
8304 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8306 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8308 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8310 emitcode ("anl", "a,#!constbyte",
8311 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8313 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8315 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8317 emitcode ("anl", "a,#!constbyte",
8318 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8320 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8322 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8324 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8326 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8327 emitcode ("orl", "a,#!constbyte",
8328 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8330 emitcode ("", "!tlabeldef", tlbl->key + 100);
8331 break; // SSSSAAAA:BBBCCCCC
8333 case 6: // AABBBBBB:CCDDDDDD
8335 tlbl = newiTempLabel (NULL);
8336 emitcode ("mov", "c,acc.7");
8337 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8339 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8341 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8343 emitcode ("anl", "a,#!constbyte",
8344 SRMask[shCount]); // 000000AA:BBBBBBCC
8346 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8347 emitcode ("orl", "a,#!constbyte",
8348 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8350 emitcode ("", "!tlabeldef", tlbl->key + 100);
8352 case 7: // ABBBBBBB:CDDDDDDD
8354 tlbl = newiTempLabel (NULL);
8355 emitcode ("mov", "c,acc.7"); // c = A
8357 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8359 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8361 emitcode ("anl", "a,#!constbyte",
8362 SRMask[shCount]); // 0000000A:BBBBBBBC
8364 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8365 emitcode ("orl", "a,#!constbyte",
8366 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8368 emitcode ("", "!tlabeldef", tlbl->key + 100);
8376 #ifdef BETTER_LITERAL_SHIFT
8378 _loadLeftIntoAx(char **lsb,
8384 // Get the initial value from left into a pair of registers.
8385 // MSB must be in A, LSB can be any register.
8387 // If the result is held in registers, it is an optimization
8388 // if the LSB can be held in the register which will hold the,
8389 // result LSB since this saves us from having to copy it into
8390 // the result following AccAXLsh.
8392 // If the result is addressed indirectly, this is not a gain.
8393 if (AOP_NEEDSACC(result))
8397 _startLazyDPSEvaluation();
8398 if (AOP_TYPE(left) == AOP_DPTR2)
8401 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
8402 // get LSB in DP2_RESULT_REG.
8403 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
8404 assert(!strcmp(leftByte, DP2_RESULT_REG));
8408 // get LSB into DP2_RESULT_REG
8409 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
8410 if (strcmp(leftByte, DP2_RESULT_REG))
8413 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
8416 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
8417 assert(strcmp(leftByte, DP2_RESULT_REG));
8420 _endLazyDPSEvaluation();
8421 *lsb = DP2_RESULT_REG;
8425 if (sameRegs (AOP (result), AOP (left)) &&
8426 ((offl + MSB16) == offr))
8428 /* don't crash result[offr] */
8429 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
8430 emitcode ("xch", "a,%s",
8431 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
8435 movLeft2Result (left, offl, result, offr, 0);
8436 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
8438 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
8439 assert(strcmp(*lsb,"a"));
8444 _storeAxResults(char *lsb,
8448 _startLazyDPSEvaluation();
8449 if (AOP_NEEDSACC(result))
8451 /* We have to explicitly update the result LSB.
8453 emitcode("xch","a,%s", lsb);
8454 aopPut(AOP(result), "a", offr);
8455 emitcode("mov","a,%s", lsb);
8457 if (getDataSize (result) > 1)
8459 aopPut (AOP (result), "a", offr + MSB16);
8461 _endLazyDPSEvaluation();
8464 /*-----------------------------------------------------------------*/
8465 /* shiftL2Left2Result - shift left two bytes from left to result */
8466 /*-----------------------------------------------------------------*/
8468 shiftL2Left2Result (operand * left, int offl,
8469 operand * result, int offr, int shCount)
8473 _loadLeftIntoAx(&lsb, left, result, offl, offr);
8475 AccAXLsh (lsb, shCount);
8477 _storeAxResults(lsb, result, offr);
8481 #ifdef BETTER_LITERAL_SHIFT
8482 /*-----------------------------------------------------------------*/
8483 /* shiftR2Left2Result - shift right two bytes from left to result */
8484 /*-----------------------------------------------------------------*/
8486 shiftR2Left2Result (operand * left, int offl,
8487 operand * result, int offr,
8488 int shCount, int sign)
8492 _loadLeftIntoAx(&lsb, left, result, offl, offr);
8494 /* a:x >> shCount (x = lsb(result)) */
8497 AccAXRshS(lsb, shCount);
8501 AccAXRsh(lsb, shCount);
8504 _storeAxResults(lsb, result, offr);
8508 /*-----------------------------------------------------------------*/
8509 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8510 /*-----------------------------------------------------------------*/
8512 shiftLLeftOrResult (operand * left, int offl,
8513 operand * result, int offr, int shCount)
8515 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8516 /* shift left accumulator */
8518 /* or with result */
8519 emitcode ("orl", "a,%s",
8520 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8521 /* back to result */
8522 aopPut (AOP (result), "a", offr);
8527 /*-----------------------------------------------------------------*/
8528 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8529 /*-----------------------------------------------------------------*/
8531 shiftRLeftOrResult (operand * left, int offl,
8532 operand * result, int offr, int shCount)
8534 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8535 /* shift right accumulator */
8537 /* or with result */
8538 emitcode ("orl", "a,%s",
8539 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8540 /* back to result */
8541 aopPut (AOP (result), "a", offr);
8545 #ifdef BETTER_LITERAL_SHIFT
8546 /*-----------------------------------------------------------------*/
8547 /* genlshOne - left shift a one byte quantity by known count */
8548 /*-----------------------------------------------------------------*/
8550 genlshOne (operand * result, operand * left, int shCount)
8552 D (emitcode (";", "genlshOne "););
8553 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8557 #ifdef BETTER_LITERAL_SHIFT
8558 /*-----------------------------------------------------------------*/
8559 /* genlshTwo - left shift two bytes by known amount != 0 */
8560 /*-----------------------------------------------------------------*/
8562 genlshTwo (operand * result, operand * left, int shCount)
8566 D (emitcode (";", "genlshTwo "););
8568 size = getDataSize (result);
8570 /* if shCount >= 8 */
8575 _startLazyDPSEvaluation();
8581 _endLazyDPSEvaluation();
8582 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8583 aopPut (AOP (result), zero, LSB);
8587 movLeft2Result (left, LSB, result, MSB16, 0);
8588 aopPut (AOP (result), zero, LSB);
8589 _endLazyDPSEvaluation();
8594 aopPut (AOP (result), zero, LSB);
8595 _endLazyDPSEvaluation();
8599 /* 1 <= shCount <= 7 */
8604 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8608 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8616 /*-----------------------------------------------------------------*/
8617 /* shiftLLong - shift left one long from left to result */
8618 /* offl = LSB or MSB16 */
8619 /*-----------------------------------------------------------------*/
8621 shiftLLong (operand * left, operand * result, int offr)
8624 int size = AOP_SIZE (result);
8626 if (size >= LSB + offr)
8628 l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8630 emitcode ("add", "a,acc");
8631 if (sameRegs (AOP (left), AOP (result)) &&
8632 size >= MSB16 + offr && offr != LSB)
8633 emitcode ("xch", "a,%s",
8634 aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8636 aopPut (AOP (result), "a", LSB + offr);
8639 if (size >= MSB16 + offr)
8641 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8643 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8645 emitcode ("rlc", "a");
8646 if (sameRegs (AOP (left), AOP (result)) &&
8647 size >= MSB24 + offr && offr != LSB)
8648 emitcode ("xch", "a,%s",
8649 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8651 aopPut (AOP (result), "a", MSB16 + offr);
8654 if (size >= MSB24 + offr)
8656 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8658 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8660 emitcode ("rlc", "a");
8661 if (sameRegs (AOP (left), AOP (result)) &&
8662 size >= MSB32 + offr && offr != LSB)
8663 emitcode ("xch", "a,%s",
8664 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8666 aopPut (AOP (result), "a", MSB24 + offr);
8669 if (size > MSB32 + offr)
8671 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8673 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8675 emitcode ("rlc", "a");
8676 aopPut (AOP (result), "a", MSB32 + offr);
8679 aopPut (AOP (result), zero, LSB);
8685 /*-----------------------------------------------------------------*/
8686 /* genlshFour - shift four byte by a known amount != 0 */
8687 /*-----------------------------------------------------------------*/
8689 genlshFour (operand * result, operand * left, int shCount)
8693 D (emitcode (";", "genlshFour ");
8696 size = AOP_SIZE (result);
8698 /* if shifting more that 3 bytes */
8703 /* lowest order of left goes to the highest
8704 order of the destination */
8705 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8707 movLeft2Result (left, LSB, result, MSB32, 0);
8708 aopPut (AOP (result), zero, LSB);
8709 aopPut (AOP (result), zero, MSB16);
8710 aopPut (AOP (result), zero, MSB24);
8714 /* more than two bytes */
8715 else if (shCount >= 16)
8717 /* lower order two bytes goes to higher order two bytes */
8719 /* if some more remaining */
8721 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8724 movLeft2Result (left, MSB16, result, MSB32, 0);
8725 movLeft2Result (left, LSB, result, MSB24, 0);
8727 aopPut (AOP (result), zero, MSB16);
8728 aopPut (AOP (result), zero, LSB);
8732 /* if more than 1 byte */
8733 else if (shCount >= 8)
8735 /* lower order three bytes goes to higher order three bytes */
8740 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8742 movLeft2Result (left, LSB, result, MSB16, 0);
8748 movLeft2Result (left, MSB24, result, MSB32, 0);
8749 movLeft2Result (left, MSB16, result, MSB24, 0);
8750 movLeft2Result (left, LSB, result, MSB16, 0);
8751 aopPut (AOP (result), zero, LSB);
8753 else if (shCount == 1)
8754 shiftLLong (left, result, MSB16);
8757 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8758 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8759 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8760 aopPut (AOP (result), zero, LSB);
8765 /* 1 <= shCount <= 7 */
8766 else if (shCount <= 2)
8768 shiftLLong (left, result, LSB);
8770 shiftLLong (result, result, LSB);
8772 /* 3 <= shCount <= 7, optimize */
8775 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8776 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8777 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8782 #ifdef BETTER_LITERAL_SHIFT
8783 /*-----------------------------------------------------------------*/
8784 /* genLeftShiftLiteral - left shifting by known count */
8785 /*-----------------------------------------------------------------*/
8787 genLeftShiftLiteral (operand * left,
8792 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8795 size = getSize (operandType (result));
8797 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8799 /* We only handle certain easy cases so far. */
8801 && (shCount < (size * 8))
8805 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8809 freeAsmop (right, NULL, ic, TRUE);
8811 aopOp(left, ic, FALSE, FALSE);
8812 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8815 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8817 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8818 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8820 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8823 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8825 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8826 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8828 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8834 emitcode ("; shift left ", "result %d, left %d", size,
8838 /* I suppose that the left size >= result size */
8841 _startLazyDPSEvaluation();
8844 movLeft2Result (left, size, result, size, 0);
8846 _endLazyDPSEvaluation();
8848 else if (shCount >= (size * 8))
8850 _startLazyDPSEvaluation();
8853 aopPut (AOP (result), zero, size);
8855 _endLazyDPSEvaluation();
8862 genlshOne (result, left, shCount);
8866 genlshTwo (result, left, shCount);
8870 genlshFour (result, left, shCount);
8874 fprintf(stderr, "*** ack! mystery literal shift!\n");
8878 freeAsmop (left, NULL, ic, TRUE);
8879 freeAsmop (result, NULL, ic, TRUE);
8884 /*-----------------------------------------------------------------*/
8885 /* genLeftShift - generates code for left shifting */
8886 /*-----------------------------------------------------------------*/
8888 genLeftShift (iCode * ic)
8890 operand *left, *right, *result;
8893 symbol *tlbl, *tlbl1;
8895 D (emitcode (";", "genLeftShift "););
8897 right = IC_RIGHT (ic);
8898 left = IC_LEFT (ic);
8899 result = IC_RESULT (ic);
8901 aopOp (right, ic, FALSE, FALSE);
8904 #ifdef BETTER_LITERAL_SHIFT
8905 /* if the shift count is known then do it
8906 as efficiently as possible */
8907 if (AOP_TYPE (right) == AOP_LIT)
8909 if (genLeftShiftLiteral (left, right, result, ic))
8916 /* shift count is unknown then we have to form
8917 a loop get the loop count in B : Note: we take
8918 only the lower order byte since shifting
8919 more that 32 bits make no sense anyway, ( the
8920 largest size of an object can be only 32 bits ) */
8922 if (AOP_TYPE (right) == AOP_LIT)
8924 /* Really should be handled by genLeftShiftLiteral,
8925 * but since I'm too lazy to fix that today, at least we can make
8926 * some small improvement.
8928 emitcode("mov", "b,#!constbyte",
8929 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8933 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8934 emitcode ("inc", "b");
8936 freeAsmop (right, NULL, ic, TRUE);
8937 aopOp (left, ic, FALSE, FALSE);
8938 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8940 /* now move the left to the result if they are not the
8942 if (!sameRegs (AOP (left), AOP (result)) &&
8943 AOP_SIZE (result) > 1)
8946 size = AOP_SIZE (result);
8948 _startLazyDPSEvaluation ();
8951 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8952 if (*l == '@' && (IS_AOP_PREG (result)))
8955 emitcode ("mov", "a,%s", l);
8956 aopPut (AOP (result), "a", offset);
8959 aopPut (AOP (result), l, offset);
8962 _endLazyDPSEvaluation ();
8965 tlbl = newiTempLabel (NULL);
8966 size = AOP_SIZE (result);
8968 tlbl1 = newiTempLabel (NULL);
8970 /* if it is only one byte then */
8973 symbol *tlbl1 = newiTempLabel (NULL);
8975 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8976 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8977 emitcode ("", "!tlabeldef", tlbl->key + 100);
8978 emitcode ("add", "a,acc");
8979 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8980 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8981 aopPut (AOP (result), "a", 0);
8985 reAdjustPreg (AOP (result));
8987 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8988 emitcode ("", "!tlabeldef", tlbl->key + 100);
8989 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8990 emitcode ("add", "a,acc");
8991 aopPut (AOP (result), "a", offset++);
8992 _startLazyDPSEvaluation ();
8995 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8996 emitcode ("rlc", "a");
8997 aopPut (AOP (result), "a", offset++);
8999 _endLazyDPSEvaluation ();
9000 reAdjustPreg (AOP (result));
9002 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9003 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9005 freeAsmop (left, NULL, ic, TRUE);
9006 freeAsmop (result, NULL, ic, TRUE);
9009 #ifdef BETTER_LITERAL_SHIFT
9010 /*-----------------------------------------------------------------*/
9011 /* genrshOne - right shift a one byte quantity by known count */
9012 /*-----------------------------------------------------------------*/
9014 genrshOne (operand * result, operand * left,
9015 int shCount, int sign)
9017 D (emitcode (";", "genrshOne"););
9018 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9022 #ifdef BETTER_LITERAL_SHIFT
9023 /*-----------------------------------------------------------------*/
9024 /* genrshTwo - right shift two bytes by known amount != 0 */
9025 /*-----------------------------------------------------------------*/
9027 genrshTwo (operand * result, operand * left,
9028 int shCount, int sign)
9030 D (emitcode (";", "genrshTwo"););
9032 /* if shCount >= 8 */
9036 _startLazyDPSEvaluation();
9039 shiftR1Left2Result (left, MSB16, result, LSB,
9044 movLeft2Result (left, MSB16, result, LSB, sign);
9046 addSign (result, MSB16, sign);
9047 _endLazyDPSEvaluation();
9050 /* 1 <= shCount <= 7 */
9053 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9058 /*-----------------------------------------------------------------*/
9059 /* shiftRLong - shift right one long from left to result */
9060 /* offl = LSB or MSB16 */
9061 /*-----------------------------------------------------------------*/
9063 shiftRLong (operand * left, int offl,
9064 operand * result, int sign)
9066 int isSameRegs=sameRegs(AOP(left),AOP(result));
9068 if (isSameRegs && offl>1) {
9069 // we are in big trouble, but this shouldn't happen
9070 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9073 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
9078 emitcode ("rlc", "a");
9079 emitcode ("subb", "a,acc");
9080 emitcode ("xch", "a,%s",
9081 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
9083 aopPut (AOP(result), zero, MSB32);
9088 emitcode ("clr", "c");
9090 emitcode ("mov", "c,acc.7");
9093 emitcode ("rrc", "a");
9095 if (isSameRegs && offl==MSB16) {
9097 "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
9099 aopPut (AOP (result), "a", MSB32);
9100 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
9103 emitcode ("rrc", "a");
9104 if (isSameRegs && offl==1) {
9105 emitcode ("xch", "a,%s",
9106 aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
9108 aopPut (AOP (result), "a", MSB24);
9109 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
9111 emitcode ("rrc", "a");
9112 aopPut (AOP (result), "a", MSB16 - offl);
9116 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
9117 emitcode ("rrc", "a");
9118 aopPut (AOP (result), "a", LSB);
9122 /*-----------------------------------------------------------------*/
9123 /* genrshFour - shift four byte by a known amount != 0 */
9124 /*-----------------------------------------------------------------*/
9126 genrshFour (operand * result, operand * left,
9127 int shCount, int sign)
9129 D (emitcode (";", "genrshFour"););
9131 /* if shifting more that 3 bytes */
9135 _startLazyDPSEvaluation();
9137 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9139 movLeft2Result (left, MSB32, result, LSB, sign);
9140 addSign (result, MSB16, sign);
9141 _endLazyDPSEvaluation();
9143 else if (shCount >= 16)
9146 _startLazyDPSEvaluation();
9148 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9151 movLeft2Result (left, MSB24, result, LSB, 0);
9152 movLeft2Result (left, MSB32, result, MSB16, sign);
9154 addSign (result, MSB24, sign);
9155 _endLazyDPSEvaluation();
9157 else if (shCount >= 8)
9160 _startLazyDPSEvaluation();
9163 shiftRLong (left, MSB16, result, sign);
9165 else if (shCount == 0)
9167 movLeft2Result (left, MSB16, result, LSB, 0);
9168 movLeft2Result (left, MSB24, result, MSB16, 0);
9169 movLeft2Result (left, MSB32, result, MSB24, sign);
9170 addSign (result, MSB32, sign);
9174 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9175 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9176 /* the last shift is signed */
9177 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9178 addSign (result, MSB32, sign);
9180 _endLazyDPSEvaluation();
9184 /* 1 <= shCount <= 7 */
9187 shiftRLong (left, LSB, result, sign);
9189 shiftRLong (result, LSB, result, sign);
9193 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9194 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9195 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9200 #ifdef BETTER_LITERAL_SHIFT
9201 /*-----------------------------------------------------------------*/
9202 /* genRightShiftLiteral - right shifting by known count */
9203 /*-----------------------------------------------------------------*/
9205 genRightShiftLiteral (operand * left,
9211 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9214 size = getSize (operandType (result));
9216 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
9218 /* We only handle certain easy cases so far. */
9220 && (shCount < (size * 8))
9225 D(emitcode (";", "genRightShiftLiteral wimping out"););
9229 freeAsmop (right, NULL, ic, TRUE);
9231 aopOp (left, ic, FALSE, FALSE);
9232 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9235 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9239 /* test the LEFT size !!! */
9241 /* I suppose that the left size >= result size */
9244 size = getDataSize (result);
9245 _startLazyDPSEvaluation();
9248 movLeft2Result (left, size, result, size, 0);
9250 _endLazyDPSEvaluation();
9252 else if (shCount >= (size * 8))
9256 /* get sign in acc.7 */
9257 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
9259 addSign (result, LSB, sign);
9266 genrshOne (result, left, shCount, sign);
9270 genrshTwo (result, left, shCount, sign);
9274 genrshFour (result, left, shCount, sign);
9281 freeAsmop (left, NULL, ic, TRUE);
9282 freeAsmop (result, NULL, ic, TRUE);
9288 /*-----------------------------------------------------------------*/
9289 /* genSignedRightShift - right shift of signed number */
9290 /*-----------------------------------------------------------------*/
9292 genSignedRightShift (iCode * ic)
9294 operand *right, *left, *result;
9297 symbol *tlbl, *tlbl1;
9299 D (emitcode (";", "genSignedRightShift "););
9301 /* we do it the hard way put the shift count in b
9302 and loop thru preserving the sign */
9304 right = IC_RIGHT (ic);
9305 left = IC_LEFT (ic);
9306 result = IC_RESULT (ic);
9308 aopOp (right, ic, FALSE, FALSE);
9310 #ifdef BETTER_LITERAL_SHIFT
9311 if (AOP_TYPE (right) == AOP_LIT)
9313 if (genRightShiftLiteral (left, right, result, ic, 1))
9319 /* shift count is unknown then we have to form
9320 a loop get the loop count in B : Note: we take
9321 only the lower order byte since shifting
9322 more that 32 bits make no sense anyway, ( the
9323 largest size of an object can be only 32 bits ) */
9325 if (AOP_TYPE (right) == AOP_LIT)
9327 /* Really should be handled by genRightShiftLiteral,
9328 * but since I'm too lazy to fix that today, at least we can make
9329 * some small improvement.
9331 emitcode("mov", "b,#!constbyte",
9332 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9336 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9337 emitcode ("inc", "b");
9339 freeAsmop (right, NULL, ic, TRUE);
9340 aopOp (left, ic, FALSE, FALSE);
9341 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9343 /* now move the left to the result if they are not the
9345 if (!sameRegs (AOP (left), AOP (result)) &&
9346 AOP_SIZE (result) > 1)
9349 size = AOP_SIZE (result);
9351 _startLazyDPSEvaluation ();
9354 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9355 if (*l == '@' && IS_AOP_PREG (result))
9358 emitcode ("mov", "a,%s", l);
9359 aopPut (AOP (result), "a", offset);
9362 aopPut (AOP (result), l, offset);
9365 _endLazyDPSEvaluation ();
9368 /* mov the highest order bit to OVR */
9369 tlbl = newiTempLabel (NULL);
9370 tlbl1 = newiTempLabel (NULL);
9372 size = AOP_SIZE (result);
9374 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
9375 emitcode ("rlc", "a");
9376 emitcode ("mov", "ov,c");
9377 /* if it is only one byte then */
9380 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9381 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9382 emitcode ("", "!tlabeldef", tlbl->key + 100);
9383 emitcode ("mov", "c,ov");
9384 emitcode ("rrc", "a");
9385 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9386 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9387 aopPut (AOP (result), "a", 0);
9391 reAdjustPreg (AOP (result));
9392 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9393 emitcode ("", "!tlabeldef", tlbl->key + 100);
9394 emitcode ("mov", "c,ov");
9395 _startLazyDPSEvaluation ();
9398 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9399 emitcode ("rrc", "a");
9400 aopPut (AOP (result), "a", offset--);
9402 _endLazyDPSEvaluation ();
9403 reAdjustPreg (AOP (result));
9404 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9405 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9408 freeAsmop (left, NULL, ic, TRUE);
9409 freeAsmop (result, NULL, ic, TRUE);
9412 /*-----------------------------------------------------------------*/
9413 /* genRightShift - generate code for right shifting */
9414 /*-----------------------------------------------------------------*/
9416 genRightShift (iCode * ic)
9418 operand *right, *left, *result;
9422 symbol *tlbl, *tlbl1;
9424 D (emitcode (";", "genRightShift "););
9426 /* if signed then we do it the hard way preserve the
9427 sign bit moving it inwards */
9428 letype = getSpec (operandType (IC_LEFT (ic)));
9430 if (!SPEC_USIGN (letype))
9432 genSignedRightShift (ic);
9436 /* signed & unsigned types are treated the same : i.e. the
9437 signed is NOT propagated inwards : quoting from the
9438 ANSI - standard : "for E1 >> E2, is equivalent to division
9439 by 2**E2 if unsigned or if it has a non-negative value,
9440 otherwise the result is implementation defined ", MY definition
9441 is that the sign does not get propagated */
9443 right = IC_RIGHT (ic);
9444 left = IC_LEFT (ic);
9445 result = IC_RESULT (ic);
9447 aopOp (right, ic, FALSE, FALSE);
9449 #ifdef BETTER_LITERAL_SHIFT
9450 /* if the shift count is known then do it
9451 as efficiently as possible */
9452 if (AOP_TYPE (right) == AOP_LIT)
9454 if (genRightShiftLiteral (left, right, result, ic, 0))
9461 /* shift count is unknown then we have to form
9462 a loop get the loop count in B : Note: we take
9463 only the lower order byte since shifting
9464 more that 32 bits make no sense anyway, ( the
9465 largest size of an object can be only 32 bits ) */
9467 if (AOP_TYPE (right) == AOP_LIT)
9469 /* Really should be handled by genRightShiftLiteral,
9470 * but since I'm too lazy to fix that today, at least we can make
9471 * some small improvement.
9473 emitcode("mov", "b,#!constbyte",
9474 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9478 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9479 emitcode ("inc", "b");
9481 freeAsmop (right, NULL, ic, TRUE);
9482 aopOp (left, ic, FALSE, FALSE);
9483 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9485 /* now move the left to the result if they are not the
9487 if (!sameRegs (AOP (left), AOP (result)) &&
9488 AOP_SIZE (result) > 1)
9491 size = AOP_SIZE (result);
9493 _startLazyDPSEvaluation ();
9496 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9497 if (*l == '@' && IS_AOP_PREG (result))
9500 emitcode ("mov", "a,%s", l);
9501 aopPut (AOP (result), "a", offset);
9504 aopPut (AOP (result), l, offset);
9507 _endLazyDPSEvaluation ();
9510 tlbl = newiTempLabel (NULL);
9511 tlbl1 = newiTempLabel (NULL);
9512 size = AOP_SIZE (result);
9515 /* if it is only one byte then */
9518 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9519 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9520 emitcode ("", "!tlabeldef", tlbl->key + 100);
9522 emitcode ("rrc", "a");
9523 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9524 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9525 aopPut (AOP (result), "a", 0);
9529 reAdjustPreg (AOP (result));
9530 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9531 emitcode ("", "!tlabeldef", tlbl->key + 100);
9533 _startLazyDPSEvaluation ();
9536 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9537 emitcode ("rrc", "a");
9538 aopPut (AOP (result), "a", offset--);
9540 _endLazyDPSEvaluation ();
9541 reAdjustPreg (AOP (result));
9543 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9544 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9547 freeAsmop (left, NULL, ic, TRUE);
9548 freeAsmop (result, NULL, ic, TRUE);
9552 /*-----------------------------------------------------------------*/
9553 /* emitPtrByteGet - emits code to get a byte into A through a */
9554 /* pointer register (R0, R1, or DPTR). The */
9555 /* original value of A can be preserved in B. */
9556 /*-----------------------------------------------------------------*/
9558 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9565 emitcode ("mov", "b,a");
9566 emitcode ("mov", "a,@%s", rname);
9571 emitcode ("mov", "b,a");
9572 emitcode ("movx", "a,@%s", rname);
9577 emitcode ("mov", "b,a");
9578 emitcode ("movx", "a,@dptr");
9583 emitcode ("mov", "b,a");
9584 emitcode ("clr", "a");
9585 emitcode ("movc", "a,@a+dptr");
9591 emitcode ("push", "b");
9592 emitcode ("push", "acc");
9594 emitcode ("lcall", "__gptrget");
9596 emitcode ("pop", "b");
9601 /*-----------------------------------------------------------------*/
9602 /* emitPtrByteSet - emits code to set a byte from src through a */
9603 /* pointer register (R0, R1, or DPTR). */
9604 /*-----------------------------------------------------------------*/
9606 emitPtrByteSet (char *rname, int p_type, char *src)
9615 emitcode ("mov", "@%s,a", rname);
9618 emitcode ("mov", "@%s,%s", rname, src);
9623 emitcode ("movx", "@%s,a", rname);
9628 emitcode ("movx", "@dptr,a");
9633 emitcode ("lcall", "__gptrput");
9638 /*-----------------------------------------------------------------*/
9639 /* genUnpackBits - generates code for unpacking bits */
9640 /*-----------------------------------------------------------------*/
9642 genUnpackBits (operand * result, char *rname, int ptype)
9644 int offset = 0; /* result byte offset */
9645 int rsize; /* result size */
9646 int rlen = 0; /* remaining bitfield length */
9647 sym_link *etype; /* bitfield type information */
9648 int blen; /* bitfield length */
9649 int bstr; /* bitfield starting bit within byte */
9651 D(emitcode ("; genUnpackBits",""));
9653 etype = getSpec (operandType (result));
9654 rsize = getSize (operandType (result));
9655 blen = SPEC_BLEN (etype);
9656 bstr = SPEC_BSTR (etype);
9658 /* If the bitfield length is less than a byte */
9661 emitPtrByteGet (rname, ptype, FALSE);
9663 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9664 aopPut (AOP (result), "a", offset++);
9668 /* Bit field did not fit in a byte. Copy all
9669 but the partial byte at the end. */
9670 for (rlen=blen;rlen>=8;rlen-=8)
9672 emitPtrByteGet (rname, ptype, FALSE);
9673 aopPut (AOP (result), "a", offset++);
9675 emitcode ("inc", "%s", rname);
9678 /* Handle the partial byte at the end */
9681 emitPtrByteGet (rname, ptype, FALSE);
9682 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9683 aopPut (AOP (result), "a", offset++);
9691 aopPut (AOP (result), zero, offset++);
9696 /*-----------------------------------------------------------------*/
9697 /* genDataPointerGet - generates code when ptr offset is known */
9698 /*-----------------------------------------------------------------*/
9700 genDataPointerGet (operand * left,
9706 int size, offset = 0;
9707 aopOp (result, ic, TRUE, FALSE);
9709 /* get the string representation of the name */
9710 l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9711 size = AOP_SIZE (result);
9712 _startLazyDPSEvaluation ();
9717 SNPRINTF (buff, sizeof(buff),
9718 "(%s + %d)", l + 1, offset);
9722 SNPRINTF (buff, sizeof(buff),
9725 aopPut (AOP (result), buff, offset++);
9727 _endLazyDPSEvaluation ();
9729 freeAsmop (left, NULL, ic, TRUE);
9730 freeAsmop (result, NULL, ic, TRUE);
9733 /*-----------------------------------------------------------------*/
9734 /* genNearPointerGet - emitcode for near pointer fetch */
9735 /*-----------------------------------------------------------------*/
9737 genNearPointerGet (operand * left,
9745 sym_link *rtype, *retype, *letype;
9746 sym_link *ltype = operandType (left);
9749 rtype = operandType (result);
9750 retype = getSpec (rtype);
9751 letype = getSpec (ltype);
9753 aopOp (left, ic, FALSE, FALSE);
9755 /* if left is rematerialisable and
9756 result is not bitfield variable type and
9757 the left is pointer to data space i.e
9758 lower 128 bytes of space */
9759 if (AOP_TYPE (left) == AOP_IMMD &&
9760 !IS_BITFIELD (retype) &&
9761 !IS_BITFIELD (letype) &&
9762 DCL_TYPE (ltype) == POINTER)
9764 genDataPointerGet (left, result, ic);
9768 /* if the value is already in a pointer register
9769 then don't need anything more */
9770 if (!AOP_INPREG (AOP (left)))
9772 /* otherwise get a free pointer register */
9774 preg = getFreePtr (ic, &aop, FALSE);
9775 emitcode ("mov", "%s,%s",
9777 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9781 rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9783 freeAsmop (left, NULL, ic, TRUE);
9784 aopOp (result, ic, FALSE, FALSE);
9786 /* if bitfield then unpack the bits */
9787 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9788 genUnpackBits (result, rname, POINTER);
9791 /* we have can just get the values */
9792 int size = AOP_SIZE (result);
9797 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9800 emitcode ("mov", "a,@%s", rname);
9801 aopPut (AOP (result), "a", offset);
9805 SNPRINTF (buff, sizeof(buff), "@%s", rname);
9806 aopPut (AOP (result), buff, offset);
9811 emitcode ("inc", "%s", rname);
9816 /* now some housekeeping stuff */
9819 /* we had to allocate for this iCode */
9820 if (pi) { /* post increment present */
9821 aopPut(AOP ( left ),rname,0);
9823 freeAsmop (NULL, aop, ic, TRUE);
9827 /* we did not allocate which means left
9828 already in a pointer register, then
9829 if size > 0 && this could be used again
9830 we have to point it back to where it
9832 if (AOP_SIZE (result) > 1 &&
9833 !OP_SYMBOL (left)->remat &&
9834 (OP_SYMBOL (left)->liveTo > ic->seq ||
9838 int size = AOP_SIZE (result) - 1;
9840 emitcode ("dec", "%s", rname);
9845 freeAsmop (result, NULL, ic, TRUE);
9846 if (pi) pi->generated = 1;
9849 /*-----------------------------------------------------------------*/
9850 /* genPagedPointerGet - emitcode for paged pointer fetch */
9851 /*-----------------------------------------------------------------*/
9853 genPagedPointerGet (operand * left,
9861 sym_link *rtype, *retype, *letype;
9863 rtype = operandType (result);
9864 retype = getSpec (rtype);
9865 letype = getSpec (operandType (left));
9866 aopOp (left, ic, FALSE, FALSE);
9868 /* if the value is already in a pointer register
9869 then don't need anything more */
9870 if (!AOP_INPREG (AOP (left)))
9872 /* otherwise get a free pointer register */
9874 preg = getFreePtr (ic, &aop, FALSE);
9875 emitcode ("mov", "%s,%s",
9877 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9881 rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9883 freeAsmop (left, NULL, ic, TRUE);
9884 aopOp (result, ic, FALSE, FALSE);
9886 /* if bitfield then unpack the bits */
9887 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9888 genUnpackBits (result, rname, PPOINTER);
9891 /* we have can just get the values */
9892 int size = AOP_SIZE (result);
9898 emitcode ("movx", "a,@%s", rname);
9899 aopPut (AOP (result), "a", offset);
9904 emitcode ("inc", "%s", rname);
9908 /* now some housekeeping stuff */
9911 /* we had to allocate for this iCode */
9912 if (pi) aopPut ( AOP (left), rname, 0);
9913 freeAsmop (NULL, aop, ic, TRUE);
9917 /* we did not allocate which means left
9918 already in a pointer register, then
9919 if size > 0 && this could be used again
9920 we have to point it back to where it
9922 if (AOP_SIZE (result) > 1 &&
9923 !OP_SYMBOL (left)->remat &&
9924 (OP_SYMBOL (left)->liveTo > ic->seq ||
9928 int size = AOP_SIZE (result) - 1;
9930 emitcode ("dec", "%s", rname);
9935 freeAsmop (result, NULL, ic, TRUE);
9936 if (pi) pi->generated = 1;
9939 /*-----------------------------------------------------------------*/
9940 /* genFarPointerGet - gget value from far space */
9941 /*-----------------------------------------------------------------*/
9943 genFarPointerGet (operand * left,
9944 operand * result, iCode * ic, iCode *pi)
9946 int size, offset, dopi=1;
9947 sym_link *retype = getSpec (operandType (result));
9948 sym_link *letype = getSpec (operandType (left));
9949 D (emitcode (";", "genFarPointerGet"););
9951 aopOp (left, ic, FALSE, FALSE);
9953 /* if the operand is already in dptr
9954 then we do nothing else we move the value to dptr */
9955 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9957 /* if this is remateriazable */
9958 if (AOP_TYPE (left) == AOP_IMMD)
9960 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9964 /* we need to get it byte by byte */
9965 _startLazyDPSEvaluation ();
9966 if (AOP_TYPE (left) != AOP_DPTR)
9968 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9969 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9970 if (options.model == MODEL_FLAT24)
9971 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9975 /* We need to generate a load to DPTR indirect through DPTR. */
9976 D (emitcode (";", "genFarPointerGet -- indirection special case."););
9977 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9978 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9979 if (options.model == MODEL_FLAT24)
9980 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9981 emitcode ("pop", "dph");
9982 emitcode ("pop", "dpl");
9985 _endLazyDPSEvaluation ();
9988 /* so dptr know contains the address */
9989 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9991 /* if bit then unpack */
9992 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9993 if (AOP_INDPTRn(left)) {
9994 genSetDPTR(AOP(left)->aopu.dptr);
9996 genUnpackBits (result, "dptr", FPOINTER);
9997 if (AOP_INDPTRn(left)) {
10002 size = AOP_SIZE (result);
10005 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10007 genSetDPTR(AOP(left)->aopu.dptr);
10008 emitcode ("movx", "a,@dptr");
10009 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10010 emitcode ("inc", "dptr");
10012 aopPut (AOP (result), "a", offset++);
10015 _startLazyDPSEvaluation ();
10017 if (AOP_INDPTRn(left)) {
10018 genSetDPTR(AOP(left)->aopu.dptr);
10024 emitcode ("movx", "a,@dptr");
10025 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10026 emitcode ("inc", "dptr");
10028 aopPut (AOP (result), "a", offset++);
10030 _endLazyDPSEvaluation ();
10033 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10034 if (!AOP_INDPTRn(left)) {
10035 _startLazyDPSEvaluation ();
10036 aopPut ( AOP (left), "dpl", 0);
10037 aopPut ( AOP (left), "dph", 1);
10038 if (options.model == MODEL_FLAT24)
10039 aopPut ( AOP (left), "dpx", 2);
10040 _endLazyDPSEvaluation ();
10043 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
10044 AOP_SIZE(result) > 1 &&
10046 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
10048 size = AOP_SIZE (result) - 1;
10049 if (AOP_INDPTRn(left)) {
10050 genSetDPTR(AOP(left)->aopu.dptr);
10052 while (size--) emitcode ("lcall","__decdptr");
10053 if (AOP_INDPTRn(left)) {
10058 freeAsmop (left, NULL, ic, TRUE);
10059 freeAsmop (result, NULL, ic, TRUE);
10062 /*-----------------------------------------------------------------*/
10063 /* genCodePointerGet - get value from code space */
10064 /*-----------------------------------------------------------------*/
10066 genCodePointerGet (operand * left,
10067 operand * result, iCode * ic, iCode *pi)
10069 int size, offset, dopi=1;
10070 sym_link *retype = getSpec (operandType (result));
10072 aopOp (left, ic, FALSE, FALSE);
10074 /* if the operand is already in dptr
10075 then we do nothing else we move the value to dptr */
10076 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
10078 /* if this is remateriazable */
10079 if (AOP_TYPE (left) == AOP_IMMD)
10081 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10084 { /* we need to get it byte by byte */
10085 _startLazyDPSEvaluation ();
10086 if (AOP_TYPE (left) != AOP_DPTR)
10088 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10089 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10090 if (options.model == MODEL_FLAT24)
10091 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10095 /* We need to generate a load to DPTR indirect through DPTR. */
10096 D (emitcode (";", "gencodePointerGet -- indirection special case."););
10097 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
10098 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
10099 if (options.model == MODEL_FLAT24)
10100 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10101 emitcode ("pop", "dph");
10102 emitcode ("pop", "dpl");
10105 _endLazyDPSEvaluation ();
10108 /* so dptr know contains the address */
10109 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10111 /* if bit then unpack */
10112 if (IS_BITFIELD (retype)) {
10113 if (AOP_INDPTRn(left)) {
10114 genSetDPTR(AOP(left)->aopu.dptr);
10116 genUnpackBits (result, "dptr", CPOINTER);
10117 if (AOP_INDPTRn(left)) {
10122 size = AOP_SIZE (result);
10124 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10126 genSetDPTR(AOP(left)->aopu.dptr);
10127 emitcode ("clr", "a");
10128 emitcode ("movc", "a,@a+dptr");
10129 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10130 emitcode ("inc", "dptr");
10132 aopPut (AOP (result), "a", offset++);
10135 _startLazyDPSEvaluation ();
10138 if (AOP_INDPTRn(left)) {
10139 genSetDPTR(AOP(left)->aopu.dptr);
10145 emitcode ("clr", "a");
10146 emitcode ("movc", "a,@a+dptr");
10147 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10148 emitcode ("inc", "dptr");
10149 aopPut (AOP (result), "a", offset++);
10151 _endLazyDPSEvaluation ();
10154 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10155 if (!AOP_INDPTRn(left)) {
10156 _startLazyDPSEvaluation ();
10158 aopPut ( AOP (left), "dpl", 0);
10159 aopPut ( AOP (left), "dph", 1);
10160 if (options.model == MODEL_FLAT24)
10161 aopPut ( AOP (left), "dpx", 2);
10163 _endLazyDPSEvaluation ();
10166 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
10167 AOP_SIZE(result) > 1 &&
10168 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10170 size = AOP_SIZE (result) - 1;
10171 if (AOP_INDPTRn(left)) {
10172 genSetDPTR(AOP(left)->aopu.dptr);
10174 while (size--) emitcode ("lcall","__decdptr");
10175 if (AOP_INDPTRn(left)) {
10180 freeAsmop (left, NULL, ic, TRUE);
10181 freeAsmop (result, NULL, ic, TRUE);
10184 /*-----------------------------------------------------------------*/
10185 /* genGenPointerGet - gget value from generic pointer space */
10186 /*-----------------------------------------------------------------*/
10188 genGenPointerGet (operand * left,
10189 operand * result, iCode * ic, iCode * pi)
10192 sym_link *retype = getSpec (operandType (result));
10193 sym_link *letype = getSpec (operandType (left));
10195 D (emitcode (";", "genGenPointerGet "); );
10197 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
10199 /* if the operand is already in dptr
10200 then we do nothing else we move the value to dptr */
10201 if (AOP_TYPE (left) != AOP_STR)
10203 /* if this is rematerializable */
10204 if (AOP_TYPE (left) == AOP_IMMD)
10206 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10207 if (AOP(left)->aopu.aop_immd.from_cast_remat)
10209 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
10213 emitcode ("mov", "b,#%d", pointerCode (retype));
10217 { /* we need to get it byte by byte */
10218 _startLazyDPSEvaluation ();
10219 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
10220 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
10221 if (options.model == MODEL_FLAT24) {
10222 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10223 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
10225 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10227 _endLazyDPSEvaluation ();
10231 /* so dptr-b now contains the address */
10233 aopOp (result, ic, FALSE, TRUE);
10236 /* if bit then unpack */
10237 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10239 genUnpackBits (result, "dptr", GPOINTER);
10243 size = AOP_SIZE (result);
10250 // Get two bytes at a time, results in _AP & A.
10251 // dptr will be incremented ONCE by __gptrgetWord.
10253 // Note: any change here must be coordinated
10254 // with the implementation of __gptrgetWord
10255 // in device/lib/_gptrget.c
10256 emitcode ("lcall", "__gptrgetWord");
10257 aopPut (AOP (result), DP2_RESULT_REG, offset++);
10258 aopPut (AOP (result), "a", offset++);
10263 // Only one byte to get.
10264 emitcode ("lcall", "__gptrget");
10265 aopPut (AOP (result), "a", offset++);
10268 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
10270 emitcode ("inc", "dptr");
10275 if (pi && AOP_TYPE (left) != AOP_IMMD) {
10276 _startLazyDPSEvaluation ();
10278 aopPut ( AOP (left), "dpl", 0);
10279 aopPut ( AOP (left), "dph", 1);
10280 if (options.model == MODEL_FLAT24) {
10281 aopPut ( AOP (left), "dpx", 2);
10282 aopPut ( AOP (left), "b", 3);
10283 } else aopPut ( AOP (left), "b", 2);
10285 _endLazyDPSEvaluation ();
10288 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
10289 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10291 size = AOP_SIZE (result) - 1;
10292 while (size--) emitcode ("lcall","__decdptr");
10295 freeAsmop (left, NULL, ic, TRUE);
10296 freeAsmop (result, NULL, ic, TRUE);
10299 /*-----------------------------------------------------------------*/
10300 /* genPointerGet - generate code for pointer get */
10301 /*-----------------------------------------------------------------*/
10303 genPointerGet (iCode * ic, iCode *pi)
10305 operand *left, *result;
10306 sym_link *type, *etype;
10309 D (emitcode (";", "genPointerGet ");
10312 left = IC_LEFT (ic);
10313 result = IC_RESULT (ic);
10315 /* depending on the type of pointer we need to
10316 move it to the correct pointer register */
10317 type = operandType (left);
10318 etype = getSpec (type);
10319 /* if left is of type of pointer then it is simple */
10320 if (IS_PTR (type) && !IS_FUNC (type->next))
10321 p_type = DCL_TYPE (type);
10324 /* we have to go by the storage class */
10325 p_type = PTR_TYPE (SPEC_OCLS (etype));
10327 /* special case when cast remat */
10328 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10329 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10331 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10332 type = operandType (left);
10333 p_type = DCL_TYPE (type);
10335 /* now that we have the pointer type we assign
10336 the pointer values */
10342 genNearPointerGet (left, result, ic, pi);
10346 genPagedPointerGet (left, result, ic, pi);
10350 genFarPointerGet (left, result, ic, pi);
10354 genCodePointerGet (left, result, ic, pi);
10358 genGenPointerGet (left, result, ic, pi);
10364 /*-----------------------------------------------------------------*/
10365 /* genPackBits - generates code for packed bit storage */
10366 /*-----------------------------------------------------------------*/
10368 genPackBits (sym_link * etype,
10370 char *rname, int p_type)
10372 int offset = 0; /* source byte offset */
10373 int rlen = 0; /* remaining bitfield length */
10374 int blen; /* bitfield length */
10375 int bstr; /* bitfield starting bit within byte */
10376 int litval; /* source literal value (if AOP_LIT) */
10377 unsigned char mask; /* bitmask within current byte */
10379 D(emitcode ("; genPackBits",""));
10381 blen = SPEC_BLEN (etype);
10382 bstr = SPEC_BSTR (etype);
10384 /* If the bitfield length is less than a byte */
10387 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10388 (unsigned char) (0xFF >> (8 - bstr)));
10390 if (AOP_TYPE (right) == AOP_LIT)
10392 /* Case with a bitfield length <8 and literal source
10394 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10396 litval &= (~mask) & 0xff;
10397 emitPtrByteGet (rname, p_type, FALSE);
10398 if ((mask|litval)!=0xff)
10399 emitcode ("anl","a,#!constbyte", mask);
10401 emitcode ("orl","a,#!constbyte", litval);
10405 if ((blen==1) && (p_type!=GPOINTER))
10407 /* Case with a bitfield length == 1 and no generic pointer
10409 if (AOP_TYPE (right) == AOP_CRY)
10410 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10413 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10414 emitcode ("rrc","a");
10416 emitPtrByteGet (rname, p_type, FALSE);
10417 emitcode ("mov","acc.%d,c",bstr);
10421 /* Case with a bitfield length < 8 and arbitrary source
10423 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10424 /* shift and mask source value */
10426 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10428 /* transfer A to B and get next byte */
10429 emitPtrByteGet (rname, p_type, TRUE);
10431 emitcode ("anl", "a,#!constbyte", mask);
10432 emitcode ("orl", "a,b");
10433 if (p_type == GPOINTER)
10434 emitcode ("pop", "b");
10438 emitPtrByteSet (rname, p_type, "a");
10442 /* Bit length is greater than 7 bits. In this case, copy */
10443 /* all except the partial byte at the end */
10444 for (rlen=blen;rlen>=8;rlen-=8)
10446 emitPtrByteSet (rname, p_type,
10447 aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
10449 emitcode ("inc", "%s", rname);
10452 /* If there was a partial byte at the end */
10455 mask = (((unsigned char) -1 << rlen) & 0xff);
10457 if (AOP_TYPE (right) == AOP_LIT)
10459 /* Case with partial byte and literal source
10461 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10462 litval >>= (blen-rlen);
10463 litval &= (~mask) & 0xff;
10464 emitPtrByteGet (rname, p_type, FALSE);
10465 if ((mask|litval)!=0xff)
10466 emitcode ("anl","a,#!constbyte", mask);
10468 emitcode ("orl","a,#!constbyte", litval);
10472 /* Case with partial byte and arbitrary source
10474 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10475 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10477 /* transfer A to B and get next byte */
10478 emitPtrByteGet (rname, p_type, TRUE);
10480 emitcode ("anl", "a,#!constbyte", mask);
10481 emitcode ("orl", "a,b");
10482 if (p_type == GPOINTER)
10483 emitcode ("pop", "b");
10485 emitPtrByteSet (rname, p_type, "a");
10491 /*-----------------------------------------------------------------*/
10492 /* genDataPointerSet - remat pointer to data space */
10493 /*-----------------------------------------------------------------*/
10495 genDataPointerSet (operand * right,
10499 int size, offset = 0;
10500 char *l, buff[256];
10502 aopOp (right, ic, FALSE, FALSE);
10504 l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
10505 size = AOP_SIZE (right);
10510 SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
10514 SNPRINTF (buff, sizeof(buff), "%s", l + 1);
10517 emitcode ("mov", "%s,%s", buff,
10518 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10521 freeAsmop (right, NULL, ic, TRUE);
10522 freeAsmop (result, NULL, ic, TRUE);
10525 /*-----------------------------------------------------------------*/
10526 /* genNearPointerSet - emitcode for near pointer put */
10527 /*-----------------------------------------------------------------*/
10529 genNearPointerSet (operand * right,
10536 sym_link *retype, *letype;
10537 sym_link *ptype = operandType (result);
10539 retype = getSpec (operandType (right));
10540 letype = getSpec (ptype);
10542 aopOp (result, ic, FALSE, FALSE);
10544 /* if the result is rematerializable &
10545 in data space & not a bit variable */
10546 if (AOP_TYPE (result) == AOP_IMMD &&
10547 DCL_TYPE (ptype) == POINTER &&
10548 !IS_BITVAR (retype) &&
10549 !IS_BITVAR (letype))
10551 genDataPointerSet (right, result, ic);
10555 /* if the value is already in a pointer register
10556 then don't need anything more */
10557 if (!AOP_INPREG (AOP (result)))
10559 /* otherwise get a free pointer register */
10562 aop = newAsmop (0);
10563 preg = getFreePtr (ic, &aop, FALSE);
10564 emitcode ("mov", "%s,%s",
10566 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10567 rname = preg->name;
10570 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10572 aopOp (right, ic, FALSE, FALSE);
10574 /* if bitfield then unpack the bits */
10575 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10576 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10579 /* we have can just get the values */
10580 int size = AOP_SIZE (right);
10585 l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10589 emitcode ("mov", "@%s,a", rname);
10592 emitcode ("mov", "@%s,%s", rname, l);
10594 emitcode ("inc", "%s", rname);
10599 /* now some housekeeping stuff */
10602 /* we had to allocate for this iCode */
10603 if (pi) aopPut (AOP (result),rname,0);
10604 freeAsmop (NULL, aop, ic, TRUE);
10608 /* we did not allocate which means left
10609 already in a pointer register, then
10610 if size > 0 && this could be used again
10611 we have to point it back to where it
10613 if (AOP_SIZE (right) > 1 &&
10614 !OP_SYMBOL (result)->remat &&
10615 (OP_SYMBOL (result)->liveTo > ic->seq ||
10619 int size = AOP_SIZE (right) - 1;
10621 emitcode ("dec", "%s", rname);
10626 if (pi) pi->generated = 1;
10627 freeAsmop (result, NULL, ic, TRUE);
10628 freeAsmop (right, NULL, ic, TRUE);
10633 /*-----------------------------------------------------------------*/
10634 /* genPagedPointerSet - emitcode for Paged pointer put */
10635 /*-----------------------------------------------------------------*/
10637 genPagedPointerSet (operand * right,
10644 sym_link *retype, *letype;
10646 retype = getSpec (operandType (right));
10647 letype = getSpec (operandType (result));
10649 aopOp (result, ic, FALSE, FALSE);
10651 /* if the value is already in a pointer register
10652 then don't need anything more */
10653 if (!AOP_INPREG (AOP (result)))
10655 /* otherwise get a free pointer register */
10658 aop = newAsmop (0);
10659 preg = getFreePtr (ic, &aop, FALSE);
10660 emitcode ("mov", "%s,%s",
10662 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10663 rname = preg->name;
10666 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10668 aopOp (right, ic, FALSE, FALSE);
10670 /* if bitfield then unpack the bits */
10671 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10672 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10675 /* we have can just get the values */
10676 int size = AOP_SIZE (right);
10681 MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10683 emitcode ("movx", "@%s,a", rname);
10686 emitcode ("inc", "%s", rname);
10692 /* now some housekeeping stuff */
10695 if (pi) aopPut (AOP (result),rname,0);
10696 /* we had to allocate for this iCode */
10697 freeAsmop (NULL, aop, ic, TRUE);
10701 /* we did not allocate which means left
10702 already in a pointer register, then
10703 if size > 0 && this could be used again
10704 we have to point it back to where it
10706 if (AOP_SIZE (right) > 1 &&
10707 !OP_SYMBOL (result)->remat &&
10708 (OP_SYMBOL (result)->liveTo > ic->seq ||
10712 int size = AOP_SIZE (right) - 1;
10714 emitcode ("dec", "%s", rname);
10719 if (pi) pi->generated = 1;
10720 freeAsmop (result, NULL, ic, TRUE);
10721 freeAsmop (right, NULL, ic, TRUE);
10726 /*-----------------------------------------------------------------*/
10727 /* genFarPointerSet - set value from far space */
10728 /*-----------------------------------------------------------------*/
10730 genFarPointerSet (operand * right,
10731 operand * result, iCode * ic, iCode *pi)
10733 int size, offset, dopi=1;
10734 sym_link *retype = getSpec (operandType (right));
10735 sym_link *letype = getSpec (operandType (result));
10737 aopOp (result, ic, FALSE, FALSE);
10739 /* if the operand is already in dptr
10740 then we do nothing else we move the value to dptr */
10741 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10743 /* if this is remateriazable */
10744 if (AOP_TYPE (result) == AOP_IMMD)
10745 emitcode ("mov", "dptr,%s",
10746 aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10749 /* we need to get it byte by byte */
10750 _startLazyDPSEvaluation ();
10751 if (AOP_TYPE (result) != AOP_DPTR)
10753 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10754 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10755 if (options.model == MODEL_FLAT24)
10756 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10760 /* We need to generate a load to DPTR indirect through DPTR. */
10761 D (emitcode (";", "genFarPointerSet -- indirection special case."););
10763 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10764 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10765 if (options.model == MODEL_FLAT24)
10766 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10767 emitcode ("pop", "dph");
10768 emitcode ("pop", "dpl");
10771 _endLazyDPSEvaluation ();
10774 /* so dptr know contains the address */
10775 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10777 /* if bit then unpack */
10778 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10779 if (AOP_INDPTRn(result)) {
10780 genSetDPTR(AOP(result)->aopu.dptr);
10782 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10783 if (AOP_INDPTRn(result)) {
10787 size = AOP_SIZE (right);
10789 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10791 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10793 genSetDPTR(AOP(result)->aopu.dptr);
10794 emitcode ("movx", "@dptr,a");
10795 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10796 emitcode ("inc", "dptr");
10800 _startLazyDPSEvaluation ();
10802 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10804 if (AOP_INDPTRn(result)) {
10805 genSetDPTR(AOP(result)->aopu.dptr);
10811 emitcode ("movx", "@dptr,a");
10812 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10813 emitcode ("inc", "dptr");
10815 _endLazyDPSEvaluation ();
10819 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10820 if (!AOP_INDPTRn(result)) {
10821 _startLazyDPSEvaluation ();
10823 aopPut (AOP(result),"dpl",0);
10824 aopPut (AOP(result),"dph",1);
10825 if (options.model == MODEL_FLAT24)
10826 aopPut (AOP(result),"dpx",2);
10828 _endLazyDPSEvaluation ();
10831 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10832 AOP_SIZE(right) > 1 &&
10833 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10835 size = AOP_SIZE (right) - 1;
10836 if (AOP_INDPTRn(result)) {
10837 genSetDPTR(AOP(result)->aopu.dptr);
10839 while (size--) emitcode ("lcall","__decdptr");
10840 if (AOP_INDPTRn(result)) {
10844 freeAsmop (result, NULL, ic, TRUE);
10845 freeAsmop (right, NULL, ic, TRUE);
10848 /*-----------------------------------------------------------------*/
10849 /* genGenPointerSet - set value from generic pointer space */
10850 /*-----------------------------------------------------------------*/
10852 genGenPointerSet (operand * right,
10853 operand * result, iCode * ic, iCode *pi)
10856 sym_link *retype = getSpec (operandType (right));
10857 sym_link *letype = getSpec (operandType (result));
10859 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10861 /* if the operand is already in dptr
10862 then we do nothing else we move the value to dptr */
10863 if (AOP_TYPE (result) != AOP_STR)
10865 _startLazyDPSEvaluation ();
10866 /* if this is remateriazable */
10867 if (AOP_TYPE (result) == AOP_IMMD)
10869 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10870 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10872 MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10877 "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10881 { /* we need to get it byte by byte */
10882 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10883 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10884 if (options.model == MODEL_FLAT24) {
10885 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10886 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10888 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10891 _endLazyDPSEvaluation ();
10893 /* so dptr + b now contains the address */
10895 aopOp (right, ic, FALSE, TRUE);
10899 /* if bit then unpack */
10900 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10902 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10906 size = AOP_SIZE (right);
10909 _startLazyDPSEvaluation ();
10914 // Set two bytes at a time, passed in _AP & A.
10915 // dptr will be incremented ONCE by __gptrputWord.
10917 // Note: any change here must be coordinated
10918 // with the implementation of __gptrputWord
10919 // in device/lib/_gptrput.c
10920 emitcode("mov", "_ap, %s",
10921 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10922 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10926 emitcode ("lcall", "__gptrputWord");
10931 // Only one byte to put.
10932 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10936 emitcode ("lcall", "__gptrput");
10939 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10941 emitcode ("inc", "dptr");
10944 _endLazyDPSEvaluation ();
10947 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10948 _startLazyDPSEvaluation ();
10950 aopPut (AOP(result),"dpl",0);
10951 aopPut (AOP(result),"dph",1);
10952 if (options.model == MODEL_FLAT24) {
10953 aopPut (AOP(result),"dpx",2);
10954 aopPut (AOP(result),"b",3);
10956 aopPut (AOP(result),"b",2);
10958 _endLazyDPSEvaluation ();
10961 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10962 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10964 size = AOP_SIZE (right) - 1;
10965 while (size--) emitcode ("lcall","__decdptr");
10967 freeAsmop (result, NULL, ic, TRUE);
10968 freeAsmop (right, NULL, ic, TRUE);
10971 /*-----------------------------------------------------------------*/
10972 /* genPointerSet - stores the value into a pointer location */
10973 /*-----------------------------------------------------------------*/
10975 genPointerSet (iCode * ic, iCode *pi)
10977 operand *right, *result;
10978 sym_link *type, *etype;
10981 D (emitcode (";", "genPointerSet "););
10983 right = IC_RIGHT (ic);
10984 result = IC_RESULT (ic);
10986 /* depending on the type of pointer we need to
10987 move it to the correct pointer register */
10988 type = operandType (result);
10989 etype = getSpec (type);
10990 /* if left is of type of pointer then it is simple */
10991 if (IS_PTR (type) && !IS_FUNC (type->next))
10993 p_type = DCL_TYPE (type);
10997 /* we have to go by the storage class */
10998 p_type = PTR_TYPE (SPEC_OCLS (etype));
11000 /* special case when cast remat */
11001 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
11002 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
11003 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
11004 type = operandType (result);
11005 p_type = DCL_TYPE (type);
11008 /* now that we have the pointer type we assign
11009 the pointer values */
11015 genNearPointerSet (right, result, ic, pi);
11019 genPagedPointerSet (right, result, ic, pi);
11023 genFarPointerSet (right, result, ic, pi);
11027 genGenPointerSet (right, result, ic, pi);
11031 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11032 "genPointerSet: illegal pointer type");
11037 /*-----------------------------------------------------------------*/
11038 /* genIfx - generate code for Ifx statement */
11039 /*-----------------------------------------------------------------*/
11041 genIfx (iCode * ic, iCode * popIc)
11043 operand *cond = IC_COND (ic);
11046 D (emitcode (";", "genIfx "););
11048 aopOp (cond, ic, FALSE, FALSE);
11050 /* get the value into acc */
11051 if (AOP_TYPE (cond) != AOP_CRY)
11060 /* the result is now in the accumulator */
11061 freeAsmop (cond, NULL, ic, TRUE);
11063 /* if there was something to be popped then do it */
11067 /* if the condition is a bit variable */
11068 if (isbit && IS_ITEMP (cond) &&
11071 genIfxJump (ic, SPIL_LOC (cond)->rname);
11073 else if (isbit && !IS_ITEMP (cond))
11075 genIfxJump (ic, OP_SYMBOL (cond)->rname);
11079 genIfxJump (ic, "a");
11085 /*-----------------------------------------------------------------*/
11086 /* genAddrOf - generates code for address of */
11087 /*-----------------------------------------------------------------*/
11089 genAddrOf (iCode * ic)
11091 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11094 D (emitcode (";", "genAddrOf ");
11097 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11099 /* if the operand is on the stack then we
11100 need to get the stack offset of this
11102 if (sym->onStack) {
11104 /* if 10 bit stack */
11105 if (options.stack10bit) {
11109 tsprintf(buff, sizeof(buff),
11110 "#!constbyte",(options.stack_loc >> 16) & 0xff);
11111 /* if it has an offset then we need to compute it */
11112 /* emitcode ("subb", "a,#!constbyte", */
11113 /* -((sym->stack < 0) ? */
11114 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11115 /* ((short) sym->stack)) & 0xff); */
11116 /* emitcode ("mov","b,a"); */
11117 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
11118 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11119 /* ((short) sym->stack)) >> 8) & 0xff); */
11121 emitcode ("mov", "a,_bpx");
11122 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
11123 ((char) (sym->stack - _G.nRegsSaved)) :
11124 ((char) sym->stack )) & 0xff);
11125 emitcode ("mov", "b,a");
11126 emitcode ("mov", "a,_bpx+1");
11128 offset = (((sym->stack < 0) ?
11129 ((short) (sym->stack - _G.nRegsSaved)) :
11130 ((short) sym->stack )) >> 8) & 0xff;
11132 emitcode ("addc","a,#!constbyte", offset);
11134 aopPut (AOP (IC_RESULT (ic)), "b", 0);
11135 aopPut (AOP (IC_RESULT (ic)), "a", 1);
11136 aopPut (AOP (IC_RESULT (ic)), buff, 2);
11138 /* we can just move _bp */
11139 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
11140 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
11141 aopPut (AOP (IC_RESULT (ic)), buff, 2);
11144 /* if it has an offset then we need to compute it */
11146 emitcode ("mov", "a,_bp");
11147 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
11148 aopPut (AOP (IC_RESULT (ic)), "a", 0);
11150 /* we can just move _bp */
11151 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
11153 /* fill the result with zero */
11154 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11157 if (options.stack10bit && size < (FPTRSIZE - 1)) {
11159 "*** warning: pointer to stack var truncated.\n");
11164 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
11170 /* object not on stack then we need the name */
11171 size = AOP_SIZE (IC_RESULT (ic));
11176 char s[SDCC_NAME_MAX];
11180 tsprintf(s, sizeof(s), "#!his",sym->rname);
11183 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
11186 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
11188 default: /* should not need this (just in case) */
11189 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
11196 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11199 aopPut (AOP (IC_RESULT (ic)), s, offset++);
11203 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11207 #if 0 // obsolete, and buggy for != xdata
11208 /*-----------------------------------------------------------------*/
11209 /* genArrayInit - generates code for address of */
11210 /*-----------------------------------------------------------------*/
11212 genArrayInit (iCode * ic)
11214 literalList *iLoop;
11216 int elementSize = 0, eIndex;
11217 unsigned val, lastVal;
11219 operand *left=IC_LEFT(ic);
11221 D (emitcode (";", "genArrayInit "););
11223 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
11225 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
11227 // Load immediate value into DPTR.
11228 emitcode("mov", "dptr, %s",
11229 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
11231 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
11234 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11235 "Unexpected operand to genArrayInit.\n");
11238 // a regression because of SDCCcse.c:1.52
11239 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
11240 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
11241 if (options.model == MODEL_FLAT24)
11242 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
11246 type = operandType(IC_LEFT(ic));
11248 if (type && type->next)
11250 elementSize = getSize(type->next);
11254 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11255 "can't determine element size in genArrayInit.\n");
11259 iLoop = IC_ARRAYILIST(ic);
11264 bool firstpass = TRUE;
11266 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
11267 iLoop->count, (int)iLoop->literalValue, elementSize);
11273 symbol *tlbl = NULL;
11275 count = ix > 256 ? 256 : ix;
11279 tlbl = newiTempLabel (NULL);
11280 if (firstpass || (count & 0xff))
11282 emitcode("mov", "b, #!constbyte", count & 0xff);
11285 emitcode ("", "!tlabeldef", tlbl->key + 100);
11290 for (eIndex = 0; eIndex < elementSize; eIndex++)
11292 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
11293 if (val != lastVal)
11295 emitcode("mov", "a, #!constbyte", val);
11299 emitcode("movx", "@dptr, a");
11300 emitcode("inc", "dptr");
11305 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
11311 iLoop = iLoop->next;
11314 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
11318 /*-----------------------------------------------------------------*/
11319 /* genFarFarAssign - assignment when both are in far space */
11320 /*-----------------------------------------------------------------*/
11322 genFarFarAssign (operand * result, operand * right, iCode * ic)
11324 int size = AOP_SIZE (right);
11326 symbol *rSym = NULL;
11330 /* quick & easy case. */
11331 D(emitcode(";","genFarFarAssign (1 byte case)"););
11332 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
11333 freeAsmop (right, NULL, ic, FALSE);
11334 /* now assign DPTR to result */
11336 aopOp(result, ic, FALSE, FALSE);
11338 aopPut(AOP(result), "a", 0);
11339 freeAsmop(result, NULL, ic, FALSE);
11343 /* See if we've got an underlying symbol to abuse. */
11344 if (IS_SYMOP(result) && OP_SYMBOL(result))
11346 if (IS_TRUE_SYMOP(result))
11348 rSym = OP_SYMBOL(result);
11350 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
11352 rSym = OP_SYMBOL(result)->usl.spillLoc;
11356 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
11358 /* We can use the '390 auto-toggle feature to good effect here. */
11360 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
11361 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11362 emitcode ("mov", "dptr,#%s", rSym->rname);
11363 /* DP2 = result, DP1 = right, DP1 is current. */
11366 emitcode("movx", "a,@dptr");
11367 emitcode("movx", "@dptr,a");
11370 emitcode("inc", "dptr");
11371 emitcode("inc", "dptr");
11374 emitcode("mov", "dps,#0");
11375 freeAsmop (right, NULL, ic, FALSE);
11377 some alternative code for processors without auto-toggle
11378 no time to test now, so later well put in...kpb
11379 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
11380 emitcode("mov", "dps,#1"); /* Select DPTR2. */
11381 emitcode ("mov", "dptr,#%s", rSym->rname);
11382 /* DP2 = result, DP1 = right, DP1 is current. */
11386 emitcode("movx", "a,@dptr");
11388 emitcode("inc", "dptr");
11389 emitcode("inc", "dps");
11390 emitcode("movx", "@dptr,a");
11392 emitcode("inc", "dptr");
11393 emitcode("inc", "dps");
11395 emitcode("mov", "dps,#0");
11396 freeAsmop (right, NULL, ic, FALSE);
11401 D (emitcode (";", "genFarFarAssign"););
11402 aopOp (result, ic, TRUE, TRUE);
11404 _startLazyDPSEvaluation ();
11408 aopPut (AOP (result),
11409 aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
11412 _endLazyDPSEvaluation ();
11413 freeAsmop (result, NULL, ic, FALSE);
11414 freeAsmop (right, NULL, ic, FALSE);
11418 /*-----------------------------------------------------------------*/
11419 /* genAssign - generate code for assignment */
11420 /*-----------------------------------------------------------------*/
11422 genAssign (iCode * ic)
11424 operand *result, *right;
11426 unsigned long lit = 0L;
11428 D (emitcode (";", "genAssign ");
11431 result = IC_RESULT (ic);
11432 right = IC_RIGHT (ic);
11434 /* if they are the same */
11435 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11438 aopOp (right, ic, FALSE, FALSE);
11440 emitcode (";", "genAssign: resultIsFar = %s",
11441 isOperandInFarSpace (result) ?
11444 /* special case both in far space */
11445 if ((AOP_TYPE (right) == AOP_DPTR ||
11446 AOP_TYPE (right) == AOP_DPTR2) &&
11447 /* IS_TRUE_SYMOP(result) && */
11448 isOperandInFarSpace (result))
11450 genFarFarAssign (result, right, ic);
11454 aopOp (result, ic, TRUE, FALSE);
11456 /* if they are the same registers */
11457 if (sameRegs (AOP (right), AOP (result)))
11460 /* if the result is a bit */
11461 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
11463 /* if the right size is a literal then
11464 we know what the value is */
11465 if (AOP_TYPE (right) == AOP_LIT)
11467 if (((int) operandLitValue (right)))
11468 aopPut (AOP (result), one, 0);
11470 aopPut (AOP (result), zero, 0);
11474 /* the right is also a bit variable */
11475 if (AOP_TYPE (right) == AOP_CRY)
11477 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11478 aopPut (AOP (result), "c", 0);
11482 /* we need to or */
11484 aopPut (AOP (result), "a", 0);
11488 /* bit variables done */
11490 size = AOP_SIZE (result);
11492 if (AOP_TYPE (right) == AOP_LIT)
11493 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11496 (AOP_TYPE (result) != AOP_REG) &&
11497 (AOP_TYPE (right) == AOP_LIT) &&
11498 !IS_FLOAT (operandType (right)))
11500 _startLazyDPSEvaluation ();
11501 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
11503 aopPut (AOP (result),
11504 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11509 /* And now fill the rest with zeros. */
11512 emitcode ("clr", "a");
11516 aopPut (AOP (result), "a", offset++);
11518 _endLazyDPSEvaluation ();
11522 _startLazyDPSEvaluation ();
11525 aopPut (AOP (result),
11526 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11530 _endLazyDPSEvaluation ();
11534 freeAsmop (right, NULL, ic, FALSE);
11535 freeAsmop (result, NULL, ic, TRUE);
11538 /*-----------------------------------------------------------------*/
11539 /* genJumpTab - generates code for jump table */
11540 /*-----------------------------------------------------------------*/
11542 genJumpTab (iCode * ic)
11547 D (emitcode (";", "genJumpTab ");
11550 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11551 /* get the condition into accumulator */
11552 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11554 /* multiply by four! */
11555 emitcode ("add", "a,acc");
11556 emitcode ("add", "a,acc");
11557 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11559 jtab = newiTempLabel (NULL);
11560 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11561 emitcode ("jmp", "@a+dptr");
11562 emitcode ("", "!tlabeldef", jtab->key + 100);
11563 /* now generate the jump labels */
11564 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11565 jtab = setNextItem (IC_JTLABELS (ic)))
11566 emitcode ("ljmp", "!tlabel", jtab->key + 100);
11570 /*-----------------------------------------------------------------*/
11571 /* genCast - gen code for casting */
11572 /*-----------------------------------------------------------------*/
11574 genCast (iCode * ic)
11576 operand *result = IC_RESULT (ic);
11577 sym_link *ctype = operandType (IC_LEFT (ic));
11578 sym_link *rtype = operandType (IC_RIGHT (ic));
11579 operand *right = IC_RIGHT (ic);
11582 D (emitcode (";", "genCast "););
11584 /* if they are equivalent then do nothing */
11585 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11588 aopOp (right, ic, FALSE, AOP_IS_STR (result));
11589 aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
11591 /* if the result is a bit */
11592 if (IS_BITVAR (OP_SYMBOL (result)->type)
11593 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11595 /* if the right size is a literal then
11596 we know what the value is */
11597 if (AOP_TYPE (right) == AOP_LIT)
11599 if (((int) operandLitValue (right)))
11600 aopPut (AOP (result), one, 0);
11602 aopPut (AOP (result), zero, 0);
11607 /* the right is also a bit variable */
11608 if (AOP_TYPE (right) == AOP_CRY)
11610 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11611 aopPut (AOP (result), "c", 0);
11615 /* we need to or */
11617 aopPut (AOP (result), "a", 0);
11621 /* if they are the same size : or less */
11622 if (AOP_SIZE (result) <= AOP_SIZE (right))
11625 /* if they are in the same place */
11626 if (sameRegs (AOP (right), AOP (result)))
11629 /* if they in different places then copy */
11630 size = AOP_SIZE (result);
11632 _startLazyDPSEvaluation ();
11635 aopPut (AOP (result),
11636 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11640 _endLazyDPSEvaluation ();
11645 /* if the result is of type pointer */
11646 if (IS_PTR (ctype))
11650 sym_link *type = operandType (right);
11652 /* pointer to generic pointer */
11653 if (IS_GENPTR (ctype))
11657 p_type = DCL_TYPE (type);
11661 #if OLD_CAST_BEHAVIOR
11662 /* KV: we are converting a non-pointer type to
11663 * a generic pointer. This (ifdef'd out) code
11664 * says that the resulting generic pointer
11665 * should have the same class as the storage
11666 * location of the non-pointer variable.
11668 * For example, converting an int (which happens
11669 * to be stored in DATA space) to a pointer results
11670 * in a DATA generic pointer; if the original int
11671 * in XDATA space, so will be the resulting pointer.
11673 * I don't like that behavior, and thus this change:
11674 * all such conversions will be forced to XDATA and
11675 * throw a warning. If you want some non-XDATA
11676 * type, or you want to suppress the warning, you
11677 * must go through an intermediate cast, like so:
11679 * char _generic *gp = (char _xdata *)(intVar);
11681 sym_link *etype = getSpec (type);
11683 /* we have to go by the storage class */
11684 if (SPEC_OCLS (etype) != generic)
11686 p_type = PTR_TYPE (SPEC_OCLS (etype));
11691 /* Converting unknown class (i.e. register variable)
11692 * to generic pointer. This is not good, but
11693 * we'll make a guess (and throw a warning).
11696 werror (W_INT_TO_GEN_PTR_CAST);
11700 /* the first two bytes are known */
11701 size = GPTRSIZE - 1;
11703 _startLazyDPSEvaluation ();
11706 aopPut (AOP (result),
11707 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11711 _endLazyDPSEvaluation ();
11713 /* the last byte depending on type */
11715 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11720 // pointerTypeToGPByte will have bitched.
11724 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%x", gpVal);
11725 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11730 /* just copy the pointers */
11731 size = AOP_SIZE (result);
11733 _startLazyDPSEvaluation ();
11736 aopPut (AOP (result),
11737 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11741 _endLazyDPSEvaluation ();
11745 /* so we now know that the size of destination is greater
11746 than the size of the source */
11747 /* we move to result for the size of source */
11748 size = AOP_SIZE (right);
11750 _startLazyDPSEvaluation ();
11753 aopPut (AOP (result),
11754 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11758 _endLazyDPSEvaluation ();
11760 /* now depending on the sign of the source && destination */
11761 size = AOP_SIZE (result) - AOP_SIZE (right);
11762 /* if unsigned or not an integral type */
11763 /* also, if the source is a bit, we don't need to sign extend, because
11764 * it can't possibly have set the sign bit.
11766 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11770 aopPut (AOP (result), zero, offset++);
11775 /* we need to extend the sign :{ */
11776 MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11777 FALSE, FALSE, NULL));
11778 emitcode ("rlc", "a");
11779 emitcode ("subb", "a,acc");
11781 aopPut (AOP (result), "a", offset++);
11784 /* we are done hurray !!!! */
11787 freeAsmop (right, NULL, ic, TRUE);
11788 freeAsmop (result, NULL, ic, TRUE);
11792 /*-----------------------------------------------------------------*/
11793 /* genDjnz - generate decrement & jump if not zero instrucion */
11794 /*-----------------------------------------------------------------*/
11796 genDjnz (iCode * ic, iCode * ifx)
11798 symbol *lbl, *lbl1;
11802 /* if the if condition has a false label
11803 then we cannot save */
11804 if (IC_FALSE (ifx))
11807 /* if the minus is not of the form
11809 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11810 !IS_OP_LITERAL (IC_RIGHT (ic)))
11813 if (operandLitValue (IC_RIGHT (ic)) != 1)
11816 /* if the size of this greater than one then no
11818 if (getSize (operandType (IC_RESULT (ic))) > 1)
11821 /* otherwise we can save BIG */
11822 D(emitcode(";", "genDjnz"););
11824 lbl = newiTempLabel (NULL);
11825 lbl1 = newiTempLabel (NULL);
11827 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11829 if (AOP_NEEDSACC(IC_RESULT(ic)))
11831 /* If the result is accessed indirectly via
11832 * the accumulator, we must explicitly write
11833 * it back after the decrement.
11835 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11837 if (strcmp(rByte, "a"))
11839 /* Something is hopelessly wrong */
11840 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11841 __FILE__, __LINE__);
11842 /* We can just give up; the generated code will be inefficient,
11843 * but what the hey.
11845 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11848 emitcode ("dec", "%s", rByte);
11849 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11850 emitcode ("jnz", "!tlabel", lbl->key + 100);
11852 else if (IS_AOP_PREG (IC_RESULT (ic)))
11854 emitcode ("dec", "%s",
11855 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11856 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11857 emitcode ("jnz", "!tlabel", lbl->key + 100);
11861 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11864 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11865 emitcode ("", "!tlabeldef", lbl->key + 100);
11866 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11867 emitcode ("", "!tlabeldef", lbl1->key + 100);
11869 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11870 ifx->generated = 1;
11874 /*-----------------------------------------------------------------*/
11875 /* genReceive - generate code for a receive iCode */
11876 /*-----------------------------------------------------------------*/
11878 genReceive (iCode * ic)
11880 int size = getSize (operandType (IC_RESULT (ic)));
11884 D (emitcode (";", "genReceive "););
11886 if (ic->argreg == 1)
11888 /* first parameter */
11889 if (AOP_IS_STR(IC_RESULT(ic)))
11891 /* Nothing to do: it's already in the proper place. */
11898 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11899 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11900 IS_TRUE_SYMOP (IC_RESULT (ic)));
11903 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11906 /* Sanity checking... */
11907 if (AOP_USESDPTR(IC_RESULT(ic)))
11909 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11910 "genReceive got unexpected DPTR.");
11912 assignResultValue (IC_RESULT (ic));
11917 /* second receive onwards */
11918 /* this gets a little tricky since unused recevies will be
11919 eliminated, we have saved the reg in the type field . and
11920 we use that to figure out which register to use */
11921 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11922 rb1off = ic->argreg;
11925 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11928 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11931 /*-----------------------------------------------------------------*/
11932 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11933 /*-----------------------------------------------------------------*/
11934 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11936 operand *from , *to , *count;
11941 /* we know it has to be 3 parameters */
11942 assert (nparms == 3);
11944 rsave = newBitVect(16);
11945 /* save DPTR if it needs to be saved */
11946 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11947 if (bitVectBitValue(ic->rMask,i))
11948 rsave = bitVectSetBit(rsave,i);
11950 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11951 ds390_rUmaskForOp (IC_RESULT(ic))));
11958 aopOp (from, ic->next, FALSE, FALSE);
11960 /* get from into DPTR1 */
11961 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11962 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11963 if (options.model == MODEL_FLAT24) {
11964 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11967 freeAsmop (from, NULL, ic, FALSE);
11968 aopOp (to, ic, FALSE, FALSE);
11969 /* get "to" into DPTR */
11970 /* if the operand is already in dptr
11971 then we do nothing else we move the value to dptr */
11972 if (AOP_TYPE (to) != AOP_STR) {
11973 /* if already in DPTR then we need to push */
11974 if (AOP_TYPE(to) == AOP_DPTR) {
11975 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11976 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11977 if (options.model == MODEL_FLAT24)
11978 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11979 emitcode ("pop", "dph");
11980 emitcode ("pop", "dpl");
11982 _startLazyDPSEvaluation ();
11983 /* if this is remateriazable */
11984 if (AOP_TYPE (to) == AOP_IMMD) {
11985 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11986 } else { /* we need to get it byte by byte */
11987 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11988 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11989 if (options.model == MODEL_FLAT24) {
11990 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11993 _endLazyDPSEvaluation ();
11996 freeAsmop (to, NULL, ic, FALSE);
11997 _G.dptrInUse = _G.dptr1InUse = 1;
11998 aopOp (count, ic->next->next, FALSE,FALSE);
11999 lbl =newiTempLabel(NULL);
12001 /* now for the actual copy */
12002 if (AOP_TYPE(count) == AOP_LIT &&
12003 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12004 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12006 emitcode ("lcall","__bi_memcpyc2x_s");
12008 emitcode ("lcall","__bi_memcpyx2x_s");
12010 freeAsmop (count, NULL, ic, FALSE);
12012 symbol *lbl1 = newiTempLabel(NULL);
12014 emitcode (";"," Auto increment but no djnz");
12015 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12016 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12017 freeAsmop (count, NULL, ic, FALSE);
12018 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12019 emitcode ("","!tlabeldef",lbl->key+100);
12021 emitcode ("clr","a");
12022 emitcode ("movc", "a,@a+dptr");
12024 emitcode ("movx", "a,@dptr");
12025 emitcode ("movx", "@dptr,a");
12026 emitcode ("inc", "dptr");
12027 emitcode ("inc", "dptr");
12028 emitcode ("mov","a,b");
12029 emitcode ("orl","a,_ap");
12030 emitcode ("jz","!tlabel",lbl1->key+100);
12031 emitcode ("mov","a,_ap");
12032 emitcode ("add","a,#!constbyte",0xFF);
12033 emitcode ("mov","_ap,a");
12034 emitcode ("mov","a,b");
12035 emitcode ("addc","a,#!constbyte",0xFF);
12036 emitcode ("mov","b,a");
12037 emitcode ("sjmp","!tlabel",lbl->key+100);
12038 emitcode ("","!tlabeldef",lbl1->key+100);
12040 emitcode ("mov", "dps,#0");
12041 _G.dptrInUse = _G.dptr1InUse = 0;
12042 unsavermask(rsave);
12046 /*-----------------------------------------------------------------*/
12047 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
12048 /*-----------------------------------------------------------------*/
12049 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
12051 operand *from , *to , *count;
12056 /* we know it has to be 3 parameters */
12057 assert (nparms == 3);
12059 rsave = newBitVect(16);
12060 /* save DPTR if it needs to be saved */
12061 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12062 if (bitVectBitValue(ic->rMask,i))
12063 rsave = bitVectSetBit(rsave,i);
12065 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12066 ds390_rUmaskForOp (IC_RESULT(ic))));
12073 aopOp (from, ic->next, FALSE, FALSE);
12075 /* get from into DPTR1 */
12076 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12077 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12078 if (options.model == MODEL_FLAT24) {
12079 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12082 freeAsmop (from, NULL, ic, FALSE);
12083 aopOp (to, ic, FALSE, FALSE);
12084 /* get "to" into DPTR */
12085 /* if the operand is already in dptr
12086 then we do nothing else we move the value to dptr */
12087 if (AOP_TYPE (to) != AOP_STR) {
12088 /* if already in DPTR then we need to push */
12089 if (AOP_TYPE(to) == AOP_DPTR) {
12090 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12091 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12092 if (options.model == MODEL_FLAT24)
12093 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12094 emitcode ("pop", "dph");
12095 emitcode ("pop", "dpl");
12097 _startLazyDPSEvaluation ();
12098 /* if this is remateriazable */
12099 if (AOP_TYPE (to) == AOP_IMMD) {
12100 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12101 } else { /* we need to get it byte by byte */
12102 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12103 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12104 if (options.model == MODEL_FLAT24) {
12105 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12108 _endLazyDPSEvaluation ();
12111 freeAsmop (to, NULL, ic, FALSE);
12112 _G.dptrInUse = _G.dptr1InUse = 1;
12113 aopOp (count, ic->next->next, FALSE,FALSE);
12114 lbl =newiTempLabel(NULL);
12115 lbl2 =newiTempLabel(NULL);
12117 /* now for the actual compare */
12118 if (AOP_TYPE(count) == AOP_LIT &&
12119 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12120 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12122 emitcode("lcall","__bi_memcmpc2x_s");
12124 emitcode("lcall","__bi_memcmpx2x_s");
12125 freeAsmop (count, NULL, ic, FALSE);
12126 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12127 aopPut(AOP(IC_RESULT(ic)),"a",0);
12128 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12130 symbol *lbl1 = newiTempLabel(NULL);
12132 emitcode("push","ar0");
12133 emitcode (";"," Auto increment but no djnz");
12134 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12135 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12136 freeAsmop (count, NULL, ic, FALSE);
12137 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12138 emitcode ("","!tlabeldef",lbl->key+100);
12140 emitcode ("clr","a");
12141 emitcode ("movc", "a,@a+dptr");
12143 emitcode ("movx", "a,@dptr");
12144 emitcode ("mov","r0,a");
12145 emitcode ("movx", "a,@dptr");
12146 emitcode ("clr","c");
12147 emitcode ("subb","a,r0");
12148 emitcode ("jnz","!tlabel",lbl2->key+100);
12149 emitcode ("inc", "dptr");
12150 emitcode ("inc", "dptr");
12151 emitcode ("mov","a,b");
12152 emitcode ("orl","a,_ap");
12153 emitcode ("jz","!tlabel",lbl1->key+100);
12154 emitcode ("mov","a,_ap");
12155 emitcode ("add","a,#!constbyte",0xFF);
12156 emitcode ("mov","_ap,a");
12157 emitcode ("mov","a,b");
12158 emitcode ("addc","a,#!constbyte",0xFF);
12159 emitcode ("mov","b,a");
12160 emitcode ("sjmp","!tlabel",lbl->key+100);
12161 emitcode ("","!tlabeldef",lbl1->key+100);
12162 emitcode ("clr","a");
12163 emitcode ("","!tlabeldef",lbl2->key+100);
12164 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12165 aopPut(AOP(IC_RESULT(ic)),"a",0);
12166 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12167 emitcode("pop","ar0");
12168 emitcode ("mov", "dps,#0");
12170 _G.dptrInUse = _G.dptr1InUse = 0;
12171 unsavermask(rsave);
12175 /*-----------------------------------------------------------------*/
12176 /* genInp - gen code for __builtin_inp read data from a mem mapped */
12177 /* port, first parameter output area second parameter pointer to */
12178 /* port third parameter count */
12179 /*-----------------------------------------------------------------*/
12180 static void genInp( iCode *ic, int nparms, operand **parms)
12182 operand *from , *to , *count;
12187 /* we know it has to be 3 parameters */
12188 assert (nparms == 3);
12190 rsave = newBitVect(16);
12191 /* save DPTR if it needs to be saved */
12192 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12193 if (bitVectBitValue(ic->rMask,i))
12194 rsave = bitVectSetBit(rsave,i);
12196 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12197 ds390_rUmaskForOp (IC_RESULT(ic))));
12204 aopOp (from, ic->next, FALSE, FALSE);
12206 /* get from into DPTR1 */
12207 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12208 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12209 if (options.model == MODEL_FLAT24) {
12210 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12213 freeAsmop (from, NULL, ic, FALSE);
12214 aopOp (to, ic, FALSE, FALSE);
12215 /* get "to" into DPTR */
12216 /* if the operand is already in dptr
12217 then we do nothing else we move the value to dptr */
12218 if (AOP_TYPE (to) != AOP_STR) {
12219 /* if already in DPTR then we need to push */
12220 if (AOP_TYPE(to) == AOP_DPTR) {
12221 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12222 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12223 if (options.model == MODEL_FLAT24)
12224 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12225 emitcode ("pop", "dph");
12226 emitcode ("pop", "dpl");
12228 _startLazyDPSEvaluation ();
12229 /* if this is remateriazable */
12230 if (AOP_TYPE (to) == AOP_IMMD) {
12231 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12232 } else { /* we need to get it byte by byte */
12233 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12234 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12235 if (options.model == MODEL_FLAT24) {
12236 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12239 _endLazyDPSEvaluation ();
12242 freeAsmop (to, NULL, ic, FALSE);
12244 _G.dptrInUse = _G.dptr1InUse = 1;
12245 aopOp (count, ic->next->next, FALSE,FALSE);
12246 lbl =newiTempLabel(NULL);
12248 /* now for the actual copy */
12249 if (AOP_TYPE(count) == AOP_LIT &&
12250 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12251 emitcode (";","OH JOY auto increment with djnz (very fast)");
12252 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12253 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12254 freeAsmop (count, NULL, ic, FALSE);
12255 emitcode ("","!tlabeldef",lbl->key+100);
12256 emitcode ("movx", "a,@dptr"); /* read data from port */
12257 emitcode ("dec","dps"); /* switch to DPTR */
12258 emitcode ("movx", "@dptr,a"); /* save into location */
12259 emitcode ("inc", "dptr"); /* point to next area */
12260 emitcode ("inc","dps"); /* switch to DPTR2 */
12261 emitcode ("djnz","b,!tlabel",lbl->key+100);
12263 symbol *lbl1 = newiTempLabel(NULL);
12265 emitcode (";"," Auto increment but no djnz");
12266 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12267 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12268 freeAsmop (count, NULL, ic, FALSE);
12269 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12270 emitcode ("","!tlabeldef",lbl->key+100);
12271 emitcode ("movx", "a,@dptr");
12272 emitcode ("dec","dps"); /* switch to DPTR */
12273 emitcode ("movx", "@dptr,a");
12274 emitcode ("inc", "dptr");
12275 emitcode ("inc","dps"); /* switch to DPTR2 */
12276 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
12277 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
12278 emitcode ("mov","a,b");
12279 emitcode ("orl","a,_ap");
12280 emitcode ("jz","!tlabel",lbl1->key+100);
12281 emitcode ("mov","a,_ap");
12282 emitcode ("add","a,#!constbyte",0xFF);
12283 emitcode ("mov","_ap,a");
12284 emitcode ("mov","a,b");
12285 emitcode ("addc","a,#!constbyte",0xFF);
12286 emitcode ("mov","b,a");
12287 emitcode ("sjmp","!tlabel",lbl->key+100);
12288 emitcode ("","!tlabeldef",lbl1->key+100);
12290 emitcode ("mov", "dps,#0");
12291 _G.dptrInUse = _G.dptr1InUse = 0;
12292 unsavermask(rsave);
12296 /*-----------------------------------------------------------------*/
12297 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
12298 /* port, first parameter output area second parameter pointer to */
12299 /* port third parameter count */
12300 /*-----------------------------------------------------------------*/
12301 static void genOutp( iCode *ic, int nparms, operand **parms)
12303 operand *from , *to , *count;
12308 /* we know it has to be 3 parameters */
12309 assert (nparms == 3);
12311 rsave = newBitVect(16);
12312 /* save DPTR if it needs to be saved */
12313 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12314 if (bitVectBitValue(ic->rMask,i))
12315 rsave = bitVectSetBit(rsave,i);
12317 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12318 ds390_rUmaskForOp (IC_RESULT(ic))));
12325 aopOp (from, ic->next, FALSE, FALSE);
12327 /* get from into DPTR1 */
12328 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12329 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12330 if (options.model == MODEL_FLAT24) {
12331 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12334 freeAsmop (from, NULL, ic, FALSE);
12335 aopOp (to, ic, FALSE, FALSE);
12336 /* get "to" into DPTR */
12337 /* if the operand is already in dptr
12338 then we do nothing else we move the value to dptr */
12339 if (AOP_TYPE (to) != AOP_STR) {
12340 /* if already in DPTR then we need to push */
12341 if (AOP_TYPE(to) == AOP_DPTR) {
12342 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12343 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12344 if (options.model == MODEL_FLAT24)
12345 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12346 emitcode ("pop", "dph");
12347 emitcode ("pop", "dpl");
12349 _startLazyDPSEvaluation ();
12350 /* if this is remateriazable */
12351 if (AOP_TYPE (to) == AOP_IMMD) {
12352 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12353 } else { /* we need to get it byte by byte */
12354 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12355 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12356 if (options.model == MODEL_FLAT24) {
12357 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12360 _endLazyDPSEvaluation ();
12363 freeAsmop (to, NULL, ic, FALSE);
12365 _G.dptrInUse = _G.dptr1InUse = 1;
12366 aopOp (count, ic->next->next, FALSE,FALSE);
12367 lbl =newiTempLabel(NULL);
12369 /* now for the actual copy */
12370 if (AOP_TYPE(count) == AOP_LIT &&
12371 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12372 emitcode (";","OH JOY auto increment with djnz (very fast)");
12373 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12374 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12375 emitcode ("","!tlabeldef",lbl->key+100);
12376 emitcode ("movx", "a,@dptr"); /* read data from port */
12377 emitcode ("inc","dps"); /* switch to DPTR2 */
12378 emitcode ("movx", "@dptr,a"); /* save into location */
12379 emitcode ("inc", "dptr"); /* point to next area */
12380 emitcode ("dec","dps"); /* switch to DPTR */
12381 emitcode ("djnz","b,!tlabel",lbl->key+100);
12382 freeAsmop (count, NULL, ic, FALSE);
12384 symbol *lbl1 = newiTempLabel(NULL);
12386 emitcode (";"," Auto increment but no djnz");
12387 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12388 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12389 freeAsmop (count, NULL, ic, FALSE);
12390 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12391 emitcode ("","!tlabeldef",lbl->key+100);
12392 emitcode ("movx", "a,@dptr");
12393 emitcode ("inc", "dptr");
12394 emitcode ("inc","dps"); /* switch to DPTR2 */
12395 emitcode ("movx", "@dptr,a");
12396 emitcode ("dec","dps"); /* switch to DPTR */
12397 emitcode ("mov","a,b");
12398 emitcode ("orl","a,_ap");
12399 emitcode ("jz","!tlabel",lbl1->key+100);
12400 emitcode ("mov","a,_ap");
12401 emitcode ("add","a,#!constbyte",0xFF);
12402 emitcode ("mov","_ap,a");
12403 emitcode ("mov","a,b");
12404 emitcode ("addc","a,#!constbyte",0xFF);
12405 emitcode ("mov","b,a");
12406 emitcode ("sjmp","!tlabel",lbl->key+100);
12407 emitcode ("","!tlabeldef",lbl1->key+100);
12409 emitcode ("mov", "dps,#0");
12410 _G.dptrInUse = _G.dptr1InUse = 0;
12411 unsavermask(rsave);
12415 /*-----------------------------------------------------------------*/
12416 /* genSwapW - swap lower & high order bytes */
12417 /*-----------------------------------------------------------------*/
12418 static void genSwapW(iCode *ic, int nparms, operand **parms)
12422 assert (nparms==1);
12425 dest=IC_RESULT(ic);
12427 assert(getSize(operandType(src))==2);
12429 aopOp (src, ic, FALSE, FALSE);
12430 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
12432 MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
12434 freeAsmop (src, NULL, ic, FALSE);
12436 aopOp (dest,ic, FALSE, FALSE);
12437 aopPut(AOP(dest),"b",0);
12438 aopPut(AOP(dest),"a",1);
12439 freeAsmop (dest, NULL, ic, FALSE);
12442 /*-----------------------------------------------------------------*/
12443 /* genMemsetX - gencode for memSetX data */
12444 /*-----------------------------------------------------------------*/
12445 static void genMemsetX(iCode *ic, int nparms, operand **parms)
12447 operand *to , *val , *count;
12453 /* we know it has to be 3 parameters */
12454 assert (nparms == 3);
12460 /* save DPTR if it needs to be saved */
12461 rsave = newBitVect(16);
12462 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12463 if (bitVectBitValue(ic->rMask,i))
12464 rsave = bitVectSetBit(rsave,i);
12466 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12467 ds390_rUmaskForOp (IC_RESULT(ic))));
12470 aopOp (to, ic, FALSE, FALSE);
12471 /* get "to" into DPTR */
12472 /* if the operand is already in dptr
12473 then we do nothing else we move the value to dptr */
12474 if (AOP_TYPE (to) != AOP_STR) {
12475 /* if already in DPTR then we need to push */
12476 if (AOP_TYPE(to) == AOP_DPTR) {
12477 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12478 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12479 if (options.model == MODEL_FLAT24)
12480 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12481 emitcode ("pop", "dph");
12482 emitcode ("pop", "dpl");
12484 _startLazyDPSEvaluation ();
12485 /* if this is remateriazable */
12486 if (AOP_TYPE (to) == AOP_IMMD) {
12487 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12488 } else { /* we need to get it byte by byte */
12489 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12490 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12491 if (options.model == MODEL_FLAT24) {
12492 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12495 _endLazyDPSEvaluation ();
12498 freeAsmop (to, NULL, ic, FALSE);
12500 aopOp (val, ic->next->next, FALSE,FALSE);
12501 aopOp (count, ic->next->next, FALSE,FALSE);
12502 lbl =newiTempLabel(NULL);
12503 /* now for the actual copy */
12504 if (AOP_TYPE(count) == AOP_LIT &&
12505 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12506 l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
12507 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12509 emitcode ("","!tlabeldef",lbl->key+100);
12510 emitcode ("movx", "@dptr,a");
12511 emitcode ("inc", "dptr");
12512 emitcode ("djnz","b,!tlabel",lbl->key+100);
12514 symbol *lbl1 = newiTempLabel(NULL);
12516 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12517 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12518 emitcode ("","!tlabeldef",lbl->key+100);
12519 MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
12520 emitcode ("movx", "@dptr,a");
12521 emitcode ("inc", "dptr");
12522 emitcode ("mov","a,b");
12523 emitcode ("orl","a,_ap");
12524 emitcode ("jz","!tlabel",lbl1->key+100);
12525 emitcode ("mov","a,_ap");
12526 emitcode ("add","a,#!constbyte",0xFF);
12527 emitcode ("mov","_ap,a");
12528 emitcode ("mov","a,b");
12529 emitcode ("addc","a,#!constbyte",0xFF);
12530 emitcode ("mov","b,a");
12531 emitcode ("sjmp","!tlabel",lbl->key+100);
12532 emitcode ("","!tlabeldef",lbl1->key+100);
12534 freeAsmop (count, NULL, ic, FALSE);
12535 unsavermask(rsave);
12538 /*-----------------------------------------------------------------*/
12539 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12540 /*-----------------------------------------------------------------*/
12541 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12544 operand *pnum, *result;
12547 assert (nparms==1);
12548 /* save registers that need to be saved */
12549 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12550 ds390_rUmaskForOp (IC_RESULT(ic))));
12553 aopOp (pnum, ic, FALSE, FALSE);
12554 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12555 freeAsmop (pnum, NULL, ic, FALSE);
12556 emitcode ("lcall","NatLib_LoadPrimitive");
12557 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12558 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
12559 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12560 for (i = (size-1) ; i >= 0 ; i-- ) {
12561 emitcode ("push","a%s",javaRet[i]);
12563 for (i=0; i < size ; i++ ) {
12564 emitcode ("pop","a%s",
12565 aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12568 for (i = 0 ; i < size ; i++ ) {
12569 aopPut(AOP(result),javaRet[i],i);
12572 freeAsmop (result, NULL, ic, FALSE);
12573 unsavermask(rsave);
12576 /*-----------------------------------------------------------------*/
12577 /* genNatLibLoadPointer - calls TINI api function to load pointer */
12578 /*-----------------------------------------------------------------*/
12579 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12582 operand *pnum, *result;
12586 assert (nparms==1);
12587 /* save registers that need to be saved */
12588 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12589 ds390_rUmaskForOp (IC_RESULT(ic))));
12592 aopOp (pnum, ic, FALSE, FALSE);
12593 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12594 freeAsmop (pnum, NULL, ic, FALSE);
12595 emitcode ("lcall","NatLib_LoadPointer");
12596 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12597 if (AOP_TYPE(result)!=AOP_STR) {
12598 for (i = 0 ; i < size ; i++ ) {
12599 aopPut(AOP(result),fReturn[i],i);
12602 freeAsmop (result, NULL, ic, FALSE);
12603 unsavermask(rsave);
12606 /*-----------------------------------------------------------------*/
12607 /* genNatLibInstallStateBlock - */
12608 /*-----------------------------------------------------------------*/
12609 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
12610 operand **parms, const char *name)
12613 operand *psb, *handle;
12614 assert (nparms==2);
12616 /* save registers that need to be saved */
12617 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12618 ds390_rUmaskForOp (IC_RESULT(ic))));
12622 /* put pointer to state block into DPTR1 */
12623 aopOp (psb, ic, FALSE, FALSE);
12624 if (AOP_TYPE (psb) == AOP_IMMD) {
12625 emitcode ("mov","dps,#1");
12626 emitcode ("mov", "dptr,%s",
12627 aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12628 emitcode ("mov","dps,#0");
12630 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12631 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12632 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12634 freeAsmop (psb, NULL, ic, FALSE);
12636 /* put libraryID into DPTR */
12637 emitcode ("mov","dptr,#LibraryID");
12639 /* put handle into r3:r2 */
12640 aopOp (handle, ic, FALSE, FALSE);
12641 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12642 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12643 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12644 emitcode ("pop","ar3");
12645 emitcode ("pop","ar2");
12647 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12648 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12650 freeAsmop (psb, NULL, ic, FALSE);
12652 /* make the call */
12653 emitcode ("lcall","NatLib_Install%sStateBlock",name);
12655 /* put return value into place*/
12657 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12659 aopPut(AOP(IC_RESULT(ic)),"a",0);
12660 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12661 unsavermask(rsave);
12664 /*-----------------------------------------------------------------*/
12665 /* genNatLibRemoveStateBlock - */
12666 /*-----------------------------------------------------------------*/
12667 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12673 /* save registers that need to be saved */
12674 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12675 ds390_rUmaskForOp (IC_RESULT(ic))));
12677 /* put libraryID into DPTR */
12678 emitcode ("mov","dptr,#LibraryID");
12679 /* make the call */
12680 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12681 unsavermask(rsave);
12684 /*-----------------------------------------------------------------*/
12685 /* genNatLibGetStateBlock - */
12686 /*-----------------------------------------------------------------*/
12687 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12688 operand **parms,const char *name)
12691 symbol *lbl = newiTempLabel(NULL);
12694 /* save registers that need to be saved */
12695 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12696 ds390_rUmaskForOp (IC_RESULT(ic))));
12698 /* put libraryID into DPTR */
12699 emitcode ("mov","dptr,#LibraryID");
12700 /* make the call */
12701 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12702 emitcode ("jnz","!tlabel",lbl->key+100);
12704 /* put return value into place */
12705 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12706 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12707 emitcode ("push","ar3");
12708 emitcode ("push","ar2");
12709 emitcode ("pop","%s",
12710 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12711 emitcode ("pop","%s",
12712 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12714 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12715 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12717 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12718 emitcode ("","!tlabeldef",lbl->key+100);
12719 unsavermask(rsave);
12722 /*-----------------------------------------------------------------*/
12723 /* genMMMalloc - */
12724 /*-----------------------------------------------------------------*/
12725 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12726 int size, const char *name)
12731 symbol *lbl = newiTempLabel(NULL);
12733 assert (nparms == 1);
12734 /* save registers that need to be saved */
12735 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12736 ds390_rUmaskForOp (IC_RESULT(ic))));
12739 aopOp (bsize,ic,FALSE,FALSE);
12741 /* put the size in R4-R2 */
12742 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12743 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12744 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12746 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12747 emitcode("pop","ar4");
12749 emitcode("pop","ar3");
12750 emitcode("pop","ar2");
12752 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12753 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12755 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12758 freeAsmop (bsize, NULL, ic, FALSE);
12760 /* make the call */
12761 emitcode ("lcall","MM_%s",name);
12762 emitcode ("jz","!tlabel",lbl->key+100);
12763 emitcode ("mov","r2,#!constbyte",0xff);
12764 emitcode ("mov","r3,#!constbyte",0xff);
12765 emitcode ("","!tlabeldef",lbl->key+100);
12766 /* we don't care about the pointer : we just save the handle */
12767 rsym = OP_SYMBOL(IC_RESULT(ic));
12768 if (rsym->liveFrom != rsym->liveTo) {
12769 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12770 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12771 emitcode ("push","ar3");
12772 emitcode ("push","ar2");
12773 emitcode ("pop","%s",
12774 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12775 emitcode ("pop","%s",
12776 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12778 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12779 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12781 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12783 unsavermask(rsave);
12786 /*-----------------------------------------------------------------*/
12788 /*-----------------------------------------------------------------*/
12789 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12794 assert (nparms == 1);
12795 /* save registers that need to be saved */
12796 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12797 ds390_rUmaskForOp (IC_RESULT(ic))));
12800 aopOp (handle,ic,FALSE,FALSE);
12802 /* put the size in R4-R2 */
12803 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12804 emitcode("push","%s",
12805 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12806 emitcode("push","%s",
12807 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12808 emitcode("pop","ar3");
12809 emitcode("pop","ar2");
12811 emitcode ("mov","r2,%s",
12812 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12813 emitcode ("mov","r3,%s",
12814 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12816 freeAsmop (handle, NULL, ic, FALSE);
12818 /* make the call */
12819 emitcode ("lcall","MM_Deref");
12822 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12823 if (rsym->liveFrom != rsym->liveTo) {
12824 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12825 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12826 _startLazyDPSEvaluation ();
12828 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12829 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12830 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12832 _endLazyDPSEvaluation ();
12837 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12838 unsavermask(rsave);
12841 /*-----------------------------------------------------------------*/
12842 /* genMMUnrestrictedPersist - */
12843 /*-----------------------------------------------------------------*/
12844 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12849 assert (nparms == 1);
12850 /* save registers that need to be saved */
12851 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12852 ds390_rUmaskForOp (IC_RESULT(ic))));
12855 aopOp (handle,ic,FALSE,FALSE);
12857 /* put the size in R3-R2 */
12858 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12859 emitcode("push","%s",
12860 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12861 emitcode("push","%s",
12862 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12863 emitcode("pop","ar3");
12864 emitcode("pop","ar2");
12866 emitcode ("mov","r2,%s",
12867 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12868 emitcode ("mov","r3,%s",
12869 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12871 freeAsmop (handle, NULL, ic, FALSE);
12873 /* make the call */
12874 emitcode ("lcall","MM_UnrestrictedPersist");
12877 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12878 if (rsym->liveFrom != rsym->liveTo) {
12879 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12880 aopPut(AOP(IC_RESULT(ic)),"a",0);
12881 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12884 unsavermask(rsave);
12887 /*-----------------------------------------------------------------*/
12888 /* genSystemExecJavaProcess - */
12889 /*-----------------------------------------------------------------*/
12890 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12893 operand *handle, *pp;
12895 assert (nparms==2);
12896 /* save registers that need to be saved */
12897 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12898 ds390_rUmaskForOp (IC_RESULT(ic))));
12903 /* put the handle in R3-R2 */
12904 aopOp (handle,ic,FALSE,FALSE);
12905 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12906 emitcode("push","%s",
12907 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12908 emitcode("push","%s",
12909 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12910 emitcode("pop","ar3");
12911 emitcode("pop","ar2");
12913 emitcode ("mov","r2,%s",
12914 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12915 emitcode ("mov","r3,%s",
12916 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12918 freeAsmop (handle, NULL, ic, FALSE);
12920 /* put pointer in DPTR */
12921 aopOp (pp,ic,FALSE,FALSE);
12922 if (AOP_TYPE(pp) == AOP_IMMD) {
12923 emitcode ("mov", "dptr,%s",
12924 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12925 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12926 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12927 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12928 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12930 freeAsmop (handle, NULL, ic, FALSE);
12932 /* make the call */
12933 emitcode ("lcall","System_ExecJavaProcess");
12935 /* put result in place */
12937 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12938 if (rsym->liveFrom != rsym->liveTo) {
12939 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12940 aopPut(AOP(IC_RESULT(ic)),"a",0);
12941 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12945 unsavermask(rsave);
12948 /*-----------------------------------------------------------------*/
12949 /* genSystemRTCRegisters - */
12950 /*-----------------------------------------------------------------*/
12951 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12957 assert (nparms==1);
12958 /* save registers that need to be saved */
12959 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12960 ds390_rUmaskForOp (IC_RESULT(ic))));
12963 /* put pointer in DPTR */
12964 aopOp (pp,ic,FALSE,FALSE);
12965 if (AOP_TYPE (pp) == AOP_IMMD) {
12966 emitcode ("mov","dps,#1");
12967 emitcode ("mov", "dptr,%s",
12968 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12969 emitcode ("mov","dps,#0");
12971 emitcode ("mov","dpl1,%s",
12972 aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12973 emitcode ("mov","dph1,%s",
12974 aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12975 emitcode ("mov","dpx1,%s",
12976 aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12978 freeAsmop (pp, NULL, ic, FALSE);
12980 /* make the call */
12981 emitcode ("lcall","System_%sRTCRegisters",name);
12983 unsavermask(rsave);
12986 /*-----------------------------------------------------------------*/
12987 /* genSystemThreadSleep - */
12988 /*-----------------------------------------------------------------*/
12989 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12994 assert (nparms==1);
12995 /* save registers that need to be saved */
12996 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12997 ds390_rUmaskForOp (IC_RESULT(ic))));
13000 aopOp(to,ic,FALSE,FALSE);
13001 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
13002 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
13003 emitcode ("push","%s",
13004 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
13005 emitcode ("push","%s",
13006 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
13007 emitcode ("push","%s",
13008 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
13009 emitcode ("push","%s",
13010 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
13011 emitcode ("pop","ar3");
13012 emitcode ("pop","ar2");
13013 emitcode ("pop","ar1");
13014 emitcode ("pop","ar0");
13016 emitcode ("mov","r0,%s",
13017 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
13018 emitcode ("mov","r1,%s",
13019 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
13020 emitcode ("mov","r2,%s",
13021 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
13022 emitcode ("mov","r3,%s",
13023 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
13025 freeAsmop (to, NULL, ic, FALSE);
13027 /* suspend in acc */
13029 aopOp(s,ic,FALSE,FALSE);
13030 emitcode ("mov","a,%s",
13031 aopGet(AOP(s),0,FALSE,TRUE,NULL));
13032 freeAsmop (s, NULL, ic, FALSE);
13034 /* make the call */
13035 emitcode ("lcall","System_%s",name);
13037 unsavermask(rsave);
13040 /*-----------------------------------------------------------------*/
13041 /* genSystemThreadResume - */
13042 /*-----------------------------------------------------------------*/
13043 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
13048 assert (nparms==2);
13049 /* save registers that need to be saved */
13050 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13051 ds390_rUmaskForOp (IC_RESULT(ic))));
13057 aopOp(pid,ic,FALSE,FALSE);
13058 emitcode ("mov","r0,%s",
13059 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13060 freeAsmop (pid, NULL, ic, FALSE);
13063 aopOp(tid,ic,FALSE,FALSE);
13064 emitcode ("mov","a,%s",
13065 aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
13066 freeAsmop (tid, NULL, ic, FALSE);
13068 emitcode ("lcall","System_ThreadResume");
13070 /* put result into place */
13072 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13073 if (rsym->liveFrom != rsym->liveTo) {
13074 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13075 aopPut(AOP(IC_RESULT(ic)),"a",0);
13076 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13079 unsavermask(rsave);
13082 /*-----------------------------------------------------------------*/
13083 /* genSystemProcessResume - */
13084 /*-----------------------------------------------------------------*/
13085 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
13090 assert (nparms==1);
13091 /* save registers that need to be saved */
13092 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13093 ds390_rUmaskForOp (IC_RESULT(ic))));
13098 aopOp(pid,ic,FALSE,FALSE);
13099 emitcode ("mov","a,%s",
13100 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13101 freeAsmop (pid, NULL, ic, FALSE);
13103 emitcode ("lcall","System_ProcessResume");
13105 unsavermask(rsave);
13108 /*-----------------------------------------------------------------*/
13110 /*-----------------------------------------------------------------*/
13111 static void genSystem (iCode *ic,int nparms,char *name)
13113 assert(nparms == 0);
13115 emitcode ("lcall","System_%s",name);
13118 /*-----------------------------------------------------------------*/
13119 /* genSystemPoll - */
13120 /*-----------------------------------------------------------------*/
13121 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
13126 assert (nparms==1);
13127 /* save registers that need to be saved */
13128 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13129 ds390_rUmaskForOp (IC_RESULT(ic))));
13132 aopOp (fp,ic,FALSE,FALSE);
13133 if (AOP_TYPE (fp) == AOP_IMMD) {
13134 emitcode ("mov", "dptr,%s",
13135 aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
13136 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
13137 emitcode ("mov","dpl,%s",
13138 aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
13139 emitcode ("mov","dph,%s",
13140 aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
13141 emitcode ("mov","dpx,%s",
13142 aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
13144 freeAsmop (fp, NULL, ic, FALSE);
13146 emitcode ("lcall","System_%sPoll",name);
13148 /* put result into place */
13150 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13151 if (rsym->liveFrom != rsym->liveTo) {
13152 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13153 aopPut(AOP(IC_RESULT(ic)),"a",0);
13154 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13157 unsavermask(rsave);
13160 /*-----------------------------------------------------------------*/
13161 /* genSystemGetCurrentID - */
13162 /*-----------------------------------------------------------------*/
13163 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
13165 assert (nparms==0);
13167 emitcode ("lcall","System_GetCurrent%sId",name);
13168 /* put result into place */
13170 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13171 if (rsym->liveFrom != rsym->liveTo) {
13172 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13173 aopPut(AOP(IC_RESULT(ic)),"a",0);
13174 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13179 /*-----------------------------------------------------------------*/
13180 /* genDummyRead - generate code for dummy read of volatiles */
13181 /*-----------------------------------------------------------------*/
13183 genDummyRead (iCode * ic)
13188 D(emitcode("; genDummyRead",""));
13190 op = IC_RIGHT (ic);
13191 if (op && IS_SYMOP (op))
13193 aopOp (op, ic, FALSE, FALSE);
13195 /* if the result is a bit */
13196 if (AOP_TYPE (op) == AOP_CRY)
13197 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13200 /* bit variables done */
13202 size = AOP_SIZE (op);
13206 MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13211 freeAsmop (op, NULL, ic, TRUE);
13215 if (op && IS_SYMOP (op))
13217 aopOp (op, ic, FALSE, FALSE);
13219 /* if the result is a bit */
13220 if (AOP_TYPE (op) == AOP_CRY)
13221 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13224 /* bit variables done */
13226 size = AOP_SIZE (op);
13230 MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13235 freeAsmop (op, NULL, ic, TRUE);
13240 /*-----------------------------------------------------------------*/
13241 /* genCritical - generate code for start of a critical sequence */
13242 /*-----------------------------------------------------------------*/
13244 genCritical (iCode *ic)
13246 symbol *tlbl = newiTempLabel (NULL);
13248 D(emitcode("; genCritical",""));
13250 if (IC_RESULT (ic))
13251 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
13253 emitcode ("setb", "c");
13254 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
13255 emitcode ("clr", "c");
13256 emitcode ("", "%05d$:", (tlbl->key + 100));
13258 if (IC_RESULT (ic))
13259 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
13261 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
13263 if (IC_RESULT (ic))
13264 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13267 /*-----------------------------------------------------------------*/
13268 /* genEndCritical - generate code for end of a critical sequence */
13269 /*-----------------------------------------------------------------*/
13271 genEndCritical (iCode *ic)
13273 D(emitcode("; genEndCritical",""));
13277 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
13278 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
13280 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
13281 emitcode ("mov", "ea,c");
13285 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE));
13286 emitcode ("rrc", "a");
13287 emitcode ("mov", "ea,c");
13289 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
13293 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
13294 emitcode ("mov", "ea,c");
13300 /*-----------------------------------------------------------------*/
13301 /* genBuiltIn - calls the appropriate function to generating code */
13302 /* for a built in function */
13303 /*-----------------------------------------------------------------*/
13304 static void genBuiltIn (iCode *ic)
13306 operand *bi_parms[MAX_BUILTIN_ARGS];
13311 /* get all the arguments for a built in function */
13312 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
13314 /* which function is it */
13315 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
13316 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
13317 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
13318 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
13319 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
13320 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
13321 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
13322 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
13323 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
13324 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
13325 genMemsetX(bi_iCode,nbi_parms,bi_parms);
13326 } else if (strcmp(bif->name,"__builtin_inp")==0) {
13327 genInp(bi_iCode,nbi_parms,bi_parms);
13328 } else if (strcmp(bif->name,"__builtin_outp")==0) {
13329 genOutp(bi_iCode,nbi_parms,bi_parms);
13330 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
13331 genSwapW(bi_iCode,nbi_parms,bi_parms);
13332 /* JavaNative builtIns */
13333 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
13334 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
13335 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
13336 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
13337 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
13338 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
13339 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
13340 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
13341 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
13342 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13343 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
13344 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13345 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
13346 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
13347 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
13348 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
13349 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
13350 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13351 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
13352 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13353 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
13354 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
13355 } else if (strcmp(bif->name,"MM_Malloc")==0) {
13356 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
13357 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
13358 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
13359 } else if (strcmp(bif->name,"MM_Free")==0) {
13360 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
13361 } else if (strcmp(bif->name,"MM_Deref")==0) {
13362 genMMDeref(bi_iCode,nbi_parms,bi_parms);
13363 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
13364 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
13365 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
13366 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
13367 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
13368 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
13369 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
13370 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
13371 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
13372 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
13373 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
13374 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
13375 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
13376 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
13377 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
13378 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
13379 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13380 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13381 } else if (strcmp(bif->name,"System_SaveThread")==0) {
13382 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13383 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13384 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13385 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
13386 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
13387 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
13388 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
13389 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
13390 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
13391 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
13392 genSystem(bi_iCode,nbi_parms,"ProcessYield");
13393 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
13394 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
13395 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
13396 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
13397 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
13398 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
13399 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
13400 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
13401 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
13402 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
13404 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
13410 /*-----------------------------------------------------------------*/
13411 /* gen390Code - generate code for Dallas 390 based controllers */
13412 /*-----------------------------------------------------------------*/
13414 gen390Code (iCode * lic)
13419 lineHead = lineCurr = NULL;
13420 dptrn[1][0] = "dpl1";
13421 dptrn[1][1] = "dph1";
13422 dptrn[1][2] = "dpx1";
13424 if (options.model == MODEL_FLAT24) {
13425 fReturnSizeDS390 = 5;
13426 fReturn = fReturn24;
13428 fReturnSizeDS390 = 4;
13429 fReturn = fReturn16;
13430 options.stack10bit=0;
13433 /* print the allocation information */
13434 if (allocInfo && currFunc)
13435 printAllocInfo (currFunc, codeOutFile);
13437 /* if debug information required */
13438 if (options.debug && currFunc)
13440 debugFile->writeFunction (currFunc, lic);
13442 /* stack pointer name */
13443 if (options.useXstack)
13449 for (ic = lic; ic; ic = ic->next)
13451 _G.current_iCode = ic;
13453 if (ic->lineno && cln != ic->lineno)
13457 debugFile->writeCLine (ic);
13459 if (!options.noCcodeInAsm) {
13460 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
13461 printCLine(ic->filename, ic->lineno));
13465 if (options.iCodeInAsm) {
13466 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
13468 /* if the result is marked as
13469 spilt and rematerializable or code for
13470 this has already been generated then
13472 if (resultRemat (ic) || ic->generated)
13475 /* depending on the operation */
13495 /* IPOP happens only when trying to restore a
13496 spilt live range, if there is an ifx statement
13497 following this pop then the if statement might
13498 be using some of the registers being popped which
13499 would destory the contents of the register so
13500 we need to check for this condition and handle it */
13502 ic->next->op == IFX &&
13503 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
13504 genIfx (ic->next, ic);
13522 genEndFunction (ic);
13542 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
13559 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
13563 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
13570 /* note these two are xlated by algebraic equivalence
13571 during parsing SDCC.y */
13572 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13573 "got '>=' or '<=' shouldn't have come here");
13577 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
13589 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
13593 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
13597 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
13621 genRightShift (ic);
13624 case GET_VALUE_AT_ADDRESS:
13625 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13629 if (POINTER_SET (ic))
13630 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13656 if (ic->builtinSEND) genBuiltIn(ic);
13657 else addSet (&_G.sendSet, ic);
13660 case DUMMY_READ_VOLATILE:
13669 genEndCritical (ic);
13676 #if 0 // obsolete, and buggy for != xdata
13688 /* now we are ready to call the
13689 peep hole optimizer */
13690 if (!options.nopeep)
13691 peepHole (&lineHead);
13693 /* now do the actual printing */
13694 printLine (lineHead, codeOutFile);