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 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1936 tlbl=newiTempLabel(NULL);
1937 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, FALSE, NULL);
1938 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC ||
1939 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1940 IS_AOP_PREG (IC_LEFT (ic)))
1942 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1947 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1949 emitcode ("", "%05d$:", tlbl->key+100);
1950 outBitC (IC_RESULT(ic));
1954 size = AOP_SIZE (IC_RESULT (ic));
1955 _startLazyDPSEvaluation ();
1958 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1959 emitcode ("cpl", "a");
1960 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1962 _endLazyDPSEvaluation ();
1966 /* release the aops */
1967 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1968 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1971 /*-----------------------------------------------------------------*/
1972 /* genUminusFloat - unary minus for floating points */
1973 /*-----------------------------------------------------------------*/
1975 genUminusFloat (operand * op, operand * result)
1977 int size, offset = 0;
1979 D(emitcode (";", "genUminusFloat"););
1981 /* for this we just copy and then flip the bit */
1983 _startLazyDPSEvaluation ();
1984 size = AOP_SIZE (op) - 1;
1988 aopPut (AOP (result),
1989 aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1994 MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1996 emitcode ("cpl", "acc.7");
1997 aopPut (AOP (result), "a", offset);
1998 _endLazyDPSEvaluation ();
2001 /*-----------------------------------------------------------------*/
2002 /* genUminus - unary minus code generation */
2003 /*-----------------------------------------------------------------*/
2005 genUminus (iCode * ic)
2010 D (emitcode (";", "genUminus "););
2013 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2014 aopOp (IC_RESULT (ic), ic, TRUE, (AOP_TYPE(IC_LEFT (ic)) == AOP_DPTR));
2016 /* if both in bit space then special
2018 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2019 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2022 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2023 emitcode ("cpl", "c");
2024 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2028 optype = operandType (IC_LEFT (ic));
2030 /* if float then do float stuff */
2031 if (IS_FLOAT (optype))
2033 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2037 /* otherwise subtract from zero */
2038 size = AOP_SIZE (IC_LEFT (ic));
2040 _startLazyDPSEvaluation ();
2043 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
2044 if (!strcmp (l, "a"))
2048 emitcode ("cpl", "a");
2049 emitcode ("addc", "a,#0");
2055 emitcode ("clr", "a");
2056 emitcode ("subb", "a,%s", l);
2058 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2060 _endLazyDPSEvaluation ();
2062 /* if any remaining bytes in the result */
2063 /* we just need to propagate the sign */
2064 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
2066 emitcode ("rlc", "a");
2067 emitcode ("subb", "a,acc");
2069 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2073 /* release the aops */
2074 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2075 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2078 /*-----------------------------------------------------------------*/
2079 /* savermask - saves registers in the mask */
2080 /*-----------------------------------------------------------------*/
2081 static void savermask(bitVect *rs_mask)
2084 if (options.useXstack) {
2085 if (bitVectBitValue (rs_mask, R0_IDX))
2086 emitcode ("mov", "b,r0");
2087 emitcode ("mov", "r0,%s", spname);
2088 for (i = 0; i < ds390_nRegs; i++) {
2089 if (bitVectBitValue (rs_mask, i)) {
2091 emitcode ("mov", "a,b");
2093 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2094 emitcode ("movx", "@r0,a");
2095 emitcode ("inc", "r0");
2098 emitcode ("mov", "%s,r0", spname);
2099 if (bitVectBitValue (rs_mask, R0_IDX))
2100 emitcode ("mov", "r0,b");
2102 for (i = 0; i < ds390_nRegs; i++) {
2103 if (bitVectBitValue (rs_mask, i))
2104 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2109 /*-----------------------------------------------------------------*/
2110 /* saveRegisters - will look for a call and save the registers */
2111 /*-----------------------------------------------------------------*/
2113 saveRegisters (iCode * lic)
2119 for (ic = lic; ic; ic = ic->next)
2120 if (ic->op == CALL || ic->op == PCALL)
2125 fprintf (stderr, "found parameter push with no function call\n");
2129 /* if the registers have been saved already then
2132 || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2135 /* special case if DPTR alive across a function call then must save it
2136 even though callee saves */
2137 if (IS_SYMOP(IC_LEFT(ic)) &&
2138 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2140 rsave = newBitVect(ic->rMask->size);
2141 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2142 if (bitVectBitValue(ic->rMask,i))
2143 rsave = bitVectSetBit(rsave,i);
2145 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2147 /* safe the registers in use at this time but skip the
2148 ones for the result */
2149 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2150 ds390_rUmaskForOp (IC_RESULT(ic)));
2156 /*-----------------------------------------------------------------*/
2157 /* usavermask - restore registers with mask */
2158 /*-----------------------------------------------------------------*/
2159 static void unsavermask(bitVect *rs_mask)
2162 if (options.useXstack) {
2163 emitcode ("mov", "r0,%s", spname);
2164 for (i = ds390_nRegs; i >= 0; i--) {
2165 if (bitVectBitValue (rs_mask, i)) {
2166 emitcode ("dec", "r0");
2167 emitcode ("movx", "a,@r0");
2169 emitcode ("mov", "b,a");
2171 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2174 emitcode ("mov", "%s,r0", spname);
2175 if (bitVectBitValue (rs_mask, R0_IDX))
2176 emitcode ("mov", "r0,b");
2178 for (i = ds390_nRegs; i >= 0; i--) {
2179 if (bitVectBitValue (rs_mask, i))
2180 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2185 /*-----------------------------------------------------------------*/
2186 /* unsaveRegisters - pop the pushed registers */
2187 /*-----------------------------------------------------------------*/
2189 unsaveRegisters (iCode * ic)
2193 if (IS_SYMOP(IC_LEFT (ic)) &&
2194 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 a:x by 1 */
8067 /*-----------------------------------------------------------------*/
8071 emitcode ("mov", "c,acc.0");
8072 emitcode ("xch", "a,%s", x);
8073 emitcode ("rrc", "a");
8074 emitcode ("xch", "a,%s", x);
8075 emitcode ("rrc", "a");
8079 #ifdef BETTER_LITERAL_SHIFT
8081 /*-----------------------------------------------------------------*/
8082 /* AccAXLrl1 - left rotate a:x by 1 */
8083 /*-----------------------------------------------------------------*/
8087 emitcode ("mov", "c,acc.7");
8088 emitcode ("xch", "a,%s", x);
8089 emitcode ("rlc", "a");
8090 emitcode ("xch", "a,%s", x);
8091 emitcode ("rlc", "a");
8095 #ifdef BETTER_LITERAL_SHIFT
8096 /*-----------------------------------------------------------------*/
8097 /* AccAXRsh1 - right shift c->a:x->c by 1 */
8098 /*-----------------------------------------------------------------*/
8102 emitcode ("rrc", "a");
8103 emitcode ("xch", "a,%s", x);
8104 emitcode ("rrc", "a");
8105 emitcode ("xch", "a,%s", x);
8109 #ifdef BETTER_LITERAL_SHIFT
8110 /*-----------------------------------------------------------------*/
8111 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8112 /*-----------------------------------------------------------------*/
8116 emitcode ("xch", "a,%s", x);
8117 emitcode ("add", "a,acc");
8118 emitcode ("xch", "a,%s", x);
8119 emitcode ("rlc", "a");
8123 #ifdef BETTER_LITERAL_SHIFT
8124 /*-----------------------------------------------------------------*/
8125 /* AccAXLsh - left shift a:x by known count (0..7) */
8126 /*-----------------------------------------------------------------*/
8128 AccAXLsh (char *x, int shCount)
8143 case 5: // AAAAABBB:CCCCCDDD
8145 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8147 emitcode ("anl", "a,#!constbyte",
8148 SLMask[shCount]); // BBB00000:CCCCCDDD
8150 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8152 AccRol (shCount); // DDDCCCCC:BBB00000
8154 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8156 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8158 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8160 emitcode ("anl", "a,#!constbyte",
8161 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8163 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8165 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8168 case 6: // AAAAAABB:CCCCCCDD
8169 emitcode ("anl", "a,#!constbyte",
8170 SRMask[shCount]); // 000000BB:CCCCCCDD
8172 AccAXRrl1 (x); // D000000B:BCCCCCCD
8173 AccAXRrl1 (x); // DD000000:BBCCCCCC
8174 emitcode ("xch", "a,%s", x); // BBCCCCCC:DD000000
8176 emitcode ("mov", "c,acc.0"); // c = B
8177 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8178 emitcode("rrc","a");
8179 emitcode("xch","a,%s", x);
8180 emitcode("rrc","a");
8181 emitcode("mov","c,acc.0"); //<< get correct bit
8182 emitcode("xch","a,%s", x);
8184 emitcode("rrc","a");
8185 emitcode("xch","a,%s", x);
8186 emitcode("rrc","a");
8187 emitcode("xch","a,%s", x);
8190 case 7: // a:x <<= 7
8192 emitcode ("anl", "a,#!constbyte",
8193 SRMask[shCount]); // 0000000B:CCCCCCCD
8195 AccAXRrl1 (x); // D0000000:BCCCCCCC
8197 emitcode ("xch", "a,%s", x); // BCCCCCCC:D0000000
8206 #ifdef BETTER_LITERAL_SHIFT
8208 /*-----------------------------------------------------------------*/
8209 /* AccAXRsh - right shift a:x known count (0..7) */
8210 /*-----------------------------------------------------------------*/
8212 AccAXRsh (char *x, int shCount)
8220 AccAXRsh1 (x); // 0->a:x
8225 AccAXRsh1 (x); // 0->a:x
8228 AccAXRsh1 (x); // 0->a:x
8233 case 5: // AAAAABBB:CCCCCDDD = a:x
8235 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8237 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8239 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8241 emitcode ("anl", "a,#!constbyte",
8242 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8244 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8246 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8248 emitcode ("anl", "a,#!constbyte",
8249 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8251 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8253 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8255 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8258 case 6: // AABBBBBB:CCDDDDDD
8260 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDE
8261 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8263 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8265 emitcode ("anl", "a,#!constbyte",
8266 SRMask[shCount]); // 000000AA:BBBBBBCC
8269 case 7: // ABBBBBBB:CDDDDDDD
8271 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8273 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8275 emitcode ("anl", "a,#!constbyte",
8276 SRMask[shCount]); // 0000000A:BBBBBBBC
8285 #ifdef BETTER_LITERAL_SHIFT
8286 /*-----------------------------------------------------------------*/
8287 /* AccAXRshS - right shift signed a:x known count (0..7) */
8288 /*-----------------------------------------------------------------*/
8290 AccAXRshS (char *x, int shCount)
8298 emitcode ("mov", "c,acc.7");
8299 AccAXRsh1 (x); // s->a:x
8303 emitcode ("mov", "c,acc.7");
8304 AccAXRsh1 (x); // s->a:x
8306 emitcode ("mov", "c,acc.7");
8307 AccAXRsh1 (x); // s->a:x
8312 case 5: // AAAAABBB:CCCCCDDD = a:x
8314 tlbl = newiTempLabel (NULL);
8315 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8317 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8319 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8321 emitcode ("anl", "a,#!constbyte",
8322 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8324 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8326 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8328 emitcode ("anl", "a,#!constbyte",
8329 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8331 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8333 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8335 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8337 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8338 emitcode ("orl", "a,#!constbyte",
8339 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8341 emitcode ("", "!tlabeldef", tlbl->key + 100);
8342 break; // SSSSAAAA:BBBCCCCC
8344 case 6: // AABBBBBB:CCDDDDDD
8346 tlbl = newiTempLabel (NULL);
8348 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8349 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8351 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8353 emitcode ("anl", "a,#!constbyte",
8354 SRMask[shCount]); // 000000AA:BBBBBBCC
8356 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8357 emitcode ("orl", "a,#!constbyte",
8358 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8360 emitcode ("", "!tlabeldef", tlbl->key + 100);
8362 case 7: // ABBBBBBB:CDDDDDDD
8364 tlbl = newiTempLabel (NULL);
8366 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8368 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8370 emitcode ("anl", "a,#!constbyte",
8371 SRMask[shCount]); // 0000000A:BBBBBBBC
8373 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8374 emitcode ("orl", "a,#!constbyte",
8375 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8377 emitcode ("", "!tlabeldef", tlbl->key + 100);
8385 #ifdef BETTER_LITERAL_SHIFT
8387 _loadLeftIntoAx(char **lsb,
8393 // Get the initial value from left into a pair of registers.
8394 // MSB must be in A, LSB can be any register.
8396 // If the result is held in registers, it is an optimization
8397 // if the LSB can be held in the register which will hold the,
8398 // result LSB since this saves us from having to copy it into
8399 // the result following AccAXLsh.
8401 // If the result is addressed indirectly, this is not a gain.
8402 if (AOP_NEEDSACC(result))
8406 _startLazyDPSEvaluation();
8407 if (AOP_TYPE(left) == AOP_DPTR2)
8410 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
8411 // get LSB in DP2_RESULT_REG.
8412 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
8413 assert(!strcmp(leftByte, DP2_RESULT_REG));
8417 // get LSB into DP2_RESULT_REG
8418 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
8419 if (strcmp(leftByte, DP2_RESULT_REG))
8422 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
8425 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
8426 assert(strcmp(leftByte, DP2_RESULT_REG));
8429 _endLazyDPSEvaluation();
8430 *lsb = DP2_RESULT_REG;
8434 if (sameRegs (AOP (result), AOP (left)) &&
8435 ((offl + MSB16) == offr))
8437 /* don't crash result[offr] */
8438 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
8439 emitcode ("xch", "a,%s",
8440 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
8444 movLeft2Result (left, offl, result, offr, 0);
8445 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
8447 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
8448 assert(strcmp(*lsb,"a"));
8453 _storeAxResults(char *lsb,
8457 _startLazyDPSEvaluation();
8458 if (AOP_NEEDSACC(result))
8460 /* We have to explicitly update the result LSB.
8462 emitcode("xch","a,%s", lsb);
8463 aopPut(AOP(result), "a", offr);
8464 emitcode("mov","a,%s", lsb);
8466 if (getDataSize (result) > 1)
8468 aopPut (AOP (result), "a", offr + MSB16);
8470 _endLazyDPSEvaluation();
8473 /*-----------------------------------------------------------------*/
8474 /* shiftL2Left2Result - shift left two bytes from left to result */
8475 /*-----------------------------------------------------------------*/
8477 shiftL2Left2Result (operand * left, int offl,
8478 operand * result, int offr, int shCount)
8482 _loadLeftIntoAx(&lsb, left, result, offl, offr);
8484 AccAXLsh (lsb, shCount);
8486 _storeAxResults(lsb, result, offr);
8490 #ifdef BETTER_LITERAL_SHIFT
8491 /*-----------------------------------------------------------------*/
8492 /* shiftR2Left2Result - shift right two bytes from left to result */
8493 /*-----------------------------------------------------------------*/
8495 shiftR2Left2Result (operand * left, int offl,
8496 operand * result, int offr,
8497 int shCount, int sign)
8501 _loadLeftIntoAx(&lsb, left, result, offl, offr);
8503 /* a:x >> shCount (x = lsb(result)) */
8506 AccAXRshS(lsb, shCount);
8510 AccAXRsh(lsb, shCount);
8513 _storeAxResults(lsb, result, offr);
8517 /*-----------------------------------------------------------------*/
8518 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8519 /*-----------------------------------------------------------------*/
8521 shiftLLeftOrResult (operand * left, int offl,
8522 operand * result, int offr, int shCount)
8524 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8525 /* shift left accumulator */
8527 /* or with result */
8528 emitcode ("orl", "a,%s",
8529 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8530 /* back to result */
8531 aopPut (AOP (result), "a", offr);
8536 /*-----------------------------------------------------------------*/
8537 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8538 /*-----------------------------------------------------------------*/
8540 shiftRLeftOrResult (operand * left, int offl,
8541 operand * result, int offr, int shCount)
8543 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8544 /* shift right accumulator */
8546 /* or with result */
8547 emitcode ("orl", "a,%s",
8548 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8549 /* back to result */
8550 aopPut (AOP (result), "a", offr);
8554 #ifdef BETTER_LITERAL_SHIFT
8555 /*-----------------------------------------------------------------*/
8556 /* genlshOne - left shift a one byte quantity by known count */
8557 /*-----------------------------------------------------------------*/
8559 genlshOne (operand * result, operand * left, int shCount)
8561 D (emitcode (";", "genlshOne "););
8562 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8566 #ifdef BETTER_LITERAL_SHIFT
8567 /*-----------------------------------------------------------------*/
8568 /* genlshTwo - left shift two bytes by known amount != 0 */
8569 /*-----------------------------------------------------------------*/
8571 genlshTwo (operand * result, operand * left, int shCount)
8575 D (emitcode (";", "genlshTwo "););
8577 size = getDataSize (result);
8579 /* if shCount >= 8 */
8584 _startLazyDPSEvaluation();
8590 _endLazyDPSEvaluation();
8591 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8592 aopPut (AOP (result), zero, LSB);
8596 movLeft2Result (left, LSB, result, MSB16, 0);
8597 aopPut (AOP (result), zero, LSB);
8598 _endLazyDPSEvaluation();
8603 aopPut (AOP (result), zero, LSB);
8604 _endLazyDPSEvaluation();
8608 /* 1 <= shCount <= 7 */
8613 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8617 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8625 /*-----------------------------------------------------------------*/
8626 /* shiftLLong - shift left one long from left to result */
8627 /* offl = LSB or MSB16 */
8628 /*-----------------------------------------------------------------*/
8630 shiftLLong (operand * left, operand * result, int offr)
8633 int size = AOP_SIZE (result);
8635 if (size >= LSB + offr)
8637 l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8639 emitcode ("add", "a,acc");
8640 if (sameRegs (AOP (left), AOP (result)) &&
8641 size >= MSB16 + offr && offr != LSB)
8642 emitcode ("xch", "a,%s",
8643 aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8645 aopPut (AOP (result), "a", LSB + offr);
8648 if (size >= MSB16 + offr)
8650 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8652 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8654 emitcode ("rlc", "a");
8655 if (sameRegs (AOP (left), AOP (result)) &&
8656 size >= MSB24 + offr && offr != LSB)
8657 emitcode ("xch", "a,%s",
8658 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8660 aopPut (AOP (result), "a", MSB16 + offr);
8663 if (size >= MSB24 + offr)
8665 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8667 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8669 emitcode ("rlc", "a");
8670 if (sameRegs (AOP (left), AOP (result)) &&
8671 size >= MSB32 + offr && offr != LSB)
8672 emitcode ("xch", "a,%s",
8673 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8675 aopPut (AOP (result), "a", MSB24 + offr);
8678 if (size > MSB32 + offr)
8680 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8682 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8684 emitcode ("rlc", "a");
8685 aopPut (AOP (result), "a", MSB32 + offr);
8688 aopPut (AOP (result), zero, LSB);
8694 /*-----------------------------------------------------------------*/
8695 /* genlshFour - shift four byte by a known amount != 0 */
8696 /*-----------------------------------------------------------------*/
8698 genlshFour (operand * result, operand * left, int shCount)
8702 D (emitcode (";", "genlshFour ");
8705 size = AOP_SIZE (result);
8707 /* if shifting more that 3 bytes */
8712 /* lowest order of left goes to the highest
8713 order of the destination */
8714 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8716 movLeft2Result (left, LSB, result, MSB32, 0);
8717 aopPut (AOP (result), zero, LSB);
8718 aopPut (AOP (result), zero, MSB16);
8719 aopPut (AOP (result), zero, MSB24);
8723 /* more than two bytes */
8724 else if (shCount >= 16)
8726 /* lower order two bytes goes to higher order two bytes */
8728 /* if some more remaining */
8730 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8733 movLeft2Result (left, MSB16, result, MSB32, 0);
8734 movLeft2Result (left, LSB, result, MSB24, 0);
8736 aopPut (AOP (result), zero, MSB16);
8737 aopPut (AOP (result), zero, LSB);
8741 /* if more than 1 byte */
8742 else if (shCount >= 8)
8744 /* lower order three bytes goes to higher order three bytes */
8749 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8751 movLeft2Result (left, LSB, result, MSB16, 0);
8757 movLeft2Result (left, MSB24, result, MSB32, 0);
8758 movLeft2Result (left, MSB16, result, MSB24, 0);
8759 movLeft2Result (left, LSB, result, MSB16, 0);
8760 aopPut (AOP (result), zero, LSB);
8762 else if (shCount == 1)
8763 shiftLLong (left, result, MSB16);
8766 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8767 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8768 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8769 aopPut (AOP (result), zero, LSB);
8774 /* 1 <= shCount <= 7 */
8775 else if (shCount <= 2)
8777 shiftLLong (left, result, LSB);
8779 shiftLLong (result, result, LSB);
8781 /* 3 <= shCount <= 7, optimize */
8784 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8785 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8786 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8791 #ifdef BETTER_LITERAL_SHIFT
8792 /*-----------------------------------------------------------------*/
8793 /* genLeftShiftLiteral - left shifting by known count */
8794 /*-----------------------------------------------------------------*/
8796 genLeftShiftLiteral (operand * left,
8801 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8804 size = getSize (operandType (result));
8806 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8808 /* We only handle certain easy cases so far. */
8810 && (shCount < (size * 8))
8814 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8818 freeAsmop (right, NULL, ic, TRUE);
8820 aopOp(left, ic, FALSE, FALSE);
8821 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8824 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8826 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8827 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8829 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8832 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8834 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8835 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8837 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8843 emitcode ("; shift left ", "result %d, left %d", size,
8847 /* I suppose that the left size >= result size */
8850 _startLazyDPSEvaluation();
8853 movLeft2Result (left, size, result, size, 0);
8855 _endLazyDPSEvaluation();
8857 else if (shCount >= (size * 8))
8859 _startLazyDPSEvaluation();
8862 aopPut (AOP (result), zero, size);
8864 _endLazyDPSEvaluation();
8871 genlshOne (result, left, shCount);
8875 genlshTwo (result, left, shCount);
8879 genlshFour (result, left, shCount);
8883 fprintf(stderr, "*** ack! mystery literal shift!\n");
8887 freeAsmop (left, NULL, ic, TRUE);
8888 freeAsmop (result, NULL, ic, TRUE);
8893 /*-----------------------------------------------------------------*/
8894 /* genLeftShift - generates code for left shifting */
8895 /*-----------------------------------------------------------------*/
8897 genLeftShift (iCode * ic)
8899 operand *left, *right, *result;
8902 symbol *tlbl, *tlbl1;
8904 D (emitcode (";", "genLeftShift "););
8906 right = IC_RIGHT (ic);
8907 left = IC_LEFT (ic);
8908 result = IC_RESULT (ic);
8910 aopOp (right, ic, FALSE, FALSE);
8913 #ifdef BETTER_LITERAL_SHIFT
8914 /* if the shift count is known then do it
8915 as efficiently as possible */
8916 if (AOP_TYPE (right) == AOP_LIT)
8918 if (genLeftShiftLiteral (left, right, result, ic))
8925 /* shift count is unknown then we have to form
8926 a loop get the loop count in B : Note: we take
8927 only the lower order byte since shifting
8928 more that 32 bits make no sense anyway, ( the
8929 largest size of an object can be only 32 bits ) */
8931 if (AOP_TYPE (right) == AOP_LIT)
8933 /* Really should be handled by genLeftShiftLiteral,
8934 * but since I'm too lazy to fix that today, at least we can make
8935 * some small improvement.
8937 emitcode("mov", "b,#!constbyte",
8938 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8942 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8943 emitcode ("inc", "b");
8945 freeAsmop (right, NULL, ic, TRUE);
8946 aopOp (left, ic, FALSE, FALSE);
8947 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8949 /* now move the left to the result if they are not the
8951 if (!sameRegs (AOP (left), AOP (result)) &&
8952 AOP_SIZE (result) > 1)
8955 size = AOP_SIZE (result);
8957 _startLazyDPSEvaluation ();
8960 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8961 if (*l == '@' && (IS_AOP_PREG (result)))
8964 emitcode ("mov", "a,%s", l);
8965 aopPut (AOP (result), "a", offset);
8968 aopPut (AOP (result), l, offset);
8971 _endLazyDPSEvaluation ();
8974 tlbl = newiTempLabel (NULL);
8975 size = AOP_SIZE (result);
8977 tlbl1 = newiTempLabel (NULL);
8979 /* if it is only one byte then */
8982 symbol *tlbl1 = newiTempLabel (NULL);
8984 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8985 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8986 emitcode ("", "!tlabeldef", tlbl->key + 100);
8987 emitcode ("add", "a,acc");
8988 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8989 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8990 aopPut (AOP (result), "a", 0);
8994 reAdjustPreg (AOP (result));
8996 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8997 emitcode ("", "!tlabeldef", tlbl->key + 100);
8998 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8999 emitcode ("add", "a,acc");
9000 aopPut (AOP (result), "a", offset++);
9001 _startLazyDPSEvaluation ();
9004 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9005 emitcode ("rlc", "a");
9006 aopPut (AOP (result), "a", offset++);
9008 _endLazyDPSEvaluation ();
9009 reAdjustPreg (AOP (result));
9011 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9012 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9014 freeAsmop (left, NULL, ic, TRUE);
9015 freeAsmop (result, NULL, ic, TRUE);
9018 #ifdef BETTER_LITERAL_SHIFT
9019 /*-----------------------------------------------------------------*/
9020 /* genrshOne - right shift a one byte quantity by known count */
9021 /*-----------------------------------------------------------------*/
9023 genrshOne (operand * result, operand * left,
9024 int shCount, int sign)
9026 D (emitcode (";", "genrshOne"););
9027 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9031 #ifdef BETTER_LITERAL_SHIFT
9032 /*-----------------------------------------------------------------*/
9033 /* genrshTwo - right shift two bytes by known amount != 0 */
9034 /*-----------------------------------------------------------------*/
9036 genrshTwo (operand * result, operand * left,
9037 int shCount, int sign)
9039 D (emitcode (";", "genrshTwo"););
9041 /* if shCount >= 8 */
9045 _startLazyDPSEvaluation();
9048 shiftR1Left2Result (left, MSB16, result, LSB,
9053 movLeft2Result (left, MSB16, result, LSB, sign);
9055 addSign (result, MSB16, sign);
9056 _endLazyDPSEvaluation();
9059 /* 1 <= shCount <= 7 */
9062 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9067 /*-----------------------------------------------------------------*/
9068 /* shiftRLong - shift right one long from left to result */
9069 /* offl = LSB or MSB16 */
9070 /*-----------------------------------------------------------------*/
9072 shiftRLong (operand * left, int offl,
9073 operand * result, int sign)
9075 int isSameRegs=sameRegs(AOP(left),AOP(result));
9077 if (isSameRegs && offl>1) {
9078 // we are in big trouble, but this shouldn't happen
9079 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9082 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
9087 emitcode ("rlc", "a");
9088 emitcode ("subb", "a,acc");
9089 emitcode ("xch", "a,%s",
9090 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
9092 aopPut (AOP(result), zero, MSB32);
9097 emitcode ("clr", "c");
9099 emitcode ("mov", "c,acc.7");
9102 emitcode ("rrc", "a");
9104 if (isSameRegs && offl==MSB16) {
9106 "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
9108 aopPut (AOP (result), "a", MSB32);
9109 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
9112 emitcode ("rrc", "a");
9113 if (isSameRegs && offl==1) {
9114 emitcode ("xch", "a,%s",
9115 aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
9117 aopPut (AOP (result), "a", MSB24);
9118 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
9120 emitcode ("rrc", "a");
9121 aopPut (AOP (result), "a", MSB16 - offl);
9125 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
9126 emitcode ("rrc", "a");
9127 aopPut (AOP (result), "a", LSB);
9131 /*-----------------------------------------------------------------*/
9132 /* genrshFour - shift four byte by a known amount != 0 */
9133 /*-----------------------------------------------------------------*/
9135 genrshFour (operand * result, operand * left,
9136 int shCount, int sign)
9138 D (emitcode (";", "genrshFour"););
9140 /* if shifting more that 3 bytes */
9144 _startLazyDPSEvaluation();
9146 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9148 movLeft2Result (left, MSB32, result, LSB, sign);
9149 addSign (result, MSB16, sign);
9150 _endLazyDPSEvaluation();
9152 else if (shCount >= 16)
9155 _startLazyDPSEvaluation();
9157 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9160 movLeft2Result (left, MSB24, result, LSB, 0);
9161 movLeft2Result (left, MSB32, result, MSB16, sign);
9163 addSign (result, MSB24, sign);
9164 _endLazyDPSEvaluation();
9166 else if (shCount >= 8)
9169 _startLazyDPSEvaluation();
9172 shiftRLong (left, MSB16, result, sign);
9174 else if (shCount == 0)
9176 movLeft2Result (left, MSB16, result, LSB, 0);
9177 movLeft2Result (left, MSB24, result, MSB16, 0);
9178 movLeft2Result (left, MSB32, result, MSB24, sign);
9179 addSign (result, MSB32, sign);
9183 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9184 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9185 /* the last shift is signed */
9186 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9187 addSign (result, MSB32, sign);
9189 _endLazyDPSEvaluation();
9193 /* 1 <= shCount <= 7 */
9196 shiftRLong (left, LSB, result, sign);
9198 shiftRLong (result, LSB, result, sign);
9202 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9203 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9204 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9209 #ifdef BETTER_LITERAL_SHIFT
9210 /*-----------------------------------------------------------------*/
9211 /* genRightShiftLiteral - right shifting by known count */
9212 /*-----------------------------------------------------------------*/
9214 genRightShiftLiteral (operand * left,
9220 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9223 size = getSize (operandType (result));
9225 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
9227 /* We only handle certain easy cases so far. */
9229 && (shCount < (size * 8))
9234 D(emitcode (";", "genRightShiftLiteral wimping out"););
9238 freeAsmop (right, NULL, ic, TRUE);
9240 aopOp (left, ic, FALSE, FALSE);
9241 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9244 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9248 /* test the LEFT size !!! */
9250 /* I suppose that the left size >= result size */
9253 size = getDataSize (result);
9254 _startLazyDPSEvaluation();
9257 movLeft2Result (left, size, result, size, 0);
9259 _endLazyDPSEvaluation();
9261 else if (shCount >= (size * 8))
9265 /* get sign in acc.7 */
9266 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
9268 addSign (result, LSB, sign);
9275 genrshOne (result, left, shCount, sign);
9279 genrshTwo (result, left, shCount, sign);
9283 genrshFour (result, left, shCount, sign);
9290 freeAsmop (left, NULL, ic, TRUE);
9291 freeAsmop (result, NULL, ic, TRUE);
9297 /*-----------------------------------------------------------------*/
9298 /* genSignedRightShift - right shift of signed number */
9299 /*-----------------------------------------------------------------*/
9301 genSignedRightShift (iCode * ic)
9303 operand *right, *left, *result;
9306 symbol *tlbl, *tlbl1;
9308 D (emitcode (";", "genSignedRightShift "););
9310 /* we do it the hard way put the shift count in b
9311 and loop thru preserving the sign */
9313 right = IC_RIGHT (ic);
9314 left = IC_LEFT (ic);
9315 result = IC_RESULT (ic);
9317 aopOp (right, ic, FALSE, FALSE);
9319 #ifdef BETTER_LITERAL_SHIFT
9320 if (AOP_TYPE (right) == AOP_LIT)
9322 if (genRightShiftLiteral (left, right, result, ic, 1))
9328 /* shift count is unknown then we have to form
9329 a loop get the loop count in B : Note: we take
9330 only the lower order byte since shifting
9331 more that 32 bits make no sense anyway, ( the
9332 largest size of an object can be only 32 bits ) */
9334 if (AOP_TYPE (right) == AOP_LIT)
9336 /* Really should be handled by genRightShiftLiteral,
9337 * but since I'm too lazy to fix that today, at least we can make
9338 * some small improvement.
9340 emitcode("mov", "b,#!constbyte",
9341 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9345 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9346 emitcode ("inc", "b");
9348 freeAsmop (right, NULL, ic, TRUE);
9349 aopOp (left, ic, FALSE, FALSE);
9350 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9352 /* now move the left to the result if they are not the
9354 if (!sameRegs (AOP (left), AOP (result)) &&
9355 AOP_SIZE (result) > 1)
9358 size = AOP_SIZE (result);
9360 _startLazyDPSEvaluation ();
9363 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9364 if (*l == '@' && IS_AOP_PREG (result))
9367 emitcode ("mov", "a,%s", l);
9368 aopPut (AOP (result), "a", offset);
9371 aopPut (AOP (result), l, offset);
9374 _endLazyDPSEvaluation ();
9377 /* mov the highest order bit to OVR */
9378 tlbl = newiTempLabel (NULL);
9379 tlbl1 = newiTempLabel (NULL);
9381 size = AOP_SIZE (result);
9383 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
9384 emitcode ("rlc", "a");
9385 emitcode ("mov", "ov,c");
9386 /* if it is only one byte then */
9389 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9390 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9391 emitcode ("", "!tlabeldef", tlbl->key + 100);
9392 emitcode ("mov", "c,ov");
9393 emitcode ("rrc", "a");
9394 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9395 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9396 aopPut (AOP (result), "a", 0);
9400 reAdjustPreg (AOP (result));
9401 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9402 emitcode ("", "!tlabeldef", tlbl->key + 100);
9403 emitcode ("mov", "c,ov");
9404 _startLazyDPSEvaluation ();
9407 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9408 emitcode ("rrc", "a");
9409 aopPut (AOP (result), "a", offset--);
9411 _endLazyDPSEvaluation ();
9412 reAdjustPreg (AOP (result));
9413 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9414 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9417 freeAsmop (left, NULL, ic, TRUE);
9418 freeAsmop (result, NULL, ic, TRUE);
9421 /*-----------------------------------------------------------------*/
9422 /* genRightShift - generate code for right shifting */
9423 /*-----------------------------------------------------------------*/
9425 genRightShift (iCode * ic)
9427 operand *right, *left, *result;
9431 symbol *tlbl, *tlbl1;
9433 D (emitcode (";", "genRightShift "););
9435 /* if signed then we do it the hard way preserve the
9436 sign bit moving it inwards */
9437 letype = getSpec (operandType (IC_LEFT (ic)));
9439 if (!SPEC_USIGN (letype))
9441 genSignedRightShift (ic);
9445 /* signed & unsigned types are treated the same : i.e. the
9446 signed is NOT propagated inwards : quoting from the
9447 ANSI - standard : "for E1 >> E2, is equivalent to division
9448 by 2**E2 if unsigned or if it has a non-negative value,
9449 otherwise the result is implementation defined ", MY definition
9450 is that the sign does not get propagated */
9452 right = IC_RIGHT (ic);
9453 left = IC_LEFT (ic);
9454 result = IC_RESULT (ic);
9456 aopOp (right, ic, FALSE, FALSE);
9458 #ifdef BETTER_LITERAL_SHIFT
9459 /* if the shift count is known then do it
9460 as efficiently as possible */
9461 if (AOP_TYPE (right) == AOP_LIT)
9463 if (genRightShiftLiteral (left, right, result, ic, 0))
9470 /* shift count is unknown then we have to form
9471 a loop get the loop count in B : Note: we take
9472 only the lower order byte since shifting
9473 more that 32 bits make no sense anyway, ( the
9474 largest size of an object can be only 32 bits ) */
9476 if (AOP_TYPE (right) == AOP_LIT)
9478 /* Really should be handled by genRightShiftLiteral,
9479 * but since I'm too lazy to fix that today, at least we can make
9480 * some small improvement.
9482 emitcode("mov", "b,#!constbyte",
9483 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9487 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9488 emitcode ("inc", "b");
9490 freeAsmop (right, NULL, ic, TRUE);
9491 aopOp (left, ic, FALSE, FALSE);
9492 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9494 /* now move the left to the result if they are not the
9496 if (!sameRegs (AOP (left), AOP (result)) &&
9497 AOP_SIZE (result) > 1)
9500 size = AOP_SIZE (result);
9502 _startLazyDPSEvaluation ();
9505 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9506 if (*l == '@' && IS_AOP_PREG (result))
9509 emitcode ("mov", "a,%s", l);
9510 aopPut (AOP (result), "a", offset);
9513 aopPut (AOP (result), l, offset);
9516 _endLazyDPSEvaluation ();
9519 tlbl = newiTempLabel (NULL);
9520 tlbl1 = newiTempLabel (NULL);
9521 size = AOP_SIZE (result);
9524 /* if it is only one byte then */
9527 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9528 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9529 emitcode ("", "!tlabeldef", tlbl->key + 100);
9531 emitcode ("rrc", "a");
9532 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9533 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9534 aopPut (AOP (result), "a", 0);
9538 reAdjustPreg (AOP (result));
9539 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9540 emitcode ("", "!tlabeldef", tlbl->key + 100);
9542 _startLazyDPSEvaluation ();
9545 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9546 emitcode ("rrc", "a");
9547 aopPut (AOP (result), "a", offset--);
9549 _endLazyDPSEvaluation ();
9550 reAdjustPreg (AOP (result));
9552 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9553 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9556 freeAsmop (left, NULL, ic, TRUE);
9557 freeAsmop (result, NULL, ic, TRUE);
9561 /*-----------------------------------------------------------------*/
9562 /* emitPtrByteGet - emits code to get a byte into A through a */
9563 /* pointer register (R0, R1, or DPTR). The */
9564 /* original value of A can be preserved in B. */
9565 /*-----------------------------------------------------------------*/
9567 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9574 emitcode ("mov", "b,a");
9575 emitcode ("mov", "a,@%s", rname);
9580 emitcode ("mov", "b,a");
9581 emitcode ("movx", "a,@%s", rname);
9586 emitcode ("mov", "b,a");
9587 emitcode ("movx", "a,@dptr");
9592 emitcode ("mov", "b,a");
9593 emitcode ("clr", "a");
9594 emitcode ("movc", "a,@a+dptr");
9600 emitcode ("push", "b");
9601 emitcode ("push", "acc");
9603 emitcode ("lcall", "__gptrget");
9605 emitcode ("pop", "b");
9610 /*-----------------------------------------------------------------*/
9611 /* emitPtrByteSet - emits code to set a byte from src through a */
9612 /* pointer register (R0, R1, or DPTR). */
9613 /*-----------------------------------------------------------------*/
9615 emitPtrByteSet (char *rname, int p_type, char *src)
9624 emitcode ("mov", "@%s,a", rname);
9627 emitcode ("mov", "@%s,%s", rname, src);
9632 emitcode ("movx", "@%s,a", rname);
9637 emitcode ("movx", "@dptr,a");
9642 emitcode ("lcall", "__gptrput");
9647 /*-----------------------------------------------------------------*/
9648 /* genUnpackBits - generates code for unpacking bits */
9649 /*-----------------------------------------------------------------*/
9651 genUnpackBits (operand * result, char *rname, int ptype)
9653 int offset = 0; /* result byte offset */
9654 int rsize; /* result size */
9655 int rlen = 0; /* remaining bitfield length */
9656 sym_link *etype; /* bitfield type information */
9657 int blen; /* bitfield length */
9658 int bstr; /* bitfield starting bit within byte */
9660 D(emitcode ("; genUnpackBits",""));
9662 etype = getSpec (operandType (result));
9663 rsize = getSize (operandType (result));
9664 blen = SPEC_BLEN (etype);
9665 bstr = SPEC_BSTR (etype);
9667 /* If the bitfield length is less than a byte */
9670 emitPtrByteGet (rname, ptype, FALSE);
9672 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9673 if (!SPEC_USIGN (etype))
9675 /* signed bitfield */
9676 symbol *tlbl = newiTempLabel (NULL);
9678 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9679 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9680 emitcode ("", "%05d$:", tlbl->key + 100);
9682 aopPut (AOP (result), "a", offset++);
9686 /* Bit field did not fit in a byte. Copy all
9687 but the partial byte at the end. */
9688 for (rlen=blen;rlen>=8;rlen-=8)
9690 emitPtrByteGet (rname, ptype, FALSE);
9691 aopPut (AOP (result), "a", offset++);
9693 emitcode ("inc", "%s", rname);
9696 /* Handle the partial byte at the end */
9699 emitPtrByteGet (rname, ptype, FALSE);
9700 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9701 if (!SPEC_USIGN (etype))
9703 /* signed bitfield */
9704 symbol *tlbl = newiTempLabel (NULL);
9706 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9707 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9708 emitcode ("", "%05d$:", tlbl->key + 100);
9710 aopPut (AOP (result), "a", offset++);
9718 if (SPEC_USIGN (etype))
9722 /* signed bitfield: sign extension with 0x00 or 0xff */
9723 emitcode ("rlc", "a");
9724 emitcode ("subb", "a,acc");
9730 aopPut (AOP (result), source, offset++);
9735 /*-----------------------------------------------------------------*/
9736 /* genDataPointerGet - generates code when ptr offset is known */
9737 /*-----------------------------------------------------------------*/
9739 genDataPointerGet (operand * left,
9745 int size, offset = 0;
9746 aopOp (result, ic, TRUE, FALSE);
9748 /* get the string representation of the name */
9749 l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9750 size = AOP_SIZE (result);
9751 _startLazyDPSEvaluation ();
9756 SNPRINTF (buff, sizeof(buff),
9757 "(%s + %d)", l + 1, offset);
9761 SNPRINTF (buff, sizeof(buff),
9764 aopPut (AOP (result), buff, offset++);
9766 _endLazyDPSEvaluation ();
9768 freeAsmop (left, NULL, ic, TRUE);
9769 freeAsmop (result, NULL, ic, TRUE);
9772 /*-----------------------------------------------------------------*/
9773 /* genNearPointerGet - emitcode for near pointer fetch */
9774 /*-----------------------------------------------------------------*/
9776 genNearPointerGet (operand * left,
9784 sym_link *rtype, *retype, *letype;
9785 sym_link *ltype = operandType (left);
9788 rtype = operandType (result);
9789 retype = getSpec (rtype);
9790 letype = getSpec (ltype);
9792 aopOp (left, ic, FALSE, FALSE);
9794 /* if left is rematerialisable and
9795 result is not bitfield variable type and
9796 the left is pointer to data space i.e
9797 lower 128 bytes of space */
9798 if (AOP_TYPE (left) == AOP_IMMD &&
9799 !IS_BITFIELD (retype) &&
9800 !IS_BITFIELD (letype) &&
9801 DCL_TYPE (ltype) == POINTER)
9803 genDataPointerGet (left, result, ic);
9807 /* if the value is already in a pointer register
9808 then don't need anything more */
9809 if (!AOP_INPREG (AOP (left)))
9811 /* otherwise get a free pointer register */
9813 preg = getFreePtr (ic, &aop, FALSE);
9814 emitcode ("mov", "%s,%s",
9816 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9820 rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9822 freeAsmop (left, NULL, ic, TRUE);
9823 aopOp (result, ic, FALSE, FALSE);
9825 /* if bitfield then unpack the bits */
9826 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9827 genUnpackBits (result, rname, POINTER);
9830 /* we have can just get the values */
9831 int size = AOP_SIZE (result);
9836 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9839 emitcode ("mov", "a,@%s", rname);
9840 aopPut (AOP (result), "a", offset);
9844 SNPRINTF (buff, sizeof(buff), "@%s", rname);
9845 aopPut (AOP (result), buff, offset);
9850 emitcode ("inc", "%s", rname);
9855 /* now some housekeeping stuff */
9858 /* we had to allocate for this iCode */
9859 if (pi) { /* post increment present */
9860 aopPut(AOP ( left ),rname,0);
9862 freeAsmop (NULL, aop, ic, TRUE);
9866 /* we did not allocate which means left
9867 already in a pointer register, then
9868 if size > 0 && this could be used again
9869 we have to point it back to where it
9871 if (AOP_SIZE (result) > 1 &&
9872 !OP_SYMBOL (left)->remat &&
9873 (OP_SYMBOL (left)->liveTo > ic->seq ||
9877 int size = AOP_SIZE (result) - 1;
9879 emitcode ("dec", "%s", rname);
9884 freeAsmop (result, NULL, ic, TRUE);
9885 if (pi) pi->generated = 1;
9888 /*-----------------------------------------------------------------*/
9889 /* genPagedPointerGet - emitcode for paged pointer fetch */
9890 /*-----------------------------------------------------------------*/
9892 genPagedPointerGet (operand * left,
9900 sym_link *rtype, *retype, *letype;
9902 rtype = operandType (result);
9903 retype = getSpec (rtype);
9904 letype = getSpec (operandType (left));
9905 aopOp (left, ic, FALSE, FALSE);
9907 /* if the value is already in a pointer register
9908 then don't need anything more */
9909 if (!AOP_INPREG (AOP (left)))
9911 /* otherwise get a free pointer register */
9913 preg = getFreePtr (ic, &aop, FALSE);
9914 emitcode ("mov", "%s,%s",
9916 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9920 rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9922 freeAsmop (left, NULL, ic, TRUE);
9923 aopOp (result, ic, FALSE, FALSE);
9925 /* if bitfield then unpack the bits */
9926 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9927 genUnpackBits (result, rname, PPOINTER);
9930 /* we have can just get the values */
9931 int size = AOP_SIZE (result);
9937 emitcode ("movx", "a,@%s", rname);
9938 aopPut (AOP (result), "a", offset);
9943 emitcode ("inc", "%s", rname);
9947 /* now some housekeeping stuff */
9950 /* we had to allocate for this iCode */
9951 if (pi) aopPut ( AOP (left), rname, 0);
9952 freeAsmop (NULL, aop, ic, TRUE);
9956 /* we did not allocate which means left
9957 already in a pointer register, then
9958 if size > 0 && this could be used again
9959 we have to point it back to where it
9961 if (AOP_SIZE (result) > 1 &&
9962 !OP_SYMBOL (left)->remat &&
9963 (OP_SYMBOL (left)->liveTo > ic->seq ||
9967 int size = AOP_SIZE (result) - 1;
9969 emitcode ("dec", "%s", rname);
9974 freeAsmop (result, NULL, ic, TRUE);
9975 if (pi) pi->generated = 1;
9978 /*-----------------------------------------------------------------*/
9979 /* genFarPointerGet - gget value from far space */
9980 /*-----------------------------------------------------------------*/
9982 genFarPointerGet (operand * left,
9983 operand * result, iCode * ic, iCode *pi)
9985 int size, offset, dopi=1;
9986 sym_link *retype = getSpec (operandType (result));
9987 sym_link *letype = getSpec (operandType (left));
9988 D (emitcode (";", "genFarPointerGet"););
9990 aopOp (left, ic, FALSE, FALSE);
9992 /* if the operand is already in dptr
9993 then we do nothing else we move the value to dptr */
9994 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9996 /* if this is remateriazable */
9997 if (AOP_TYPE (left) == AOP_IMMD)
9999 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10003 /* we need to get it byte by byte */
10004 _startLazyDPSEvaluation ();
10005 if (AOP_TYPE (left) != AOP_DPTR)
10007 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10008 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10009 if (options.model == MODEL_FLAT24)
10010 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10014 /* We need to generate a load to DPTR indirect through DPTR. */
10015 D (emitcode (";", "genFarPointerGet -- indirection special case."););
10016 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
10017 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
10018 if (options.model == MODEL_FLAT24)
10019 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10020 emitcode ("pop", "dph");
10021 emitcode ("pop", "dpl");
10024 _endLazyDPSEvaluation ();
10027 /* so dptr know contains the address */
10028 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10030 /* if bit then unpack */
10031 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10032 if (AOP_INDPTRn(left)) {
10033 genSetDPTR(AOP(left)->aopu.dptr);
10035 genUnpackBits (result, "dptr", FPOINTER);
10036 if (AOP_INDPTRn(left)) {
10041 size = AOP_SIZE (result);
10044 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10046 genSetDPTR(AOP(left)->aopu.dptr);
10047 emitcode ("movx", "a,@dptr");
10048 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10049 emitcode ("inc", "dptr");
10051 aopPut (AOP (result), "a", offset++);
10054 _startLazyDPSEvaluation ();
10056 if (AOP_INDPTRn(left)) {
10057 genSetDPTR(AOP(left)->aopu.dptr);
10063 emitcode ("movx", "a,@dptr");
10064 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10065 emitcode ("inc", "dptr");
10067 aopPut (AOP (result), "a", offset++);
10069 _endLazyDPSEvaluation ();
10072 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10073 if (!AOP_INDPTRn(left)) {
10074 _startLazyDPSEvaluation ();
10075 aopPut ( AOP (left), "dpl", 0);
10076 aopPut ( AOP (left), "dph", 1);
10077 if (options.model == MODEL_FLAT24)
10078 aopPut ( AOP (left), "dpx", 2);
10079 _endLazyDPSEvaluation ();
10082 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
10083 AOP_SIZE(result) > 1 &&
10085 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
10087 size = AOP_SIZE (result) - 1;
10088 if (AOP_INDPTRn(left)) {
10089 genSetDPTR(AOP(left)->aopu.dptr);
10091 while (size--) emitcode ("lcall","__decdptr");
10092 if (AOP_INDPTRn(left)) {
10097 freeAsmop (left, NULL, ic, TRUE);
10098 freeAsmop (result, NULL, ic, TRUE);
10101 /*-----------------------------------------------------------------*/
10102 /* genCodePointerGet - get value from code space */
10103 /*-----------------------------------------------------------------*/
10105 genCodePointerGet (operand * left,
10106 operand * result, iCode * ic, iCode *pi)
10108 int size, offset, dopi=1;
10109 sym_link *retype = getSpec (operandType (result));
10111 aopOp (left, ic, FALSE, FALSE);
10113 /* if the operand is already in dptr
10114 then we do nothing else we move the value to dptr */
10115 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
10117 /* if this is remateriazable */
10118 if (AOP_TYPE (left) == AOP_IMMD)
10120 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10123 { /* we need to get it byte by byte */
10124 _startLazyDPSEvaluation ();
10125 if (AOP_TYPE (left) != AOP_DPTR)
10127 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10128 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10129 if (options.model == MODEL_FLAT24)
10130 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10134 /* We need to generate a load to DPTR indirect through DPTR. */
10135 D (emitcode (";", "gencodePointerGet -- indirection special case."););
10136 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
10137 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
10138 if (options.model == MODEL_FLAT24)
10139 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10140 emitcode ("pop", "dph");
10141 emitcode ("pop", "dpl");
10144 _endLazyDPSEvaluation ();
10147 /* so dptr know contains the address */
10148 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10150 /* if bit then unpack */
10151 if (IS_BITFIELD (retype)) {
10152 if (AOP_INDPTRn(left)) {
10153 genSetDPTR(AOP(left)->aopu.dptr);
10155 genUnpackBits (result, "dptr", CPOINTER);
10156 if (AOP_INDPTRn(left)) {
10161 size = AOP_SIZE (result);
10163 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10165 genSetDPTR(AOP(left)->aopu.dptr);
10166 emitcode ("clr", "a");
10167 emitcode ("movc", "a,@a+dptr");
10168 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10169 emitcode ("inc", "dptr");
10171 aopPut (AOP (result), "a", offset++);
10174 _startLazyDPSEvaluation ();
10177 if (AOP_INDPTRn(left)) {
10178 genSetDPTR(AOP(left)->aopu.dptr);
10184 emitcode ("clr", "a");
10185 emitcode ("movc", "a,@a+dptr");
10186 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10187 emitcode ("inc", "dptr");
10188 aopPut (AOP (result), "a", offset++);
10190 _endLazyDPSEvaluation ();
10193 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10194 if (!AOP_INDPTRn(left)) {
10195 _startLazyDPSEvaluation ();
10197 aopPut ( AOP (left), "dpl", 0);
10198 aopPut ( AOP (left), "dph", 1);
10199 if (options.model == MODEL_FLAT24)
10200 aopPut ( AOP (left), "dpx", 2);
10202 _endLazyDPSEvaluation ();
10205 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
10206 AOP_SIZE(result) > 1 &&
10207 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10209 size = AOP_SIZE (result) - 1;
10210 if (AOP_INDPTRn(left)) {
10211 genSetDPTR(AOP(left)->aopu.dptr);
10213 while (size--) emitcode ("lcall","__decdptr");
10214 if (AOP_INDPTRn(left)) {
10219 freeAsmop (left, NULL, ic, TRUE);
10220 freeAsmop (result, NULL, ic, TRUE);
10223 /*-----------------------------------------------------------------*/
10224 /* genGenPointerGet - gget value from generic pointer space */
10225 /*-----------------------------------------------------------------*/
10227 genGenPointerGet (operand * left,
10228 operand * result, iCode * ic, iCode * pi)
10231 sym_link *retype = getSpec (operandType (result));
10232 sym_link *letype = getSpec (operandType (left));
10234 D (emitcode (";", "genGenPointerGet "); );
10236 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
10238 /* if the operand is already in dptr
10239 then we do nothing else we move the value to dptr */
10240 if (AOP_TYPE (left) != AOP_STR)
10242 /* if this is rematerializable */
10243 if (AOP_TYPE (left) == AOP_IMMD)
10245 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10246 if (AOP(left)->aopu.aop_immd.from_cast_remat)
10248 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
10252 emitcode ("mov", "b,#%d", pointerCode (retype));
10256 { /* we need to get it byte by byte */
10257 _startLazyDPSEvaluation ();
10258 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
10259 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
10260 if (options.model == MODEL_FLAT24) {
10261 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10262 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
10264 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10266 _endLazyDPSEvaluation ();
10270 /* so dptr-b now contains the address */
10272 aopOp (result, ic, FALSE, TRUE);
10275 /* if bit then unpack */
10276 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10278 genUnpackBits (result, "dptr", GPOINTER);
10282 size = AOP_SIZE (result);
10289 // Get two bytes at a time, results in _AP & A.
10290 // dptr will be incremented ONCE by __gptrgetWord.
10292 // Note: any change here must be coordinated
10293 // with the implementation of __gptrgetWord
10294 // in device/lib/_gptrget.c
10295 emitcode ("lcall", "__gptrgetWord");
10296 aopPut (AOP (result), DP2_RESULT_REG, offset++);
10297 aopPut (AOP (result), "a", offset++);
10302 // Only one byte to get.
10303 emitcode ("lcall", "__gptrget");
10304 aopPut (AOP (result), "a", offset++);
10307 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
10309 emitcode ("inc", "dptr");
10314 if (pi && AOP_TYPE (left) != AOP_IMMD) {
10315 _startLazyDPSEvaluation ();
10317 aopPut ( AOP (left), "dpl", 0);
10318 aopPut ( AOP (left), "dph", 1);
10319 if (options.model == MODEL_FLAT24) {
10320 aopPut ( AOP (left), "dpx", 2);
10321 aopPut ( AOP (left), "b", 3);
10322 } else aopPut ( AOP (left), "b", 2);
10324 _endLazyDPSEvaluation ();
10327 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
10328 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10330 size = AOP_SIZE (result) - 1;
10331 while (size--) emitcode ("lcall","__decdptr");
10334 freeAsmop (left, NULL, ic, TRUE);
10335 freeAsmop (result, NULL, ic, TRUE);
10338 /*-----------------------------------------------------------------*/
10339 /* genPointerGet - generate code for pointer get */
10340 /*-----------------------------------------------------------------*/
10342 genPointerGet (iCode * ic, iCode *pi)
10344 operand *left, *result;
10345 sym_link *type, *etype;
10348 D (emitcode (";", "genPointerGet ");
10351 left = IC_LEFT (ic);
10352 result = IC_RESULT (ic);
10354 /* depending on the type of pointer we need to
10355 move it to the correct pointer register */
10356 type = operandType (left);
10357 etype = getSpec (type);
10358 /* if left is of type of pointer then it is simple */
10359 if (IS_PTR (type) && !IS_FUNC (type->next))
10360 p_type = DCL_TYPE (type);
10363 /* we have to go by the storage class */
10364 p_type = PTR_TYPE (SPEC_OCLS (etype));
10366 /* special case when cast remat */
10367 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10368 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10370 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10371 type = operandType (left);
10372 p_type = DCL_TYPE (type);
10374 /* now that we have the pointer type we assign
10375 the pointer values */
10381 genNearPointerGet (left, result, ic, pi);
10385 genPagedPointerGet (left, result, ic, pi);
10389 genFarPointerGet (left, result, ic, pi);
10393 genCodePointerGet (left, result, ic, pi);
10397 genGenPointerGet (left, result, ic, pi);
10403 /*-----------------------------------------------------------------*/
10404 /* genPackBits - generates code for packed bit storage */
10405 /*-----------------------------------------------------------------*/
10407 genPackBits (sym_link * etype,
10409 char *rname, int p_type)
10411 int offset = 0; /* source byte offset */
10412 int rlen = 0; /* remaining bitfield length */
10413 int blen; /* bitfield length */
10414 int bstr; /* bitfield starting bit within byte */
10415 int litval; /* source literal value (if AOP_LIT) */
10416 unsigned char mask; /* bitmask within current byte */
10418 D(emitcode ("; genPackBits",""));
10420 blen = SPEC_BLEN (etype);
10421 bstr = SPEC_BSTR (etype);
10423 /* If the bitfield length is less than a byte */
10426 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10427 (unsigned char) (0xFF >> (8 - bstr)));
10429 if (AOP_TYPE (right) == AOP_LIT)
10431 /* Case with a bitfield length <8 and literal source
10433 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10435 litval &= (~mask) & 0xff;
10436 emitPtrByteGet (rname, p_type, FALSE);
10437 if ((mask|litval)!=0xff)
10438 emitcode ("anl","a,#!constbyte", mask);
10440 emitcode ("orl","a,#!constbyte", litval);
10444 if ((blen==1) && (p_type!=GPOINTER))
10446 /* Case with a bitfield length == 1 and no generic pointer
10448 if (AOP_TYPE (right) == AOP_CRY)
10449 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10452 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10453 emitcode ("rrc","a");
10455 emitPtrByteGet (rname, p_type, FALSE);
10456 emitcode ("mov","acc.%d,c",bstr);
10460 /* Case with a bitfield length < 8 and arbitrary source
10462 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10463 /* shift and mask source value */
10465 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10467 /* transfer A to B and get next byte */
10468 emitPtrByteGet (rname, p_type, TRUE);
10470 emitcode ("anl", "a,#!constbyte", mask);
10471 emitcode ("orl", "a,b");
10472 if (p_type == GPOINTER)
10473 emitcode ("pop", "b");
10477 emitPtrByteSet (rname, p_type, "a");
10481 /* Bit length is greater than 7 bits. In this case, copy */
10482 /* all except the partial byte at the end */
10483 for (rlen=blen;rlen>=8;rlen-=8)
10485 emitPtrByteSet (rname, p_type,
10486 aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
10488 emitcode ("inc", "%s", rname);
10491 /* If there was a partial byte at the end */
10494 mask = (((unsigned char) -1 << rlen) & 0xff);
10496 if (AOP_TYPE (right) == AOP_LIT)
10498 /* Case with partial byte and literal source
10500 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10501 litval >>= (blen-rlen);
10502 litval &= (~mask) & 0xff;
10503 emitPtrByteGet (rname, p_type, FALSE);
10504 if ((mask|litval)!=0xff)
10505 emitcode ("anl","a,#!constbyte", mask);
10507 emitcode ("orl","a,#!constbyte", litval);
10511 /* Case with partial byte and arbitrary source
10513 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10514 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10516 /* transfer A to B and get next byte */
10517 emitPtrByteGet (rname, p_type, TRUE);
10519 emitcode ("anl", "a,#!constbyte", mask);
10520 emitcode ("orl", "a,b");
10521 if (p_type == GPOINTER)
10522 emitcode ("pop", "b");
10524 emitPtrByteSet (rname, p_type, "a");
10530 /*-----------------------------------------------------------------*/
10531 /* genDataPointerSet - remat pointer to data space */
10532 /*-----------------------------------------------------------------*/
10534 genDataPointerSet (operand * right,
10538 int size, offset = 0;
10539 char *l, buff[256];
10541 aopOp (right, ic, FALSE, FALSE);
10543 l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
10544 size = AOP_SIZE (right);
10549 SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
10553 SNPRINTF (buff, sizeof(buff), "%s", l + 1);
10556 emitcode ("mov", "%s,%s", buff,
10557 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10560 freeAsmop (right, NULL, ic, TRUE);
10561 freeAsmop (result, NULL, ic, TRUE);
10564 /*-----------------------------------------------------------------*/
10565 /* genNearPointerSet - emitcode for near pointer put */
10566 /*-----------------------------------------------------------------*/
10568 genNearPointerSet (operand * right,
10575 sym_link *retype, *letype;
10576 sym_link *ptype = operandType (result);
10578 retype = getSpec (operandType (right));
10579 letype = getSpec (ptype);
10581 aopOp (result, ic, FALSE, FALSE);
10583 /* if the result is rematerializable &
10584 in data space & not a bit variable */
10585 if (AOP_TYPE (result) == AOP_IMMD &&
10586 DCL_TYPE (ptype) == POINTER &&
10587 !IS_BITVAR (retype) &&
10588 !IS_BITVAR (letype))
10590 genDataPointerSet (right, result, ic);
10594 /* if the value is already in a pointer register
10595 then don't need anything more */
10596 if (!AOP_INPREG (AOP (result)))
10598 /* otherwise get a free pointer register */
10601 aop = newAsmop (0);
10602 preg = getFreePtr (ic, &aop, FALSE);
10603 emitcode ("mov", "%s,%s",
10605 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10606 rname = preg->name;
10609 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10611 aopOp (right, ic, FALSE, FALSE);
10613 /* if bitfield then unpack the bits */
10614 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10615 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10618 /* we have can just get the values */
10619 int size = AOP_SIZE (right);
10624 l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10628 emitcode ("mov", "@%s,a", rname);
10631 emitcode ("mov", "@%s,%s", rname, l);
10633 emitcode ("inc", "%s", rname);
10638 /* now some housekeeping stuff */
10641 /* we had to allocate for this iCode */
10642 if (pi) aopPut (AOP (result),rname,0);
10643 freeAsmop (NULL, aop, ic, TRUE);
10647 /* we did not allocate which means left
10648 already in a pointer register, then
10649 if size > 0 && this could be used again
10650 we have to point it back to where it
10652 if (AOP_SIZE (right) > 1 &&
10653 !OP_SYMBOL (result)->remat &&
10654 (OP_SYMBOL (result)->liveTo > ic->seq ||
10658 int size = AOP_SIZE (right) - 1;
10660 emitcode ("dec", "%s", rname);
10665 if (pi) pi->generated = 1;
10666 freeAsmop (result, NULL, ic, TRUE);
10667 freeAsmop (right, NULL, ic, TRUE);
10672 /*-----------------------------------------------------------------*/
10673 /* genPagedPointerSet - emitcode for Paged pointer put */
10674 /*-----------------------------------------------------------------*/
10676 genPagedPointerSet (operand * right,
10683 sym_link *retype, *letype;
10685 retype = getSpec (operandType (right));
10686 letype = getSpec (operandType (result));
10688 aopOp (result, ic, FALSE, FALSE);
10690 /* if the value is already in a pointer register
10691 then don't need anything more */
10692 if (!AOP_INPREG (AOP (result)))
10694 /* otherwise get a free pointer register */
10697 aop = newAsmop (0);
10698 preg = getFreePtr (ic, &aop, FALSE);
10699 emitcode ("mov", "%s,%s",
10701 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10702 rname = preg->name;
10705 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10707 aopOp (right, ic, FALSE, FALSE);
10709 /* if bitfield then unpack the bits */
10710 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10711 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10714 /* we have can just get the values */
10715 int size = AOP_SIZE (right);
10720 MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10722 emitcode ("movx", "@%s,a", rname);
10725 emitcode ("inc", "%s", rname);
10731 /* now some housekeeping stuff */
10734 if (pi) aopPut (AOP (result),rname,0);
10735 /* we had to allocate for this iCode */
10736 freeAsmop (NULL, aop, ic, TRUE);
10740 /* we did not allocate which means left
10741 already in a pointer register, then
10742 if size > 0 && this could be used again
10743 we have to point it back to where it
10745 if (AOP_SIZE (right) > 1 &&
10746 !OP_SYMBOL (result)->remat &&
10747 (OP_SYMBOL (result)->liveTo > ic->seq ||
10751 int size = AOP_SIZE (right) - 1;
10753 emitcode ("dec", "%s", rname);
10758 if (pi) pi->generated = 1;
10759 freeAsmop (result, NULL, ic, TRUE);
10760 freeAsmop (right, NULL, ic, TRUE);
10765 /*-----------------------------------------------------------------*/
10766 /* genFarPointerSet - set value from far space */
10767 /*-----------------------------------------------------------------*/
10769 genFarPointerSet (operand * right,
10770 operand * result, iCode * ic, iCode *pi)
10772 int size, offset, dopi=1;
10773 sym_link *retype = getSpec (operandType (right));
10774 sym_link *letype = getSpec (operandType (result));
10776 aopOp (result, ic, FALSE, FALSE);
10778 /* if the operand is already in dptr
10779 then we do nothing else we move the value to dptr */
10780 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10782 /* if this is remateriazable */
10783 if (AOP_TYPE (result) == AOP_IMMD)
10784 emitcode ("mov", "dptr,%s",
10785 aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10788 /* we need to get it byte by byte */
10789 _startLazyDPSEvaluation ();
10790 if (AOP_TYPE (result) != AOP_DPTR)
10792 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10793 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10794 if (options.model == MODEL_FLAT24)
10795 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10799 /* We need to generate a load to DPTR indirect through DPTR. */
10800 D (emitcode (";", "genFarPointerSet -- indirection special case."););
10802 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10803 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10804 if (options.model == MODEL_FLAT24)
10805 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10806 emitcode ("pop", "dph");
10807 emitcode ("pop", "dpl");
10810 _endLazyDPSEvaluation ();
10813 /* so dptr know contains the address */
10814 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10816 /* if bit then unpack */
10817 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10818 if (AOP_INDPTRn(result)) {
10819 genSetDPTR(AOP(result)->aopu.dptr);
10821 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10822 if (AOP_INDPTRn(result)) {
10826 size = AOP_SIZE (right);
10828 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10830 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10832 genSetDPTR(AOP(result)->aopu.dptr);
10833 emitcode ("movx", "@dptr,a");
10834 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10835 emitcode ("inc", "dptr");
10839 _startLazyDPSEvaluation ();
10841 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10843 if (AOP_INDPTRn(result)) {
10844 genSetDPTR(AOP(result)->aopu.dptr);
10850 emitcode ("movx", "@dptr,a");
10851 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10852 emitcode ("inc", "dptr");
10854 _endLazyDPSEvaluation ();
10858 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10859 if (!AOP_INDPTRn(result)) {
10860 _startLazyDPSEvaluation ();
10862 aopPut (AOP(result),"dpl",0);
10863 aopPut (AOP(result),"dph",1);
10864 if (options.model == MODEL_FLAT24)
10865 aopPut (AOP(result),"dpx",2);
10867 _endLazyDPSEvaluation ();
10870 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10871 AOP_SIZE(right) > 1 &&
10872 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10874 size = AOP_SIZE (right) - 1;
10875 if (AOP_INDPTRn(result)) {
10876 genSetDPTR(AOP(result)->aopu.dptr);
10878 while (size--) emitcode ("lcall","__decdptr");
10879 if (AOP_INDPTRn(result)) {
10883 freeAsmop (result, NULL, ic, TRUE);
10884 freeAsmop (right, NULL, ic, TRUE);
10887 /*-----------------------------------------------------------------*/
10888 /* genGenPointerSet - set value from generic pointer space */
10889 /*-----------------------------------------------------------------*/
10891 genGenPointerSet (operand * right,
10892 operand * result, iCode * ic, iCode *pi)
10895 sym_link *retype = getSpec (operandType (right));
10896 sym_link *letype = getSpec (operandType (result));
10898 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10900 /* if the operand is already in dptr
10901 then we do nothing else we move the value to dptr */
10902 if (AOP_TYPE (result) != AOP_STR)
10904 _startLazyDPSEvaluation ();
10905 /* if this is remateriazable */
10906 if (AOP_TYPE (result) == AOP_IMMD)
10908 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10909 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10911 MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10916 "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10920 { /* we need to get it byte by byte */
10921 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10922 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10923 if (options.model == MODEL_FLAT24) {
10924 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10925 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10927 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10930 _endLazyDPSEvaluation ();
10932 /* so dptr + b now contains the address */
10934 aopOp (right, ic, FALSE, TRUE);
10938 /* if bit then unpack */
10939 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10941 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10945 size = AOP_SIZE (right);
10948 _startLazyDPSEvaluation ();
10953 // Set two bytes at a time, passed in _AP & A.
10954 // dptr will be incremented ONCE by __gptrputWord.
10956 // Note: any change here must be coordinated
10957 // with the implementation of __gptrputWord
10958 // in device/lib/_gptrput.c
10959 emitcode("mov", "_ap, %s",
10960 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10961 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10965 emitcode ("lcall", "__gptrputWord");
10970 // Only one byte to put.
10971 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10975 emitcode ("lcall", "__gptrput");
10978 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10980 emitcode ("inc", "dptr");
10983 _endLazyDPSEvaluation ();
10986 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10987 _startLazyDPSEvaluation ();
10989 aopPut (AOP(result),"dpl",0);
10990 aopPut (AOP(result),"dph",1);
10991 if (options.model == MODEL_FLAT24) {
10992 aopPut (AOP(result),"dpx",2);
10993 aopPut (AOP(result),"b",3);
10995 aopPut (AOP(result),"b",2);
10997 _endLazyDPSEvaluation ();
11000 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
11001 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
11003 size = AOP_SIZE (right) - 1;
11004 while (size--) emitcode ("lcall","__decdptr");
11006 freeAsmop (result, NULL, ic, TRUE);
11007 freeAsmop (right, NULL, ic, TRUE);
11010 /*-----------------------------------------------------------------*/
11011 /* genPointerSet - stores the value into a pointer location */
11012 /*-----------------------------------------------------------------*/
11014 genPointerSet (iCode * ic, iCode *pi)
11016 operand *right, *result;
11017 sym_link *type, *etype;
11020 D (emitcode (";", "genPointerSet "););
11022 right = IC_RIGHT (ic);
11023 result = IC_RESULT (ic);
11025 /* depending on the type of pointer we need to
11026 move it to the correct pointer register */
11027 type = operandType (result);
11028 etype = getSpec (type);
11029 /* if left is of type of pointer then it is simple */
11030 if (IS_PTR (type) && !IS_FUNC (type->next))
11032 p_type = DCL_TYPE (type);
11036 /* we have to go by the storage class */
11037 p_type = PTR_TYPE (SPEC_OCLS (etype));
11039 /* special case when cast remat */
11040 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
11041 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
11042 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
11043 type = operandType (result);
11044 p_type = DCL_TYPE (type);
11047 /* now that we have the pointer type we assign
11048 the pointer values */
11054 genNearPointerSet (right, result, ic, pi);
11058 genPagedPointerSet (right, result, ic, pi);
11062 genFarPointerSet (right, result, ic, pi);
11066 genGenPointerSet (right, result, ic, pi);
11070 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11071 "genPointerSet: illegal pointer type");
11076 /*-----------------------------------------------------------------*/
11077 /* genIfx - generate code for Ifx statement */
11078 /*-----------------------------------------------------------------*/
11080 genIfx (iCode * ic, iCode * popIc)
11082 operand *cond = IC_COND (ic);
11085 D (emitcode (";", "genIfx "););
11087 aopOp (cond, ic, FALSE, FALSE);
11089 /* get the value into acc */
11090 if (AOP_TYPE (cond) != AOP_CRY)
11099 /* the result is now in the accumulator */
11100 freeAsmop (cond, NULL, ic, TRUE);
11102 /* if there was something to be popped then do it */
11106 /* if the condition is a bit variable */
11107 if (isbit && IS_ITEMP (cond) &&
11110 genIfxJump (ic, SPIL_LOC (cond)->rname);
11112 else if (isbit && !IS_ITEMP (cond))
11114 genIfxJump (ic, OP_SYMBOL (cond)->rname);
11118 genIfxJump (ic, "a");
11124 /*-----------------------------------------------------------------*/
11125 /* genAddrOf - generates code for address of */
11126 /*-----------------------------------------------------------------*/
11128 genAddrOf (iCode * ic)
11130 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11133 D (emitcode (";", "genAddrOf ");
11136 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11138 /* if the operand is on the stack then we
11139 need to get the stack offset of this
11141 if (sym->onStack) {
11143 /* if 10 bit stack */
11144 if (options.stack10bit) {
11148 tsprintf(buff, sizeof(buff),
11149 "#!constbyte",(options.stack_loc >> 16) & 0xff);
11150 /* if it has an offset then we need to compute it */
11151 /* emitcode ("subb", "a,#!constbyte", */
11152 /* -((sym->stack < 0) ? */
11153 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11154 /* ((short) sym->stack)) & 0xff); */
11155 /* emitcode ("mov","b,a"); */
11156 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
11157 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11158 /* ((short) sym->stack)) >> 8) & 0xff); */
11160 emitcode ("mov", "a,_bpx");
11161 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
11162 ((char) (sym->stack - _G.nRegsSaved)) :
11163 ((char) sym->stack )) & 0xff);
11164 emitcode ("mov", "b,a");
11165 emitcode ("mov", "a,_bpx+1");
11167 offset = (((sym->stack < 0) ?
11168 ((short) (sym->stack - _G.nRegsSaved)) :
11169 ((short) sym->stack )) >> 8) & 0xff;
11171 emitcode ("addc","a,#!constbyte", offset);
11173 aopPut (AOP (IC_RESULT (ic)), "b", 0);
11174 aopPut (AOP (IC_RESULT (ic)), "a", 1);
11175 aopPut (AOP (IC_RESULT (ic)), buff, 2);
11177 /* we can just move _bp */
11178 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
11179 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
11180 aopPut (AOP (IC_RESULT (ic)), buff, 2);
11183 /* if it has an offset then we need to compute it */
11185 emitcode ("mov", "a,_bp");
11186 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
11187 aopPut (AOP (IC_RESULT (ic)), "a", 0);
11189 /* we can just move _bp */
11190 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
11192 /* fill the result with zero */
11193 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11196 if (options.stack10bit && size < (FPTRSIZE - 1)) {
11198 "*** warning: pointer to stack var truncated.\n");
11203 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
11209 /* object not on stack then we need the name */
11210 size = AOP_SIZE (IC_RESULT (ic));
11215 char s[SDCC_NAME_MAX];
11219 tsprintf(s, sizeof(s), "#!his",sym->rname);
11222 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
11225 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
11227 default: /* should not need this (just in case) */
11228 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
11235 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11238 aopPut (AOP (IC_RESULT (ic)), s, offset++);
11242 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11246 #if 0 // obsolete, and buggy for != xdata
11247 /*-----------------------------------------------------------------*/
11248 /* genArrayInit - generates code for address of */
11249 /*-----------------------------------------------------------------*/
11251 genArrayInit (iCode * ic)
11253 literalList *iLoop;
11255 int elementSize = 0, eIndex;
11256 unsigned val, lastVal;
11258 operand *left=IC_LEFT(ic);
11260 D (emitcode (";", "genArrayInit "););
11262 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
11264 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
11266 // Load immediate value into DPTR.
11267 emitcode("mov", "dptr, %s",
11268 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
11270 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
11273 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11274 "Unexpected operand to genArrayInit.\n");
11277 // a regression because of SDCCcse.c:1.52
11278 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
11279 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
11280 if (options.model == MODEL_FLAT24)
11281 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
11285 type = operandType(IC_LEFT(ic));
11287 if (type && type->next)
11289 elementSize = getSize(type->next);
11293 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11294 "can't determine element size in genArrayInit.\n");
11298 iLoop = IC_ARRAYILIST(ic);
11303 bool firstpass = TRUE;
11305 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
11306 iLoop->count, (int)iLoop->literalValue, elementSize);
11312 symbol *tlbl = NULL;
11314 count = ix > 256 ? 256 : ix;
11318 tlbl = newiTempLabel (NULL);
11319 if (firstpass || (count & 0xff))
11321 emitcode("mov", "b, #!constbyte", count & 0xff);
11324 emitcode ("", "!tlabeldef", tlbl->key + 100);
11329 for (eIndex = 0; eIndex < elementSize; eIndex++)
11331 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
11332 if (val != lastVal)
11334 emitcode("mov", "a, #!constbyte", val);
11338 emitcode("movx", "@dptr, a");
11339 emitcode("inc", "dptr");
11344 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
11350 iLoop = iLoop->next;
11353 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
11357 /*-----------------------------------------------------------------*/
11358 /* genFarFarAssign - assignment when both are in far space */
11359 /*-----------------------------------------------------------------*/
11361 genFarFarAssign (operand * result, operand * right, iCode * ic)
11363 int size = AOP_SIZE (right);
11365 symbol *rSym = NULL;
11369 /* quick & easy case. */
11370 D(emitcode(";","genFarFarAssign (1 byte case)"););
11371 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
11372 freeAsmop (right, NULL, ic, FALSE);
11373 /* now assign DPTR to result */
11375 aopOp(result, ic, FALSE, FALSE);
11377 aopPut(AOP(result), "a", 0);
11378 freeAsmop(result, NULL, ic, FALSE);
11382 /* See if we've got an underlying symbol to abuse. */
11383 if (IS_SYMOP(result) && OP_SYMBOL(result))
11385 if (IS_TRUE_SYMOP(result))
11387 rSym = OP_SYMBOL(result);
11389 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
11391 rSym = OP_SYMBOL(result)->usl.spillLoc;
11395 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
11397 /* We can use the '390 auto-toggle feature to good effect here. */
11399 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
11400 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11401 emitcode ("mov", "dptr,#%s", rSym->rname);
11402 /* DP2 = result, DP1 = right, DP1 is current. */
11405 emitcode("movx", "a,@dptr");
11406 emitcode("movx", "@dptr,a");
11409 emitcode("inc", "dptr");
11410 emitcode("inc", "dptr");
11413 emitcode("mov", "dps,#0");
11414 freeAsmop (right, NULL, ic, FALSE);
11416 some alternative code for processors without auto-toggle
11417 no time to test now, so later well put in...kpb
11418 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
11419 emitcode("mov", "dps,#1"); /* Select DPTR2. */
11420 emitcode ("mov", "dptr,#%s", rSym->rname);
11421 /* DP2 = result, DP1 = right, DP1 is current. */
11425 emitcode("movx", "a,@dptr");
11427 emitcode("inc", "dptr");
11428 emitcode("inc", "dps");
11429 emitcode("movx", "@dptr,a");
11431 emitcode("inc", "dptr");
11432 emitcode("inc", "dps");
11434 emitcode("mov", "dps,#0");
11435 freeAsmop (right, NULL, ic, FALSE);
11440 D (emitcode (";", "genFarFarAssign"););
11441 aopOp (result, ic, TRUE, TRUE);
11443 _startLazyDPSEvaluation ();
11447 aopPut (AOP (result),
11448 aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
11451 _endLazyDPSEvaluation ();
11452 freeAsmop (result, NULL, ic, FALSE);
11453 freeAsmop (right, NULL, ic, FALSE);
11457 /*-----------------------------------------------------------------*/
11458 /* genAssign - generate code for assignment */
11459 /*-----------------------------------------------------------------*/
11461 genAssign (iCode * ic)
11463 operand *result, *right;
11465 unsigned long lit = 0L;
11467 D (emitcode (";", "genAssign ");
11470 result = IC_RESULT (ic);
11471 right = IC_RIGHT (ic);
11473 /* if they are the same */
11474 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11477 aopOp (right, ic, FALSE, FALSE);
11479 emitcode (";", "genAssign: resultIsFar = %s",
11480 isOperandInFarSpace (result) ?
11483 /* special case both in far space */
11484 if ((AOP_TYPE (right) == AOP_DPTR ||
11485 AOP_TYPE (right) == AOP_DPTR2) &&
11486 /* IS_TRUE_SYMOP(result) && */
11487 isOperandInFarSpace (result))
11489 genFarFarAssign (result, right, ic);
11493 aopOp (result, ic, TRUE, FALSE);
11495 /* if they are the same registers */
11496 if (sameRegs (AOP (right), AOP (result)))
11499 /* if the result is a bit */
11500 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
11502 /* if the right size is a literal then
11503 we know what the value is */
11504 if (AOP_TYPE (right) == AOP_LIT)
11506 if (((int) operandLitValue (right)))
11507 aopPut (AOP (result), one, 0);
11509 aopPut (AOP (result), zero, 0);
11513 /* the right is also a bit variable */
11514 if (AOP_TYPE (right) == AOP_CRY)
11516 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11517 aopPut (AOP (result), "c", 0);
11521 /* we need to or */
11523 aopPut (AOP (result), "a", 0);
11527 /* bit variables done */
11529 size = AOP_SIZE (result);
11531 if (AOP_TYPE (right) == AOP_LIT)
11532 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11535 (AOP_TYPE (result) != AOP_REG) &&
11536 (AOP_TYPE (right) == AOP_LIT) &&
11537 !IS_FLOAT (operandType (right)))
11539 _startLazyDPSEvaluation ();
11540 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
11542 aopPut (AOP (result),
11543 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11548 /* And now fill the rest with zeros. */
11551 emitcode ("clr", "a");
11555 aopPut (AOP (result), "a", offset++);
11557 _endLazyDPSEvaluation ();
11561 _startLazyDPSEvaluation ();
11564 aopPut (AOP (result),
11565 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11569 _endLazyDPSEvaluation ();
11573 freeAsmop (right, NULL, ic, FALSE);
11574 freeAsmop (result, NULL, ic, TRUE);
11577 /*-----------------------------------------------------------------*/
11578 /* genJumpTab - generates code for jump table */
11579 /*-----------------------------------------------------------------*/
11581 genJumpTab (iCode * ic)
11586 D (emitcode (";", "genJumpTab ");
11589 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11590 /* get the condition into accumulator */
11591 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11593 /* multiply by four! */
11594 emitcode ("add", "a,acc");
11595 emitcode ("add", "a,acc");
11596 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11598 jtab = newiTempLabel (NULL);
11599 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11600 emitcode ("jmp", "@a+dptr");
11601 emitcode ("", "!tlabeldef", jtab->key + 100);
11602 /* now generate the jump labels */
11603 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11604 jtab = setNextItem (IC_JTLABELS (ic)))
11605 emitcode ("ljmp", "!tlabel", jtab->key + 100);
11609 /*-----------------------------------------------------------------*/
11610 /* genCast - gen code for casting */
11611 /*-----------------------------------------------------------------*/
11613 genCast (iCode * ic)
11615 operand *result = IC_RESULT (ic);
11616 sym_link *ctype = operandType (IC_LEFT (ic));
11617 sym_link *rtype = operandType (IC_RIGHT (ic));
11618 operand *right = IC_RIGHT (ic);
11621 D (emitcode (";", "genCast "););
11623 /* if they are equivalent then do nothing */
11624 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11627 aopOp (right, ic, FALSE, AOP_IS_STR (result));
11628 aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
11630 /* if the result is a bit */
11631 if (IS_BITVAR (OP_SYMBOL (result)->type)
11632 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11634 /* if the right size is a literal then
11635 we know what the value is */
11636 if (AOP_TYPE (right) == AOP_LIT)
11638 if (((int) operandLitValue (right)))
11639 aopPut (AOP (result), one, 0);
11641 aopPut (AOP (result), zero, 0);
11646 /* the right is also a bit variable */
11647 if (AOP_TYPE (right) == AOP_CRY)
11649 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11650 aopPut (AOP (result), "c", 0);
11654 /* we need to or */
11656 aopPut (AOP (result), "a", 0);
11660 /* if they are the same size : or less */
11661 if (AOP_SIZE (result) <= AOP_SIZE (right))
11664 /* if they are in the same place */
11665 if (sameRegs (AOP (right), AOP (result)))
11668 /* if they in different places then copy */
11669 size = AOP_SIZE (result);
11671 _startLazyDPSEvaluation ();
11674 aopPut (AOP (result),
11675 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11679 _endLazyDPSEvaluation ();
11684 /* if the result is of type pointer */
11685 if (IS_PTR (ctype))
11689 sym_link *type = operandType (right);
11691 /* pointer to generic pointer */
11692 if (IS_GENPTR (ctype))
11696 p_type = DCL_TYPE (type);
11700 #if OLD_CAST_BEHAVIOR
11701 /* KV: we are converting a non-pointer type to
11702 * a generic pointer. This (ifdef'd out) code
11703 * says that the resulting generic pointer
11704 * should have the same class as the storage
11705 * location of the non-pointer variable.
11707 * For example, converting an int (which happens
11708 * to be stored in DATA space) to a pointer results
11709 * in a DATA generic pointer; if the original int
11710 * in XDATA space, so will be the resulting pointer.
11712 * I don't like that behavior, and thus this change:
11713 * all such conversions will be forced to XDATA and
11714 * throw a warning. If you want some non-XDATA
11715 * type, or you want to suppress the warning, you
11716 * must go through an intermediate cast, like so:
11718 * char _generic *gp = (char _xdata *)(intVar);
11720 sym_link *etype = getSpec (type);
11722 /* we have to go by the storage class */
11723 if (SPEC_OCLS (etype) != generic)
11725 p_type = PTR_TYPE (SPEC_OCLS (etype));
11730 /* Converting unknown class (i.e. register variable)
11731 * to generic pointer. This is not good, but
11732 * we'll make a guess (and throw a warning).
11735 werror (W_INT_TO_GEN_PTR_CAST);
11739 /* the first two bytes are known */
11740 size = GPTRSIZE - 1;
11742 _startLazyDPSEvaluation ();
11745 aopPut (AOP (result),
11746 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11750 _endLazyDPSEvaluation ();
11752 /* the last byte depending on type */
11754 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11759 // pointerTypeToGPByte will have bitched.
11763 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%x", gpVal);
11764 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11769 /* just copy the pointers */
11770 size = AOP_SIZE (result);
11772 _startLazyDPSEvaluation ();
11775 aopPut (AOP (result),
11776 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11780 _endLazyDPSEvaluation ();
11784 /* so we now know that the size of destination is greater
11785 than the size of the source */
11786 /* we move to result for the size of source */
11787 size = AOP_SIZE (right);
11789 _startLazyDPSEvaluation ();
11792 aopPut (AOP (result),
11793 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11797 _endLazyDPSEvaluation ();
11799 /* now depending on the sign of the source && destination */
11800 size = AOP_SIZE (result) - AOP_SIZE (right);
11801 /* if unsigned or not an integral type */
11802 /* also, if the source is a bit, we don't need to sign extend, because
11803 * it can't possibly have set the sign bit.
11805 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11809 aopPut (AOP (result), zero, offset++);
11814 /* we need to extend the sign :{ */
11815 MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11816 FALSE, FALSE, NULL));
11817 emitcode ("rlc", "a");
11818 emitcode ("subb", "a,acc");
11820 aopPut (AOP (result), "a", offset++);
11823 /* we are done hurray !!!! */
11826 freeAsmop (right, NULL, ic, TRUE);
11827 freeAsmop (result, NULL, ic, TRUE);
11831 /*-----------------------------------------------------------------*/
11832 /* genDjnz - generate decrement & jump if not zero instrucion */
11833 /*-----------------------------------------------------------------*/
11835 genDjnz (iCode * ic, iCode * ifx)
11837 symbol *lbl, *lbl1;
11841 /* if the if condition has a false label
11842 then we cannot save */
11843 if (IC_FALSE (ifx))
11846 /* if the minus is not of the form
11848 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11849 !IS_OP_LITERAL (IC_RIGHT (ic)))
11852 if (operandLitValue (IC_RIGHT (ic)) != 1)
11855 /* if the size of this greater than one then no
11857 if (getSize (operandType (IC_RESULT (ic))) > 1)
11860 /* otherwise we can save BIG */
11861 D(emitcode(";", "genDjnz"););
11863 lbl = newiTempLabel (NULL);
11864 lbl1 = newiTempLabel (NULL);
11866 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11868 if (AOP_NEEDSACC(IC_RESULT(ic)))
11870 /* If the result is accessed indirectly via
11871 * the accumulator, we must explicitly write
11872 * it back after the decrement.
11874 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11876 if (strcmp(rByte, "a"))
11878 /* Something is hopelessly wrong */
11879 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11880 __FILE__, __LINE__);
11881 /* We can just give up; the generated code will be inefficient,
11882 * but what the hey.
11884 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11887 emitcode ("dec", "%s", rByte);
11888 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11889 emitcode ("jnz", "!tlabel", lbl->key + 100);
11891 else if (IS_AOP_PREG (IC_RESULT (ic)))
11893 emitcode ("dec", "%s",
11894 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11895 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11896 emitcode ("jnz", "!tlabel", lbl->key + 100);
11900 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11903 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11904 emitcode ("", "!tlabeldef", lbl->key + 100);
11905 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11906 emitcode ("", "!tlabeldef", lbl1->key + 100);
11908 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11909 ifx->generated = 1;
11913 /*-----------------------------------------------------------------*/
11914 /* genReceive - generate code for a receive iCode */
11915 /*-----------------------------------------------------------------*/
11917 genReceive (iCode * ic)
11919 int size = getSize (operandType (IC_RESULT (ic)));
11923 D (emitcode (";", "genReceive "););
11925 if (ic->argreg == 1)
11927 /* first parameter */
11928 if (AOP_IS_STR(IC_RESULT(ic)))
11930 /* Nothing to do: it's already in the proper place. */
11937 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11938 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11939 IS_TRUE_SYMOP (IC_RESULT (ic)));
11942 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11945 /* Sanity checking... */
11946 if (AOP_USESDPTR(IC_RESULT(ic)))
11948 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11949 "genReceive got unexpected DPTR.");
11951 assignResultValue (IC_RESULT (ic));
11956 /* second receive onwards */
11957 /* this gets a little tricky since unused recevies will be
11958 eliminated, we have saved the reg in the type field . and
11959 we use that to figure out which register to use */
11960 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11961 rb1off = ic->argreg;
11964 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11967 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11970 /*-----------------------------------------------------------------*/
11971 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11972 /*-----------------------------------------------------------------*/
11973 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11975 operand *from , *to , *count;
11980 /* we know it has to be 3 parameters */
11981 assert (nparms == 3);
11983 rsave = newBitVect(16);
11984 /* save DPTR if it needs to be saved */
11985 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11986 if (bitVectBitValue(ic->rMask,i))
11987 rsave = bitVectSetBit(rsave,i);
11989 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11990 ds390_rUmaskForOp (IC_RESULT(ic))));
11997 aopOp (from, ic->next, FALSE, FALSE);
11999 /* get from into DPTR1 */
12000 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12001 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12002 if (options.model == MODEL_FLAT24) {
12003 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12006 freeAsmop (from, NULL, ic, FALSE);
12007 aopOp (to, ic, FALSE, FALSE);
12008 /* get "to" into DPTR */
12009 /* if the operand is already in dptr
12010 then we do nothing else we move the value to dptr */
12011 if (AOP_TYPE (to) != AOP_STR) {
12012 /* if already in DPTR then we need to push */
12013 if (AOP_TYPE(to) == AOP_DPTR) {
12014 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12015 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12016 if (options.model == MODEL_FLAT24)
12017 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12018 emitcode ("pop", "dph");
12019 emitcode ("pop", "dpl");
12021 _startLazyDPSEvaluation ();
12022 /* if this is remateriazable */
12023 if (AOP_TYPE (to) == AOP_IMMD) {
12024 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12025 } else { /* we need to get it byte by byte */
12026 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12027 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12028 if (options.model == MODEL_FLAT24) {
12029 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12032 _endLazyDPSEvaluation ();
12035 freeAsmop (to, NULL, ic, FALSE);
12036 _G.dptrInUse = _G.dptr1InUse = 1;
12037 aopOp (count, ic->next->next, FALSE,FALSE);
12038 lbl =newiTempLabel(NULL);
12040 /* now for the actual copy */
12041 if (AOP_TYPE(count) == AOP_LIT &&
12042 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12043 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12045 emitcode ("lcall","__bi_memcpyc2x_s");
12047 emitcode ("lcall","__bi_memcpyx2x_s");
12049 freeAsmop (count, NULL, ic, FALSE);
12051 symbol *lbl1 = newiTempLabel(NULL);
12053 emitcode (";"," Auto increment but no djnz");
12054 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12055 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12056 freeAsmop (count, NULL, ic, FALSE);
12057 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12058 emitcode ("","!tlabeldef",lbl->key+100);
12060 emitcode ("clr","a");
12061 emitcode ("movc", "a,@a+dptr");
12063 emitcode ("movx", "a,@dptr");
12064 emitcode ("movx", "@dptr,a");
12065 emitcode ("inc", "dptr");
12066 emitcode ("inc", "dptr");
12067 emitcode ("mov","a,b");
12068 emitcode ("orl","a,_ap");
12069 emitcode ("jz","!tlabel",lbl1->key+100);
12070 emitcode ("mov","a,_ap");
12071 emitcode ("add","a,#!constbyte",0xFF);
12072 emitcode ("mov","_ap,a");
12073 emitcode ("mov","a,b");
12074 emitcode ("addc","a,#!constbyte",0xFF);
12075 emitcode ("mov","b,a");
12076 emitcode ("sjmp","!tlabel",lbl->key+100);
12077 emitcode ("","!tlabeldef",lbl1->key+100);
12079 emitcode ("mov", "dps,#0");
12080 _G.dptrInUse = _G.dptr1InUse = 0;
12081 unsavermask(rsave);
12085 /*-----------------------------------------------------------------*/
12086 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
12087 /*-----------------------------------------------------------------*/
12088 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
12090 operand *from , *to , *count;
12095 /* we know it has to be 3 parameters */
12096 assert (nparms == 3);
12098 rsave = newBitVect(16);
12099 /* save DPTR if it needs to be saved */
12100 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12101 if (bitVectBitValue(ic->rMask,i))
12102 rsave = bitVectSetBit(rsave,i);
12104 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12105 ds390_rUmaskForOp (IC_RESULT(ic))));
12112 aopOp (from, ic->next, FALSE, FALSE);
12114 /* get from into DPTR1 */
12115 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12116 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12117 if (options.model == MODEL_FLAT24) {
12118 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12121 freeAsmop (from, NULL, ic, FALSE);
12122 aopOp (to, ic, FALSE, FALSE);
12123 /* get "to" into DPTR */
12124 /* if the operand is already in dptr
12125 then we do nothing else we move the value to dptr */
12126 if (AOP_TYPE (to) != AOP_STR) {
12127 /* if already in DPTR then we need to push */
12128 if (AOP_TYPE(to) == AOP_DPTR) {
12129 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12130 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12131 if (options.model == MODEL_FLAT24)
12132 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12133 emitcode ("pop", "dph");
12134 emitcode ("pop", "dpl");
12136 _startLazyDPSEvaluation ();
12137 /* if this is remateriazable */
12138 if (AOP_TYPE (to) == AOP_IMMD) {
12139 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12140 } else { /* we need to get it byte by byte */
12141 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12142 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12143 if (options.model == MODEL_FLAT24) {
12144 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12147 _endLazyDPSEvaluation ();
12150 freeAsmop (to, NULL, ic, FALSE);
12151 _G.dptrInUse = _G.dptr1InUse = 1;
12152 aopOp (count, ic->next->next, FALSE,FALSE);
12153 lbl =newiTempLabel(NULL);
12154 lbl2 =newiTempLabel(NULL);
12156 /* now for the actual compare */
12157 if (AOP_TYPE(count) == AOP_LIT &&
12158 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12159 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12161 emitcode("lcall","__bi_memcmpc2x_s");
12163 emitcode("lcall","__bi_memcmpx2x_s");
12164 freeAsmop (count, NULL, ic, FALSE);
12165 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12166 aopPut(AOP(IC_RESULT(ic)),"a",0);
12167 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12169 symbol *lbl1 = newiTempLabel(NULL);
12171 emitcode("push","ar0");
12172 emitcode (";"," Auto increment but no djnz");
12173 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12174 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12175 freeAsmop (count, NULL, ic, FALSE);
12176 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12177 emitcode ("","!tlabeldef",lbl->key+100);
12179 emitcode ("clr","a");
12180 emitcode ("movc", "a,@a+dptr");
12182 emitcode ("movx", "a,@dptr");
12183 emitcode ("mov","r0,a");
12184 emitcode ("movx", "a,@dptr");
12185 emitcode ("clr","c");
12186 emitcode ("subb","a,r0");
12187 emitcode ("jnz","!tlabel",lbl2->key+100);
12188 emitcode ("inc", "dptr");
12189 emitcode ("inc", "dptr");
12190 emitcode ("mov","a,b");
12191 emitcode ("orl","a,_ap");
12192 emitcode ("jz","!tlabel",lbl1->key+100);
12193 emitcode ("mov","a,_ap");
12194 emitcode ("add","a,#!constbyte",0xFF);
12195 emitcode ("mov","_ap,a");
12196 emitcode ("mov","a,b");
12197 emitcode ("addc","a,#!constbyte",0xFF);
12198 emitcode ("mov","b,a");
12199 emitcode ("sjmp","!tlabel",lbl->key+100);
12200 emitcode ("","!tlabeldef",lbl1->key+100);
12201 emitcode ("clr","a");
12202 emitcode ("","!tlabeldef",lbl2->key+100);
12203 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12204 aopPut(AOP(IC_RESULT(ic)),"a",0);
12205 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12206 emitcode("pop","ar0");
12207 emitcode ("mov", "dps,#0");
12209 _G.dptrInUse = _G.dptr1InUse = 0;
12210 unsavermask(rsave);
12214 /*-----------------------------------------------------------------*/
12215 /* genInp - gen code for __builtin_inp read data from a mem mapped */
12216 /* port, first parameter output area second parameter pointer to */
12217 /* port third parameter count */
12218 /*-----------------------------------------------------------------*/
12219 static void genInp( iCode *ic, int nparms, operand **parms)
12221 operand *from , *to , *count;
12226 /* we know it has to be 3 parameters */
12227 assert (nparms == 3);
12229 rsave = newBitVect(16);
12230 /* save DPTR if it needs to be saved */
12231 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12232 if (bitVectBitValue(ic->rMask,i))
12233 rsave = bitVectSetBit(rsave,i);
12235 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12236 ds390_rUmaskForOp (IC_RESULT(ic))));
12243 aopOp (from, ic->next, FALSE, FALSE);
12245 /* get from into DPTR1 */
12246 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12247 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12248 if (options.model == MODEL_FLAT24) {
12249 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12252 freeAsmop (from, NULL, ic, FALSE);
12253 aopOp (to, ic, FALSE, FALSE);
12254 /* get "to" into DPTR */
12255 /* if the operand is already in dptr
12256 then we do nothing else we move the value to dptr */
12257 if (AOP_TYPE (to) != AOP_STR) {
12258 /* if already in DPTR then we need to push */
12259 if (AOP_TYPE(to) == AOP_DPTR) {
12260 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12261 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12262 if (options.model == MODEL_FLAT24)
12263 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12264 emitcode ("pop", "dph");
12265 emitcode ("pop", "dpl");
12267 _startLazyDPSEvaluation ();
12268 /* if this is remateriazable */
12269 if (AOP_TYPE (to) == AOP_IMMD) {
12270 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12271 } else { /* we need to get it byte by byte */
12272 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12273 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12274 if (options.model == MODEL_FLAT24) {
12275 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12278 _endLazyDPSEvaluation ();
12281 freeAsmop (to, NULL, ic, FALSE);
12283 _G.dptrInUse = _G.dptr1InUse = 1;
12284 aopOp (count, ic->next->next, FALSE,FALSE);
12285 lbl =newiTempLabel(NULL);
12287 /* now for the actual copy */
12288 if (AOP_TYPE(count) == AOP_LIT &&
12289 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12290 emitcode (";","OH JOY auto increment with djnz (very fast)");
12291 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12292 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12293 freeAsmop (count, NULL, ic, FALSE);
12294 emitcode ("","!tlabeldef",lbl->key+100);
12295 emitcode ("movx", "a,@dptr"); /* read data from port */
12296 emitcode ("dec","dps"); /* switch to DPTR */
12297 emitcode ("movx", "@dptr,a"); /* save into location */
12298 emitcode ("inc", "dptr"); /* point to next area */
12299 emitcode ("inc","dps"); /* switch to DPTR2 */
12300 emitcode ("djnz","b,!tlabel",lbl->key+100);
12302 symbol *lbl1 = newiTempLabel(NULL);
12304 emitcode (";"," Auto increment but no djnz");
12305 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12306 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12307 freeAsmop (count, NULL, ic, FALSE);
12308 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12309 emitcode ("","!tlabeldef",lbl->key+100);
12310 emitcode ("movx", "a,@dptr");
12311 emitcode ("dec","dps"); /* switch to DPTR */
12312 emitcode ("movx", "@dptr,a");
12313 emitcode ("inc", "dptr");
12314 emitcode ("inc","dps"); /* switch to DPTR2 */
12315 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
12316 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
12317 emitcode ("mov","a,b");
12318 emitcode ("orl","a,_ap");
12319 emitcode ("jz","!tlabel",lbl1->key+100);
12320 emitcode ("mov","a,_ap");
12321 emitcode ("add","a,#!constbyte",0xFF);
12322 emitcode ("mov","_ap,a");
12323 emitcode ("mov","a,b");
12324 emitcode ("addc","a,#!constbyte",0xFF);
12325 emitcode ("mov","b,a");
12326 emitcode ("sjmp","!tlabel",lbl->key+100);
12327 emitcode ("","!tlabeldef",lbl1->key+100);
12329 emitcode ("mov", "dps,#0");
12330 _G.dptrInUse = _G.dptr1InUse = 0;
12331 unsavermask(rsave);
12335 /*-----------------------------------------------------------------*/
12336 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
12337 /* port, first parameter output area second parameter pointer to */
12338 /* port third parameter count */
12339 /*-----------------------------------------------------------------*/
12340 static void genOutp( iCode *ic, int nparms, operand **parms)
12342 operand *from , *to , *count;
12347 /* we know it has to be 3 parameters */
12348 assert (nparms == 3);
12350 rsave = newBitVect(16);
12351 /* save DPTR if it needs to be saved */
12352 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12353 if (bitVectBitValue(ic->rMask,i))
12354 rsave = bitVectSetBit(rsave,i);
12356 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12357 ds390_rUmaskForOp (IC_RESULT(ic))));
12364 aopOp (from, ic->next, FALSE, FALSE);
12366 /* get from into DPTR1 */
12367 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12368 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12369 if (options.model == MODEL_FLAT24) {
12370 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12373 freeAsmop (from, NULL, ic, FALSE);
12374 aopOp (to, ic, FALSE, FALSE);
12375 /* get "to" into DPTR */
12376 /* if the operand is already in dptr
12377 then we do nothing else we move the value to dptr */
12378 if (AOP_TYPE (to) != AOP_STR) {
12379 /* if already in DPTR then we need to push */
12380 if (AOP_TYPE(to) == AOP_DPTR) {
12381 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12382 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12383 if (options.model == MODEL_FLAT24)
12384 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12385 emitcode ("pop", "dph");
12386 emitcode ("pop", "dpl");
12388 _startLazyDPSEvaluation ();
12389 /* if this is remateriazable */
12390 if (AOP_TYPE (to) == AOP_IMMD) {
12391 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12392 } else { /* we need to get it byte by byte */
12393 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12394 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12395 if (options.model == MODEL_FLAT24) {
12396 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12399 _endLazyDPSEvaluation ();
12402 freeAsmop (to, NULL, ic, FALSE);
12404 _G.dptrInUse = _G.dptr1InUse = 1;
12405 aopOp (count, ic->next->next, FALSE,FALSE);
12406 lbl =newiTempLabel(NULL);
12408 /* now for the actual copy */
12409 if (AOP_TYPE(count) == AOP_LIT &&
12410 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12411 emitcode (";","OH JOY auto increment with djnz (very fast)");
12412 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12413 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12414 emitcode ("","!tlabeldef",lbl->key+100);
12415 emitcode ("movx", "a,@dptr"); /* read data from port */
12416 emitcode ("inc","dps"); /* switch to DPTR2 */
12417 emitcode ("movx", "@dptr,a"); /* save into location */
12418 emitcode ("inc", "dptr"); /* point to next area */
12419 emitcode ("dec","dps"); /* switch to DPTR */
12420 emitcode ("djnz","b,!tlabel",lbl->key+100);
12421 freeAsmop (count, NULL, ic, FALSE);
12423 symbol *lbl1 = newiTempLabel(NULL);
12425 emitcode (";"," Auto increment but no djnz");
12426 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12427 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12428 freeAsmop (count, NULL, ic, FALSE);
12429 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12430 emitcode ("","!tlabeldef",lbl->key+100);
12431 emitcode ("movx", "a,@dptr");
12432 emitcode ("inc", "dptr");
12433 emitcode ("inc","dps"); /* switch to DPTR2 */
12434 emitcode ("movx", "@dptr,a");
12435 emitcode ("dec","dps"); /* switch to DPTR */
12436 emitcode ("mov","a,b");
12437 emitcode ("orl","a,_ap");
12438 emitcode ("jz","!tlabel",lbl1->key+100);
12439 emitcode ("mov","a,_ap");
12440 emitcode ("add","a,#!constbyte",0xFF);
12441 emitcode ("mov","_ap,a");
12442 emitcode ("mov","a,b");
12443 emitcode ("addc","a,#!constbyte",0xFF);
12444 emitcode ("mov","b,a");
12445 emitcode ("sjmp","!tlabel",lbl->key+100);
12446 emitcode ("","!tlabeldef",lbl1->key+100);
12448 emitcode ("mov", "dps,#0");
12449 _G.dptrInUse = _G.dptr1InUse = 0;
12450 unsavermask(rsave);
12454 /*-----------------------------------------------------------------*/
12455 /* genSwapW - swap lower & high order bytes */
12456 /*-----------------------------------------------------------------*/
12457 static void genSwapW(iCode *ic, int nparms, operand **parms)
12461 assert (nparms==1);
12464 dest=IC_RESULT(ic);
12466 assert(getSize(operandType(src))==2);
12468 aopOp (src, ic, FALSE, FALSE);
12469 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
12471 MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
12473 freeAsmop (src, NULL, ic, FALSE);
12475 aopOp (dest,ic, FALSE, FALSE);
12476 aopPut(AOP(dest),"b",0);
12477 aopPut(AOP(dest),"a",1);
12478 freeAsmop (dest, NULL, ic, FALSE);
12481 /*-----------------------------------------------------------------*/
12482 /* genMemsetX - gencode for memSetX data */
12483 /*-----------------------------------------------------------------*/
12484 static void genMemsetX(iCode *ic, int nparms, operand **parms)
12486 operand *to , *val , *count;
12492 /* we know it has to be 3 parameters */
12493 assert (nparms == 3);
12499 /* save DPTR if it needs to be saved */
12500 rsave = newBitVect(16);
12501 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12502 if (bitVectBitValue(ic->rMask,i))
12503 rsave = bitVectSetBit(rsave,i);
12505 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12506 ds390_rUmaskForOp (IC_RESULT(ic))));
12509 aopOp (to, ic, FALSE, FALSE);
12510 /* get "to" into DPTR */
12511 /* if the operand is already in dptr
12512 then we do nothing else we move the value to dptr */
12513 if (AOP_TYPE (to) != AOP_STR) {
12514 /* if already in DPTR then we need to push */
12515 if (AOP_TYPE(to) == AOP_DPTR) {
12516 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12517 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12518 if (options.model == MODEL_FLAT24)
12519 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12520 emitcode ("pop", "dph");
12521 emitcode ("pop", "dpl");
12523 _startLazyDPSEvaluation ();
12524 /* if this is remateriazable */
12525 if (AOP_TYPE (to) == AOP_IMMD) {
12526 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12527 } else { /* we need to get it byte by byte */
12528 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12529 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12530 if (options.model == MODEL_FLAT24) {
12531 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12534 _endLazyDPSEvaluation ();
12537 freeAsmop (to, NULL, ic, FALSE);
12539 aopOp (val, ic->next->next, FALSE,FALSE);
12540 aopOp (count, ic->next->next, FALSE,FALSE);
12541 lbl =newiTempLabel(NULL);
12542 /* now for the actual copy */
12543 if (AOP_TYPE(count) == AOP_LIT &&
12544 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12545 l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
12546 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12548 emitcode ("","!tlabeldef",lbl->key+100);
12549 emitcode ("movx", "@dptr,a");
12550 emitcode ("inc", "dptr");
12551 emitcode ("djnz","b,!tlabel",lbl->key+100);
12553 symbol *lbl1 = newiTempLabel(NULL);
12555 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12556 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12557 emitcode ("","!tlabeldef",lbl->key+100);
12558 MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
12559 emitcode ("movx", "@dptr,a");
12560 emitcode ("inc", "dptr");
12561 emitcode ("mov","a,b");
12562 emitcode ("orl","a,_ap");
12563 emitcode ("jz","!tlabel",lbl1->key+100);
12564 emitcode ("mov","a,_ap");
12565 emitcode ("add","a,#!constbyte",0xFF);
12566 emitcode ("mov","_ap,a");
12567 emitcode ("mov","a,b");
12568 emitcode ("addc","a,#!constbyte",0xFF);
12569 emitcode ("mov","b,a");
12570 emitcode ("sjmp","!tlabel",lbl->key+100);
12571 emitcode ("","!tlabeldef",lbl1->key+100);
12573 freeAsmop (count, NULL, ic, FALSE);
12574 unsavermask(rsave);
12577 /*-----------------------------------------------------------------*/
12578 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12579 /*-----------------------------------------------------------------*/
12580 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12583 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_LoadPrimitive");
12596 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12597 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
12598 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12599 for (i = (size-1) ; i >= 0 ; i-- ) {
12600 emitcode ("push","a%s",javaRet[i]);
12602 for (i=0; i < size ; i++ ) {
12603 emitcode ("pop","a%s",
12604 aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12607 for (i = 0 ; i < size ; i++ ) {
12608 aopPut(AOP(result),javaRet[i],i);
12611 freeAsmop (result, NULL, ic, FALSE);
12612 unsavermask(rsave);
12615 /*-----------------------------------------------------------------*/
12616 /* genNatLibLoadPointer - calls TINI api function to load pointer */
12617 /*-----------------------------------------------------------------*/
12618 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12621 operand *pnum, *result;
12625 assert (nparms==1);
12626 /* save registers that need to be saved */
12627 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12628 ds390_rUmaskForOp (IC_RESULT(ic))));
12631 aopOp (pnum, ic, FALSE, FALSE);
12632 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12633 freeAsmop (pnum, NULL, ic, FALSE);
12634 emitcode ("lcall","NatLib_LoadPointer");
12635 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12636 if (AOP_TYPE(result)!=AOP_STR) {
12637 for (i = 0 ; i < size ; i++ ) {
12638 aopPut(AOP(result),fReturn[i],i);
12641 freeAsmop (result, NULL, ic, FALSE);
12642 unsavermask(rsave);
12645 /*-----------------------------------------------------------------*/
12646 /* genNatLibInstallStateBlock - */
12647 /*-----------------------------------------------------------------*/
12648 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
12649 operand **parms, const char *name)
12652 operand *psb, *handle;
12653 assert (nparms==2);
12655 /* save registers that need to be saved */
12656 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12657 ds390_rUmaskForOp (IC_RESULT(ic))));
12661 /* put pointer to state block into DPTR1 */
12662 aopOp (psb, ic, FALSE, FALSE);
12663 if (AOP_TYPE (psb) == AOP_IMMD) {
12664 emitcode ("mov","dps,#1");
12665 emitcode ("mov", "dptr,%s",
12666 aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12667 emitcode ("mov","dps,#0");
12669 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12670 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12671 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12673 freeAsmop (psb, NULL, ic, FALSE);
12675 /* put libraryID into DPTR */
12676 emitcode ("mov","dptr,#LibraryID");
12678 /* put handle into r3:r2 */
12679 aopOp (handle, ic, FALSE, FALSE);
12680 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12681 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12682 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12683 emitcode ("pop","ar3");
12684 emitcode ("pop","ar2");
12686 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12687 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12689 freeAsmop (psb, NULL, ic, FALSE);
12691 /* make the call */
12692 emitcode ("lcall","NatLib_Install%sStateBlock",name);
12694 /* put return value into place*/
12696 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12698 aopPut(AOP(IC_RESULT(ic)),"a",0);
12699 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12700 unsavermask(rsave);
12703 /*-----------------------------------------------------------------*/
12704 /* genNatLibRemoveStateBlock - */
12705 /*-----------------------------------------------------------------*/
12706 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12712 /* save registers that need to be saved */
12713 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12714 ds390_rUmaskForOp (IC_RESULT(ic))));
12716 /* put libraryID into DPTR */
12717 emitcode ("mov","dptr,#LibraryID");
12718 /* make the call */
12719 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12720 unsavermask(rsave);
12723 /*-----------------------------------------------------------------*/
12724 /* genNatLibGetStateBlock - */
12725 /*-----------------------------------------------------------------*/
12726 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12727 operand **parms,const char *name)
12730 symbol *lbl = newiTempLabel(NULL);
12733 /* save registers that need to be saved */
12734 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12735 ds390_rUmaskForOp (IC_RESULT(ic))));
12737 /* put libraryID into DPTR */
12738 emitcode ("mov","dptr,#LibraryID");
12739 /* make the call */
12740 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12741 emitcode ("jnz","!tlabel",lbl->key+100);
12743 /* put return value into place */
12744 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12745 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12746 emitcode ("push","ar3");
12747 emitcode ("push","ar2");
12748 emitcode ("pop","%s",
12749 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12750 emitcode ("pop","%s",
12751 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12753 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12754 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12756 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12757 emitcode ("","!tlabeldef",lbl->key+100);
12758 unsavermask(rsave);
12761 /*-----------------------------------------------------------------*/
12762 /* genMMMalloc - */
12763 /*-----------------------------------------------------------------*/
12764 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12765 int size, const char *name)
12770 symbol *lbl = newiTempLabel(NULL);
12772 assert (nparms == 1);
12773 /* save registers that need to be saved */
12774 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12775 ds390_rUmaskForOp (IC_RESULT(ic))));
12778 aopOp (bsize,ic,FALSE,FALSE);
12780 /* put the size in R4-R2 */
12781 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12782 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12783 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12785 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12786 emitcode("pop","ar4");
12788 emitcode("pop","ar3");
12789 emitcode("pop","ar2");
12791 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12792 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12794 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12797 freeAsmop (bsize, NULL, ic, FALSE);
12799 /* make the call */
12800 emitcode ("lcall","MM_%s",name);
12801 emitcode ("jz","!tlabel",lbl->key+100);
12802 emitcode ("mov","r2,#!constbyte",0xff);
12803 emitcode ("mov","r3,#!constbyte",0xff);
12804 emitcode ("","!tlabeldef",lbl->key+100);
12805 /* we don't care about the pointer : we just save the handle */
12806 rsym = OP_SYMBOL(IC_RESULT(ic));
12807 if (rsym->liveFrom != rsym->liveTo) {
12808 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12809 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12810 emitcode ("push","ar3");
12811 emitcode ("push","ar2");
12812 emitcode ("pop","%s",
12813 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12814 emitcode ("pop","%s",
12815 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12817 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12818 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12820 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12822 unsavermask(rsave);
12825 /*-----------------------------------------------------------------*/
12827 /*-----------------------------------------------------------------*/
12828 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12833 assert (nparms == 1);
12834 /* save registers that need to be saved */
12835 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12836 ds390_rUmaskForOp (IC_RESULT(ic))));
12839 aopOp (handle,ic,FALSE,FALSE);
12841 /* put the size in R4-R2 */
12842 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12843 emitcode("push","%s",
12844 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12845 emitcode("push","%s",
12846 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12847 emitcode("pop","ar3");
12848 emitcode("pop","ar2");
12850 emitcode ("mov","r2,%s",
12851 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12852 emitcode ("mov","r3,%s",
12853 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12855 freeAsmop (handle, NULL, ic, FALSE);
12857 /* make the call */
12858 emitcode ("lcall","MM_Deref");
12861 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12862 if (rsym->liveFrom != rsym->liveTo) {
12863 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12864 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12865 _startLazyDPSEvaluation ();
12867 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12868 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12869 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12871 _endLazyDPSEvaluation ();
12876 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12877 unsavermask(rsave);
12880 /*-----------------------------------------------------------------*/
12881 /* genMMUnrestrictedPersist - */
12882 /*-----------------------------------------------------------------*/
12883 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12888 assert (nparms == 1);
12889 /* save registers that need to be saved */
12890 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12891 ds390_rUmaskForOp (IC_RESULT(ic))));
12894 aopOp (handle,ic,FALSE,FALSE);
12896 /* put the size in R3-R2 */
12897 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12898 emitcode("push","%s",
12899 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12900 emitcode("push","%s",
12901 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12902 emitcode("pop","ar3");
12903 emitcode("pop","ar2");
12905 emitcode ("mov","r2,%s",
12906 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12907 emitcode ("mov","r3,%s",
12908 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12910 freeAsmop (handle, NULL, ic, FALSE);
12912 /* make the call */
12913 emitcode ("lcall","MM_UnrestrictedPersist");
12916 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12917 if (rsym->liveFrom != rsym->liveTo) {
12918 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12919 aopPut(AOP(IC_RESULT(ic)),"a",0);
12920 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12923 unsavermask(rsave);
12926 /*-----------------------------------------------------------------*/
12927 /* genSystemExecJavaProcess - */
12928 /*-----------------------------------------------------------------*/
12929 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12932 operand *handle, *pp;
12934 assert (nparms==2);
12935 /* save registers that need to be saved */
12936 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12937 ds390_rUmaskForOp (IC_RESULT(ic))));
12942 /* put the handle in R3-R2 */
12943 aopOp (handle,ic,FALSE,FALSE);
12944 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12945 emitcode("push","%s",
12946 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12947 emitcode("push","%s",
12948 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12949 emitcode("pop","ar3");
12950 emitcode("pop","ar2");
12952 emitcode ("mov","r2,%s",
12953 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12954 emitcode ("mov","r3,%s",
12955 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12957 freeAsmop (handle, NULL, ic, FALSE);
12959 /* put pointer in DPTR */
12960 aopOp (pp,ic,FALSE,FALSE);
12961 if (AOP_TYPE(pp) == AOP_IMMD) {
12962 emitcode ("mov", "dptr,%s",
12963 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12964 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12965 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12966 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12967 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12969 freeAsmop (handle, NULL, ic, FALSE);
12971 /* make the call */
12972 emitcode ("lcall","System_ExecJavaProcess");
12974 /* put result in place */
12976 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12977 if (rsym->liveFrom != rsym->liveTo) {
12978 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12979 aopPut(AOP(IC_RESULT(ic)),"a",0);
12980 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12984 unsavermask(rsave);
12987 /*-----------------------------------------------------------------*/
12988 /* genSystemRTCRegisters - */
12989 /*-----------------------------------------------------------------*/
12990 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12996 assert (nparms==1);
12997 /* save registers that need to be saved */
12998 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12999 ds390_rUmaskForOp (IC_RESULT(ic))));
13002 /* put pointer in DPTR */
13003 aopOp (pp,ic,FALSE,FALSE);
13004 if (AOP_TYPE (pp) == AOP_IMMD) {
13005 emitcode ("mov","dps,#1");
13006 emitcode ("mov", "dptr,%s",
13007 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
13008 emitcode ("mov","dps,#0");
13010 emitcode ("mov","dpl1,%s",
13011 aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
13012 emitcode ("mov","dph1,%s",
13013 aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
13014 emitcode ("mov","dpx1,%s",
13015 aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
13017 freeAsmop (pp, NULL, ic, FALSE);
13019 /* make the call */
13020 emitcode ("lcall","System_%sRTCRegisters",name);
13022 unsavermask(rsave);
13025 /*-----------------------------------------------------------------*/
13026 /* genSystemThreadSleep - */
13027 /*-----------------------------------------------------------------*/
13028 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
13033 assert (nparms==1);
13034 /* save registers that need to be saved */
13035 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13036 ds390_rUmaskForOp (IC_RESULT(ic))));
13039 aopOp(to,ic,FALSE,FALSE);
13040 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
13041 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
13042 emitcode ("push","%s",
13043 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
13044 emitcode ("push","%s",
13045 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
13046 emitcode ("push","%s",
13047 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
13048 emitcode ("push","%s",
13049 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
13050 emitcode ("pop","ar3");
13051 emitcode ("pop","ar2");
13052 emitcode ("pop","ar1");
13053 emitcode ("pop","ar0");
13055 emitcode ("mov","r0,%s",
13056 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
13057 emitcode ("mov","r1,%s",
13058 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
13059 emitcode ("mov","r2,%s",
13060 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
13061 emitcode ("mov","r3,%s",
13062 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
13064 freeAsmop (to, NULL, ic, FALSE);
13066 /* suspend in acc */
13068 aopOp(s,ic,FALSE,FALSE);
13069 emitcode ("mov","a,%s",
13070 aopGet(AOP(s),0,FALSE,TRUE,NULL));
13071 freeAsmop (s, NULL, ic, FALSE);
13073 /* make the call */
13074 emitcode ("lcall","System_%s",name);
13076 unsavermask(rsave);
13079 /*-----------------------------------------------------------------*/
13080 /* genSystemThreadResume - */
13081 /*-----------------------------------------------------------------*/
13082 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
13087 assert (nparms==2);
13088 /* save registers that need to be saved */
13089 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13090 ds390_rUmaskForOp (IC_RESULT(ic))));
13096 aopOp(pid,ic,FALSE,FALSE);
13097 emitcode ("mov","r0,%s",
13098 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13099 freeAsmop (pid, NULL, ic, FALSE);
13102 aopOp(tid,ic,FALSE,FALSE);
13103 emitcode ("mov","a,%s",
13104 aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
13105 freeAsmop (tid, NULL, ic, FALSE);
13107 emitcode ("lcall","System_ThreadResume");
13109 /* put result into place */
13111 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13112 if (rsym->liveFrom != rsym->liveTo) {
13113 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13114 aopPut(AOP(IC_RESULT(ic)),"a",0);
13115 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13118 unsavermask(rsave);
13121 /*-----------------------------------------------------------------*/
13122 /* genSystemProcessResume - */
13123 /*-----------------------------------------------------------------*/
13124 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
13129 assert (nparms==1);
13130 /* save registers that need to be saved */
13131 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13132 ds390_rUmaskForOp (IC_RESULT(ic))));
13137 aopOp(pid,ic,FALSE,FALSE);
13138 emitcode ("mov","a,%s",
13139 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13140 freeAsmop (pid, NULL, ic, FALSE);
13142 emitcode ("lcall","System_ProcessResume");
13144 unsavermask(rsave);
13147 /*-----------------------------------------------------------------*/
13149 /*-----------------------------------------------------------------*/
13150 static void genSystem (iCode *ic,int nparms,char *name)
13152 assert(nparms == 0);
13154 emitcode ("lcall","System_%s",name);
13157 /*-----------------------------------------------------------------*/
13158 /* genSystemPoll - */
13159 /*-----------------------------------------------------------------*/
13160 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
13165 assert (nparms==1);
13166 /* save registers that need to be saved */
13167 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13168 ds390_rUmaskForOp (IC_RESULT(ic))));
13171 aopOp (fp,ic,FALSE,FALSE);
13172 if (AOP_TYPE (fp) == AOP_IMMD) {
13173 emitcode ("mov", "dptr,%s",
13174 aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
13175 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
13176 emitcode ("mov","dpl,%s",
13177 aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
13178 emitcode ("mov","dph,%s",
13179 aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
13180 emitcode ("mov","dpx,%s",
13181 aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
13183 freeAsmop (fp, NULL, ic, FALSE);
13185 emitcode ("lcall","System_%sPoll",name);
13187 /* put result into place */
13189 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13190 if (rsym->liveFrom != rsym->liveTo) {
13191 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13192 aopPut(AOP(IC_RESULT(ic)),"a",0);
13193 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13196 unsavermask(rsave);
13199 /*-----------------------------------------------------------------*/
13200 /* genSystemGetCurrentID - */
13201 /*-----------------------------------------------------------------*/
13202 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
13204 assert (nparms==0);
13206 emitcode ("lcall","System_GetCurrent%sId",name);
13207 /* put result into place */
13209 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13210 if (rsym->liveFrom != rsym->liveTo) {
13211 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13212 aopPut(AOP(IC_RESULT(ic)),"a",0);
13213 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13218 /*-----------------------------------------------------------------*/
13219 /* genDummyRead - generate code for dummy read of volatiles */
13220 /*-----------------------------------------------------------------*/
13222 genDummyRead (iCode * ic)
13227 D(emitcode("; genDummyRead",""));
13229 op = IC_RIGHT (ic);
13230 if (op && IS_SYMOP (op))
13232 aopOp (op, ic, FALSE, FALSE);
13234 /* if the result is a bit */
13235 if (AOP_TYPE (op) == AOP_CRY)
13236 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13239 /* bit variables done */
13241 size = AOP_SIZE (op);
13245 MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13250 freeAsmop (op, NULL, ic, TRUE);
13254 if (op && IS_SYMOP (op))
13256 aopOp (op, ic, FALSE, FALSE);
13258 /* if the result is a bit */
13259 if (AOP_TYPE (op) == AOP_CRY)
13260 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13263 /* bit variables done */
13265 size = AOP_SIZE (op);
13269 MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13274 freeAsmop (op, NULL, ic, TRUE);
13279 /*-----------------------------------------------------------------*/
13280 /* genCritical - generate code for start of a critical sequence */
13281 /*-----------------------------------------------------------------*/
13283 genCritical (iCode *ic)
13285 symbol *tlbl = newiTempLabel (NULL);
13287 D(emitcode("; genCritical",""));
13289 if (IC_RESULT (ic))
13290 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
13292 emitcode ("setb", "c");
13293 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
13294 emitcode ("clr", "c");
13295 emitcode ("", "%05d$:", (tlbl->key + 100));
13297 if (IC_RESULT (ic))
13298 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
13300 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
13302 if (IC_RESULT (ic))
13303 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13306 /*-----------------------------------------------------------------*/
13307 /* genEndCritical - generate code for end of a critical sequence */
13308 /*-----------------------------------------------------------------*/
13310 genEndCritical (iCode *ic)
13312 D(emitcode("; genEndCritical",""));
13316 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
13317 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
13319 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
13320 emitcode ("mov", "ea,c");
13324 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE));
13325 emitcode ("rrc", "a");
13326 emitcode ("mov", "ea,c");
13328 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
13332 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
13333 emitcode ("mov", "ea,c");
13339 /*-----------------------------------------------------------------*/
13340 /* genBuiltIn - calls the appropriate function to generating code */
13341 /* for a built in function */
13342 /*-----------------------------------------------------------------*/
13343 static void genBuiltIn (iCode *ic)
13345 operand *bi_parms[MAX_BUILTIN_ARGS];
13350 /* get all the arguments for a built in function */
13351 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
13353 /* which function is it */
13354 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
13355 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
13356 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
13357 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
13358 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
13359 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
13360 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
13361 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
13362 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
13363 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
13364 genMemsetX(bi_iCode,nbi_parms,bi_parms);
13365 } else if (strcmp(bif->name,"__builtin_inp")==0) {
13366 genInp(bi_iCode,nbi_parms,bi_parms);
13367 } else if (strcmp(bif->name,"__builtin_outp")==0) {
13368 genOutp(bi_iCode,nbi_parms,bi_parms);
13369 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
13370 genSwapW(bi_iCode,nbi_parms,bi_parms);
13371 /* JavaNative builtIns */
13372 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
13373 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
13374 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
13375 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
13376 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
13377 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
13378 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
13379 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
13380 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
13381 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13382 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
13383 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13384 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
13385 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
13386 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
13387 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
13388 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
13389 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13390 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
13391 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13392 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
13393 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
13394 } else if (strcmp(bif->name,"MM_Malloc")==0) {
13395 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
13396 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
13397 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
13398 } else if (strcmp(bif->name,"MM_Free")==0) {
13399 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
13400 } else if (strcmp(bif->name,"MM_Deref")==0) {
13401 genMMDeref(bi_iCode,nbi_parms,bi_parms);
13402 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
13403 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
13404 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
13405 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
13406 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
13407 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
13408 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
13409 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
13410 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
13411 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
13412 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
13413 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
13414 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
13415 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
13416 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
13417 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
13418 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13419 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13420 } else if (strcmp(bif->name,"System_SaveThread")==0) {
13421 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13422 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13423 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13424 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
13425 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
13426 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
13427 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
13428 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
13429 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
13430 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
13431 genSystem(bi_iCode,nbi_parms,"ProcessYield");
13432 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
13433 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
13434 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
13435 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
13436 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
13437 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
13438 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
13439 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
13440 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
13441 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
13443 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
13449 /*-----------------------------------------------------------------*/
13450 /* gen390Code - generate code for Dallas 390 based controllers */
13451 /*-----------------------------------------------------------------*/
13453 gen390Code (iCode * lic)
13458 lineHead = lineCurr = NULL;
13459 dptrn[1][0] = "dpl1";
13460 dptrn[1][1] = "dph1";
13461 dptrn[1][2] = "dpx1";
13463 if (options.model == MODEL_FLAT24) {
13464 fReturnSizeDS390 = 5;
13465 fReturn = fReturn24;
13467 fReturnSizeDS390 = 4;
13468 fReturn = fReturn16;
13469 options.stack10bit=0;
13472 /* print the allocation information */
13473 if (allocInfo && currFunc)
13474 printAllocInfo (currFunc, codeOutFile);
13476 /* if debug information required */
13477 if (options.debug && currFunc)
13479 debugFile->writeFunction (currFunc, lic);
13481 /* stack pointer name */
13482 if (options.useXstack)
13488 for (ic = lic; ic; ic = ic->next)
13490 _G.current_iCode = ic;
13492 if (ic->lineno && cln != ic->lineno)
13496 debugFile->writeCLine (ic);
13498 if (!options.noCcodeInAsm) {
13499 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
13500 printCLine(ic->filename, ic->lineno));
13504 if (options.iCodeInAsm) {
13505 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
13507 /* if the result is marked as
13508 spilt and rematerializable or code for
13509 this has already been generated then
13511 if (resultRemat (ic) || ic->generated)
13514 /* depending on the operation */
13534 /* IPOP happens only when trying to restore a
13535 spilt live range, if there is an ifx statement
13536 following this pop then the if statement might
13537 be using some of the registers being popped which
13538 would destory the contents of the register so
13539 we need to check for this condition and handle it */
13541 ic->next->op == IFX &&
13542 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
13543 genIfx (ic->next, ic);
13561 genEndFunction (ic);
13581 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
13598 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
13602 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
13609 /* note these two are xlated by algebraic equivalence
13610 during parsing SDCC.y */
13611 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13612 "got '>=' or '<=' shouldn't have come here");
13616 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
13628 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
13632 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
13636 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
13660 genRightShift (ic);
13663 case GET_VALUE_AT_ADDRESS:
13664 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13668 if (POINTER_SET (ic))
13669 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13695 if (ic->builtinSEND) genBuiltIn(ic);
13696 else addSet (&_G.sendSet, ic);
13699 case DUMMY_READ_VOLATILE:
13708 genEndCritical (ic);
13715 #if 0 // obsolete, and buggy for != xdata
13727 /* now we are ready to call the
13728 peep hole optimizer */
13729 if (!options.nopeep)
13730 peepHole (&lineHead);
13732 /* now do the actual printing */
13733 printLine (lineHead, codeOutFile);