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 c->a:x->c by 1 */
8067 /*-----------------------------------------------------------------*/
8071 emitcode ("rrc", "a");
8072 emitcode ("xch", "a,%s", x);
8073 emitcode ("rrc", "a");
8074 emitcode ("xch", "a,%s", x);
8078 #ifdef BETTER_LITERAL_SHIFT
8080 /*-----------------------------------------------------------------*/
8081 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8082 /*-----------------------------------------------------------------*/
8086 emitcode ("xch", "a,%s", x);
8087 emitcode ("rlc", "a");
8088 emitcode ("xch", "a,%s", x);
8089 emitcode ("rlc", "a");
8093 #ifdef BETTER_LITERAL_SHIFT
8094 /*-----------------------------------------------------------------*/
8095 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8096 /*-----------------------------------------------------------------*/
8100 emitcode ("xch", "a,%s", x);
8101 emitcode ("add", "a,acc");
8102 emitcode ("xch", "a,%s", x);
8103 emitcode ("rlc", "a");
8107 #ifdef BETTER_LITERAL_SHIFT
8108 /*-----------------------------------------------------------------*/
8109 /* AccAXLsh - left shift a:x by known count (0..7) */
8110 /*-----------------------------------------------------------------*/
8112 AccAXLsh (char *x, int shCount)
8127 case 5: // AAAAABBB:CCCCCDDD
8129 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8131 emitcode ("anl", "a,#!constbyte",
8132 SLMask[shCount]); // BBB00000:CCCCCDDD
8134 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8136 AccRol (shCount); // DDDCCCCC:BBB00000
8138 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8140 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8142 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8144 emitcode ("anl", "a,#!constbyte",
8145 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8147 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8149 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8152 case 6: // AAAAAABB:CCCCCCDD
8153 emitcode ("anl", "a,#!constbyte",
8154 SRMask[shCount]); // 000000BB:CCCCCCDD
8155 emitcode ("mov", "c,acc.0"); // c = B
8156 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8158 AccAXRrl1 (x); // BCCCCCCD:D000000B
8159 AccAXRrl1 (x); // BBCCCCCC:DD000000
8161 emitcode("rrc","a");
8162 emitcode("xch","a,%s", x);
8163 emitcode("rrc","a");
8164 emitcode("mov","c,acc.0"); //<< get correct bit
8165 emitcode("xch","a,%s", x);
8167 emitcode("rrc","a");
8168 emitcode("xch","a,%s", x);
8169 emitcode("rrc","a");
8170 emitcode("xch","a,%s", x);
8173 case 7: // a:x <<= 7
8175 emitcode ("anl", "a,#!constbyte",
8176 SRMask[shCount]); // 0000000B:CCCCCCCD
8178 emitcode ("mov", "c,acc.0"); // c = B
8180 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8182 AccAXRrl1 (x); // BCCCCCCC:D0000000
8191 #ifdef BETTER_LITERAL_SHIFT
8193 /*-----------------------------------------------------------------*/
8194 /* AccAXRsh - right shift a:x known count (0..7) */
8195 /*-----------------------------------------------------------------*/
8197 AccAXRsh (char *x, int shCount)
8205 AccAXRrl1 (x); // 0->a:x
8210 AccAXRrl1 (x); // 0->a:x
8213 AccAXRrl1 (x); // 0->a:x
8218 case 5: // AAAAABBB:CCCCCDDD = a:x
8220 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8222 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8224 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8226 emitcode ("anl", "a,#!constbyte",
8227 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8229 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8231 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8233 emitcode ("anl", "a,#!constbyte",
8234 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8236 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8238 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8240 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8243 case 6: // AABBBBBB:CCDDDDDD
8245 emitcode ("mov", "c,acc.7");
8246 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8248 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8250 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8252 emitcode ("anl", "a,#!constbyte",
8253 SRMask[shCount]); // 000000AA:BBBBBBCC
8256 case 7: // ABBBBBBB:CDDDDDDD
8258 emitcode ("mov", "c,acc.7"); // c = A
8260 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8262 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8264 emitcode ("anl", "a,#!constbyte",
8265 SRMask[shCount]); // 0000000A:BBBBBBBC
8274 #ifdef BETTER_LITERAL_SHIFT
8275 /*-----------------------------------------------------------------*/
8276 /* AccAXRshS - right shift signed a:x known count (0..7) */
8277 /*-----------------------------------------------------------------*/
8279 AccAXRshS (char *x, int shCount)
8287 emitcode ("mov", "c,acc.7");
8288 AccAXRrl1 (x); // s->a:x
8292 emitcode ("mov", "c,acc.7");
8293 AccAXRrl1 (x); // s->a:x
8295 emitcode ("mov", "c,acc.7");
8296 AccAXRrl1 (x); // s->a:x
8301 case 5: // AAAAABBB:CCCCCDDD = a:x
8303 tlbl = newiTempLabel (NULL);
8304 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8306 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8308 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8310 emitcode ("anl", "a,#!constbyte",
8311 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8313 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8315 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8317 emitcode ("anl", "a,#!constbyte",
8318 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8320 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8322 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8324 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8326 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8327 emitcode ("orl", "a,#!constbyte",
8328 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8330 emitcode ("", "!tlabeldef", tlbl->key + 100);
8331 break; // SSSSAAAA:BBBCCCCC
8333 case 6: // AABBBBBB:CCDDDDDD
8335 tlbl = newiTempLabel (NULL);
8336 emitcode ("mov", "c,acc.7");
8337 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8339 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8341 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8343 emitcode ("anl", "a,#!constbyte",
8344 SRMask[shCount]); // 000000AA:BBBBBBCC
8346 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8347 emitcode ("orl", "a,#!constbyte",
8348 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8350 emitcode ("", "!tlabeldef", tlbl->key + 100);
8352 case 7: // ABBBBBBB:CDDDDDDD
8354 tlbl = newiTempLabel (NULL);
8355 emitcode ("mov", "c,acc.7"); // c = A
8357 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8359 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8361 emitcode ("anl", "a,#!constbyte",
8362 SRMask[shCount]); // 0000000A:BBBBBBBC
8364 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8365 emitcode ("orl", "a,#!constbyte",
8366 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8368 emitcode ("", "!tlabeldef", tlbl->key + 100);
8376 #ifdef BETTER_LITERAL_SHIFT
8378 _loadLeftIntoAx(char **lsb,
8384 // Get the initial value from left into a pair of registers.
8385 // MSB must be in A, LSB can be any register.
8387 // If the result is held in registers, it is an optimization
8388 // if the LSB can be held in the register which will hold the,
8389 // result LSB since this saves us from having to copy it into
8390 // the result following AccAXLsh.
8392 // If the result is addressed indirectly, this is not a gain.
8393 if (AOP_NEEDSACC(result))
8397 _startLazyDPSEvaluation();
8398 if (AOP_TYPE(left) == AOP_DPTR2)
8401 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
8402 // get LSB in DP2_RESULT_REG.
8403 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
8404 assert(!strcmp(leftByte, DP2_RESULT_REG));
8408 // get LSB into DP2_RESULT_REG
8409 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
8410 if (strcmp(leftByte, DP2_RESULT_REG))
8413 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
8416 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
8417 assert(strcmp(leftByte, DP2_RESULT_REG));
8420 _endLazyDPSEvaluation();
8421 *lsb = DP2_RESULT_REG;
8425 if (sameRegs (AOP (result), AOP (left)) &&
8426 ((offl + MSB16) == offr))
8428 /* don't crash result[offr] */
8429 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
8430 emitcode ("xch", "a,%s",
8431 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
8435 movLeft2Result (left, offl, result, offr, 0);
8436 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
8438 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
8439 assert(strcmp(*lsb,"a"));
8444 _storeAxResults(char *lsb,
8448 _startLazyDPSEvaluation();
8449 if (AOP_NEEDSACC(result))
8451 /* We have to explicitly update the result LSB.
8453 emitcode("xch","a,%s", lsb);
8454 aopPut(AOP(result), "a", offr);
8455 emitcode("mov","a,%s", lsb);
8457 if (getDataSize (result) > 1)
8459 aopPut (AOP (result), "a", offr + MSB16);
8461 _endLazyDPSEvaluation();
8464 /*-----------------------------------------------------------------*/
8465 /* shiftL2Left2Result - shift left two bytes from left to result */
8466 /*-----------------------------------------------------------------*/
8468 shiftL2Left2Result (operand * left, int offl,
8469 operand * result, int offr, int shCount)
8473 _loadLeftIntoAx(&lsb, left, result, offl, offr);
8475 AccAXLsh (lsb, shCount);
8477 _storeAxResults(lsb, result, offr);
8481 #ifdef BETTER_LITERAL_SHIFT
8482 /*-----------------------------------------------------------------*/
8483 /* shiftR2Left2Result - shift right two bytes from left to result */
8484 /*-----------------------------------------------------------------*/
8486 shiftR2Left2Result (operand * left, int offl,
8487 operand * result, int offr,
8488 int shCount, int sign)
8492 _loadLeftIntoAx(&lsb, left, result, offl, offr);
8494 /* a:x >> shCount (x = lsb(result)) */
8497 AccAXRshS(lsb, shCount);
8501 AccAXRsh(lsb, shCount);
8504 _storeAxResults(lsb, result, offr);
8508 /*-----------------------------------------------------------------*/
8509 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8510 /*-----------------------------------------------------------------*/
8512 shiftLLeftOrResult (operand * left, int offl,
8513 operand * result, int offr, int shCount)
8515 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8516 /* shift left accumulator */
8518 /* or with result */
8519 emitcode ("orl", "a,%s",
8520 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8521 /* back to result */
8522 aopPut (AOP (result), "a", offr);
8527 /*-----------------------------------------------------------------*/
8528 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8529 /*-----------------------------------------------------------------*/
8531 shiftRLeftOrResult (operand * left, int offl,
8532 operand * result, int offr, int shCount)
8534 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8535 /* shift right accumulator */
8537 /* or with result */
8538 emitcode ("orl", "a,%s",
8539 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8540 /* back to result */
8541 aopPut (AOP (result), "a", offr);
8545 #ifdef BETTER_LITERAL_SHIFT
8546 /*-----------------------------------------------------------------*/
8547 /* genlshOne - left shift a one byte quantity by known count */
8548 /*-----------------------------------------------------------------*/
8550 genlshOne (operand * result, operand * left, int shCount)
8552 D (emitcode (";", "genlshOne "););
8553 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8557 #ifdef BETTER_LITERAL_SHIFT
8558 /*-----------------------------------------------------------------*/
8559 /* genlshTwo - left shift two bytes by known amount != 0 */
8560 /*-----------------------------------------------------------------*/
8562 genlshTwo (operand * result, operand * left, int shCount)
8566 D (emitcode (";", "genlshTwo "););
8568 size = getDataSize (result);
8570 /* if shCount >= 8 */
8575 _startLazyDPSEvaluation();
8581 _endLazyDPSEvaluation();
8582 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8583 aopPut (AOP (result), zero, LSB);
8587 movLeft2Result (left, LSB, result, MSB16, 0);
8588 aopPut (AOP (result), zero, LSB);
8589 _endLazyDPSEvaluation();
8594 aopPut (AOP (result), zero, LSB);
8595 _endLazyDPSEvaluation();
8599 /* 1 <= shCount <= 7 */
8604 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8608 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8616 /*-----------------------------------------------------------------*/
8617 /* shiftLLong - shift left one long from left to result */
8618 /* offl = LSB or MSB16 */
8619 /*-----------------------------------------------------------------*/
8621 shiftLLong (operand * left, operand * result, int offr)
8624 int size = AOP_SIZE (result);
8626 if (size >= LSB + offr)
8628 l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8630 emitcode ("add", "a,acc");
8631 if (sameRegs (AOP (left), AOP (result)) &&
8632 size >= MSB16 + offr && offr != LSB)
8633 emitcode ("xch", "a,%s",
8634 aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8636 aopPut (AOP (result), "a", LSB + offr);
8639 if (size >= MSB16 + offr)
8641 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8643 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8645 emitcode ("rlc", "a");
8646 if (sameRegs (AOP (left), AOP (result)) &&
8647 size >= MSB24 + offr && offr != LSB)
8648 emitcode ("xch", "a,%s",
8649 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8651 aopPut (AOP (result), "a", MSB16 + offr);
8654 if (size >= MSB24 + offr)
8656 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8658 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8660 emitcode ("rlc", "a");
8661 if (sameRegs (AOP (left), AOP (result)) &&
8662 size >= MSB32 + offr && offr != LSB)
8663 emitcode ("xch", "a,%s",
8664 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8666 aopPut (AOP (result), "a", MSB24 + offr);
8669 if (size > MSB32 + offr)
8671 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8673 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8675 emitcode ("rlc", "a");
8676 aopPut (AOP (result), "a", MSB32 + offr);
8679 aopPut (AOP (result), zero, LSB);
8685 /*-----------------------------------------------------------------*/
8686 /* genlshFour - shift four byte by a known amount != 0 */
8687 /*-----------------------------------------------------------------*/
8689 genlshFour (operand * result, operand * left, int shCount)
8693 D (emitcode (";", "genlshFour ");
8696 size = AOP_SIZE (result);
8698 /* if shifting more that 3 bytes */
8703 /* lowest order of left goes to the highest
8704 order of the destination */
8705 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8707 movLeft2Result (left, LSB, result, MSB32, 0);
8708 aopPut (AOP (result), zero, LSB);
8709 aopPut (AOP (result), zero, MSB16);
8710 aopPut (AOP (result), zero, MSB24);
8714 /* more than two bytes */
8715 else if (shCount >= 16)
8717 /* lower order two bytes goes to higher order two bytes */
8719 /* if some more remaining */
8721 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8724 movLeft2Result (left, MSB16, result, MSB32, 0);
8725 movLeft2Result (left, LSB, result, MSB24, 0);
8727 aopPut (AOP (result), zero, MSB16);
8728 aopPut (AOP (result), zero, LSB);
8732 /* if more than 1 byte */
8733 else if (shCount >= 8)
8735 /* lower order three bytes goes to higher order three bytes */
8740 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8742 movLeft2Result (left, LSB, result, MSB16, 0);
8748 movLeft2Result (left, MSB24, result, MSB32, 0);
8749 movLeft2Result (left, MSB16, result, MSB24, 0);
8750 movLeft2Result (left, LSB, result, MSB16, 0);
8751 aopPut (AOP (result), zero, LSB);
8753 else if (shCount == 1)
8754 shiftLLong (left, result, MSB16);
8757 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8758 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8759 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8760 aopPut (AOP (result), zero, LSB);
8765 /* 1 <= shCount <= 7 */
8766 else if (shCount <= 2)
8768 shiftLLong (left, result, LSB);
8770 shiftLLong (result, result, LSB);
8772 /* 3 <= shCount <= 7, optimize */
8775 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8776 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8777 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8782 #ifdef BETTER_LITERAL_SHIFT
8783 /*-----------------------------------------------------------------*/
8784 /* genLeftShiftLiteral - left shifting by known count */
8785 /*-----------------------------------------------------------------*/
8787 genLeftShiftLiteral (operand * left,
8792 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8795 size = getSize (operandType (result));
8797 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8799 /* We only handle certain easy cases so far. */
8801 && (shCount < (size * 8))
8805 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8809 freeAsmop (right, NULL, ic, TRUE);
8811 aopOp(left, ic, FALSE, FALSE);
8812 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8815 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8817 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8818 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8820 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8823 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8825 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8826 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8828 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8834 emitcode ("; shift left ", "result %d, left %d", size,
8838 /* I suppose that the left size >= result size */
8841 _startLazyDPSEvaluation();
8844 movLeft2Result (left, size, result, size, 0);
8846 _endLazyDPSEvaluation();
8848 else if (shCount >= (size * 8))
8850 _startLazyDPSEvaluation();
8853 aopPut (AOP (result), zero, size);
8855 _endLazyDPSEvaluation();
8862 genlshOne (result, left, shCount);
8866 genlshTwo (result, left, shCount);
8870 genlshFour (result, left, shCount);
8874 fprintf(stderr, "*** ack! mystery literal shift!\n");
8878 freeAsmop (left, NULL, ic, TRUE);
8879 freeAsmop (result, NULL, ic, TRUE);
8884 /*-----------------------------------------------------------------*/
8885 /* genLeftShift - generates code for left shifting */
8886 /*-----------------------------------------------------------------*/
8888 genLeftShift (iCode * ic)
8890 operand *left, *right, *result;
8893 symbol *tlbl, *tlbl1;
8895 D (emitcode (";", "genLeftShift "););
8897 right = IC_RIGHT (ic);
8898 left = IC_LEFT (ic);
8899 result = IC_RESULT (ic);
8901 aopOp (right, ic, FALSE, FALSE);
8904 #ifdef BETTER_LITERAL_SHIFT
8905 /* if the shift count is known then do it
8906 as efficiently as possible */
8907 if (AOP_TYPE (right) == AOP_LIT)
8909 if (genLeftShiftLiteral (left, right, result, ic))
8916 /* shift count is unknown then we have to form
8917 a loop get the loop count in B : Note: we take
8918 only the lower order byte since shifting
8919 more that 32 bits make no sense anyway, ( the
8920 largest size of an object can be only 32 bits ) */
8922 if (AOP_TYPE (right) == AOP_LIT)
8924 /* Really should be handled by genLeftShiftLiteral,
8925 * but since I'm too lazy to fix that today, at least we can make
8926 * some small improvement.
8928 emitcode("mov", "b,#!constbyte",
8929 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8933 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8934 emitcode ("inc", "b");
8936 freeAsmop (right, NULL, ic, TRUE);
8937 aopOp (left, ic, FALSE, FALSE);
8938 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8940 /* now move the left to the result if they are not the
8942 if (!sameRegs (AOP (left), AOP (result)) &&
8943 AOP_SIZE (result) > 1)
8946 size = AOP_SIZE (result);
8948 _startLazyDPSEvaluation ();
8951 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8952 if (*l == '@' && (IS_AOP_PREG (result)))
8955 emitcode ("mov", "a,%s", l);
8956 aopPut (AOP (result), "a", offset);
8959 aopPut (AOP (result), l, offset);
8962 _endLazyDPSEvaluation ();
8965 tlbl = newiTempLabel (NULL);
8966 size = AOP_SIZE (result);
8968 tlbl1 = newiTempLabel (NULL);
8970 /* if it is only one byte then */
8973 symbol *tlbl1 = newiTempLabel (NULL);
8975 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8976 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8977 emitcode ("", "!tlabeldef", tlbl->key + 100);
8978 emitcode ("add", "a,acc");
8979 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8980 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8981 aopPut (AOP (result), "a", 0);
8985 reAdjustPreg (AOP (result));
8987 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8988 emitcode ("", "!tlabeldef", tlbl->key + 100);
8989 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8990 emitcode ("add", "a,acc");
8991 aopPut (AOP (result), "a", offset++);
8992 _startLazyDPSEvaluation ();
8995 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8996 emitcode ("rlc", "a");
8997 aopPut (AOP (result), "a", offset++);
8999 _endLazyDPSEvaluation ();
9000 reAdjustPreg (AOP (result));
9002 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9003 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9005 freeAsmop (left, NULL, ic, TRUE);
9006 freeAsmop (result, NULL, ic, TRUE);
9009 #ifdef BETTER_LITERAL_SHIFT
9010 /*-----------------------------------------------------------------*/
9011 /* genrshOne - right shift a one byte quantity by known count */
9012 /*-----------------------------------------------------------------*/
9014 genrshOne (operand * result, operand * left,
9015 int shCount, int sign)
9017 D (emitcode (";", "genrshOne"););
9018 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9022 #ifdef BETTER_LITERAL_SHIFT
9023 /*-----------------------------------------------------------------*/
9024 /* genrshTwo - right shift two bytes by known amount != 0 */
9025 /*-----------------------------------------------------------------*/
9027 genrshTwo (operand * result, operand * left,
9028 int shCount, int sign)
9030 D (emitcode (";", "genrshTwo"););
9032 /* if shCount >= 8 */
9036 _startLazyDPSEvaluation();
9039 shiftR1Left2Result (left, MSB16, result, LSB,
9044 movLeft2Result (left, MSB16, result, LSB, sign);
9046 addSign (result, MSB16, sign);
9047 _endLazyDPSEvaluation();
9050 /* 1 <= shCount <= 7 */
9053 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9058 /*-----------------------------------------------------------------*/
9059 /* shiftRLong - shift right one long from left to result */
9060 /* offl = LSB or MSB16 */
9061 /*-----------------------------------------------------------------*/
9063 shiftRLong (operand * left, int offl,
9064 operand * result, int sign)
9066 int isSameRegs=sameRegs(AOP(left),AOP(result));
9068 if (isSameRegs && offl>1) {
9069 // we are in big trouble, but this shouldn't happen
9070 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9073 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
9078 emitcode ("rlc", "a");
9079 emitcode ("subb", "a,acc");
9080 emitcode ("xch", "a,%s",
9081 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
9083 aopPut (AOP(result), zero, MSB32);
9088 emitcode ("clr", "c");
9090 emitcode ("mov", "c,acc.7");
9093 emitcode ("rrc", "a");
9095 if (isSameRegs && offl==MSB16) {
9097 "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
9099 aopPut (AOP (result), "a", MSB32);
9100 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
9103 emitcode ("rrc", "a");
9104 if (isSameRegs && offl==1) {
9105 emitcode ("xch", "a,%s",
9106 aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
9108 aopPut (AOP (result), "a", MSB24);
9109 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
9111 emitcode ("rrc", "a");
9112 aopPut (AOP (result), "a", MSB16 - offl);
9116 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
9117 emitcode ("rrc", "a");
9118 aopPut (AOP (result), "a", LSB);
9122 /*-----------------------------------------------------------------*/
9123 /* genrshFour - shift four byte by a known amount != 0 */
9124 /*-----------------------------------------------------------------*/
9126 genrshFour (operand * result, operand * left,
9127 int shCount, int sign)
9129 D (emitcode (";", "genrshFour"););
9131 /* if shifting more that 3 bytes */
9135 _startLazyDPSEvaluation();
9137 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9139 movLeft2Result (left, MSB32, result, LSB, sign);
9140 addSign (result, MSB16, sign);
9141 _endLazyDPSEvaluation();
9143 else if (shCount >= 16)
9146 _startLazyDPSEvaluation();
9148 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9151 movLeft2Result (left, MSB24, result, LSB, 0);
9152 movLeft2Result (left, MSB32, result, MSB16, sign);
9154 addSign (result, MSB24, sign);
9155 _endLazyDPSEvaluation();
9157 else if (shCount >= 8)
9160 _startLazyDPSEvaluation();
9163 shiftRLong (left, MSB16, result, sign);
9165 else if (shCount == 0)
9167 movLeft2Result (left, MSB16, result, LSB, 0);
9168 movLeft2Result (left, MSB24, result, MSB16, 0);
9169 movLeft2Result (left, MSB32, result, MSB24, sign);
9170 addSign (result, MSB32, sign);
9174 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9175 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9176 /* the last shift is signed */
9177 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9178 addSign (result, MSB32, sign);
9180 _endLazyDPSEvaluation();
9184 /* 1 <= shCount <= 7 */
9187 shiftRLong (left, LSB, result, sign);
9189 shiftRLong (result, LSB, result, sign);
9193 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9194 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9195 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9200 #ifdef BETTER_LITERAL_SHIFT
9201 /*-----------------------------------------------------------------*/
9202 /* genRightShiftLiteral - right shifting by known count */
9203 /*-----------------------------------------------------------------*/
9205 genRightShiftLiteral (operand * left,
9211 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9214 size = getSize (operandType (result));
9216 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
9218 /* We only handle certain easy cases so far. */
9220 && (shCount < (size * 8))
9225 D(emitcode (";", "genRightShiftLiteral wimping out"););
9229 freeAsmop (right, NULL, ic, TRUE);
9231 aopOp (left, ic, FALSE, FALSE);
9232 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9235 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9239 /* test the LEFT size !!! */
9241 /* I suppose that the left size >= result size */
9244 size = getDataSize (result);
9245 _startLazyDPSEvaluation();
9248 movLeft2Result (left, size, result, size, 0);
9250 _endLazyDPSEvaluation();
9252 else if (shCount >= (size * 8))
9256 /* get sign in acc.7 */
9257 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
9259 addSign (result, LSB, sign);
9266 genrshOne (result, left, shCount, sign);
9270 genrshTwo (result, left, shCount, sign);
9274 genrshFour (result, left, shCount, sign);
9281 freeAsmop (left, NULL, ic, TRUE);
9282 freeAsmop (result, NULL, ic, TRUE);
9288 /*-----------------------------------------------------------------*/
9289 /* genSignedRightShift - right shift of signed number */
9290 /*-----------------------------------------------------------------*/
9292 genSignedRightShift (iCode * ic)
9294 operand *right, *left, *result;
9297 symbol *tlbl, *tlbl1;
9299 D (emitcode (";", "genSignedRightShift "););
9301 /* we do it the hard way put the shift count in b
9302 and loop thru preserving the sign */
9304 right = IC_RIGHT (ic);
9305 left = IC_LEFT (ic);
9306 result = IC_RESULT (ic);
9308 aopOp (right, ic, FALSE, FALSE);
9310 #ifdef BETTER_LITERAL_SHIFT
9311 if (AOP_TYPE (right) == AOP_LIT)
9313 if (genRightShiftLiteral (left, right, result, ic, 1))
9319 /* shift count is unknown then we have to form
9320 a loop get the loop count in B : Note: we take
9321 only the lower order byte since shifting
9322 more that 32 bits make no sense anyway, ( the
9323 largest size of an object can be only 32 bits ) */
9325 if (AOP_TYPE (right) == AOP_LIT)
9327 /* Really should be handled by genRightShiftLiteral,
9328 * but since I'm too lazy to fix that today, at least we can make
9329 * some small improvement.
9331 emitcode("mov", "b,#!constbyte",
9332 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9336 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9337 emitcode ("inc", "b");
9339 freeAsmop (right, NULL, ic, TRUE);
9340 aopOp (left, ic, FALSE, FALSE);
9341 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9343 /* now move the left to the result if they are not the
9345 if (!sameRegs (AOP (left), AOP (result)) &&
9346 AOP_SIZE (result) > 1)
9349 size = AOP_SIZE (result);
9351 _startLazyDPSEvaluation ();
9354 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9355 if (*l == '@' && IS_AOP_PREG (result))
9358 emitcode ("mov", "a,%s", l);
9359 aopPut (AOP (result), "a", offset);
9362 aopPut (AOP (result), l, offset);
9365 _endLazyDPSEvaluation ();
9368 /* mov the highest order bit to OVR */
9369 tlbl = newiTempLabel (NULL);
9370 tlbl1 = newiTempLabel (NULL);
9372 size = AOP_SIZE (result);
9374 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
9375 emitcode ("rlc", "a");
9376 emitcode ("mov", "ov,c");
9377 /* if it is only one byte then */
9380 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9381 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9382 emitcode ("", "!tlabeldef", tlbl->key + 100);
9383 emitcode ("mov", "c,ov");
9384 emitcode ("rrc", "a");
9385 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9386 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9387 aopPut (AOP (result), "a", 0);
9391 reAdjustPreg (AOP (result));
9392 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9393 emitcode ("", "!tlabeldef", tlbl->key + 100);
9394 emitcode ("mov", "c,ov");
9395 _startLazyDPSEvaluation ();
9398 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9399 emitcode ("rrc", "a");
9400 aopPut (AOP (result), "a", offset--);
9402 _endLazyDPSEvaluation ();
9403 reAdjustPreg (AOP (result));
9404 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9405 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9408 freeAsmop (left, NULL, ic, TRUE);
9409 freeAsmop (result, NULL, ic, TRUE);
9412 /*-----------------------------------------------------------------*/
9413 /* genRightShift - generate code for right shifting */
9414 /*-----------------------------------------------------------------*/
9416 genRightShift (iCode * ic)
9418 operand *right, *left, *result;
9422 symbol *tlbl, *tlbl1;
9424 D (emitcode (";", "genRightShift "););
9426 /* if signed then we do it the hard way preserve the
9427 sign bit moving it inwards */
9428 letype = getSpec (operandType (IC_LEFT (ic)));
9430 if (!SPEC_USIGN (letype))
9432 genSignedRightShift (ic);
9436 /* signed & unsigned types are treated the same : i.e. the
9437 signed is NOT propagated inwards : quoting from the
9438 ANSI - standard : "for E1 >> E2, is equivalent to division
9439 by 2**E2 if unsigned or if it has a non-negative value,
9440 otherwise the result is implementation defined ", MY definition
9441 is that the sign does not get propagated */
9443 right = IC_RIGHT (ic);
9444 left = IC_LEFT (ic);
9445 result = IC_RESULT (ic);
9447 aopOp (right, ic, FALSE, FALSE);
9449 #ifdef BETTER_LITERAL_SHIFT
9450 /* if the shift count is known then do it
9451 as efficiently as possible */
9452 if (AOP_TYPE (right) == AOP_LIT)
9454 if (genRightShiftLiteral (left, right, result, ic, 0))
9461 /* shift count is unknown then we have to form
9462 a loop get the loop count in B : Note: we take
9463 only the lower order byte since shifting
9464 more that 32 bits make no sense anyway, ( the
9465 largest size of an object can be only 32 bits ) */
9467 if (AOP_TYPE (right) == AOP_LIT)
9469 /* Really should be handled by genRightShiftLiteral,
9470 * but since I'm too lazy to fix that today, at least we can make
9471 * some small improvement.
9473 emitcode("mov", "b,#!constbyte",
9474 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9478 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9479 emitcode ("inc", "b");
9481 freeAsmop (right, NULL, ic, TRUE);
9482 aopOp (left, ic, FALSE, FALSE);
9483 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9485 /* now move the left to the result if they are not the
9487 if (!sameRegs (AOP (left), AOP (result)) &&
9488 AOP_SIZE (result) > 1)
9491 size = AOP_SIZE (result);
9493 _startLazyDPSEvaluation ();
9496 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9497 if (*l == '@' && IS_AOP_PREG (result))
9500 emitcode ("mov", "a,%s", l);
9501 aopPut (AOP (result), "a", offset);
9504 aopPut (AOP (result), l, offset);
9507 _endLazyDPSEvaluation ();
9510 tlbl = newiTempLabel (NULL);
9511 tlbl1 = newiTempLabel (NULL);
9512 size = AOP_SIZE (result);
9515 /* if it is only one byte then */
9518 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9519 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9520 emitcode ("", "!tlabeldef", tlbl->key + 100);
9522 emitcode ("rrc", "a");
9523 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9524 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9525 aopPut (AOP (result), "a", 0);
9529 reAdjustPreg (AOP (result));
9530 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9531 emitcode ("", "!tlabeldef", tlbl->key + 100);
9533 _startLazyDPSEvaluation ();
9536 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9537 emitcode ("rrc", "a");
9538 aopPut (AOP (result), "a", offset--);
9540 _endLazyDPSEvaluation ();
9541 reAdjustPreg (AOP (result));
9543 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9544 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9547 freeAsmop (left, NULL, ic, TRUE);
9548 freeAsmop (result, NULL, ic, TRUE);
9552 /*-----------------------------------------------------------------*/
9553 /* emitPtrByteGet - emits code to get a byte into A through a */
9554 /* pointer register (R0, R1, or DPTR). The */
9555 /* original value of A can be preserved in B. */
9556 /*-----------------------------------------------------------------*/
9558 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9565 emitcode ("mov", "b,a");
9566 emitcode ("mov", "a,@%s", rname);
9571 emitcode ("mov", "b,a");
9572 emitcode ("movx", "a,@%s", rname);
9577 emitcode ("mov", "b,a");
9578 emitcode ("movx", "a,@dptr");
9583 emitcode ("mov", "b,a");
9584 emitcode ("clr", "a");
9585 emitcode ("movc", "a,@a+dptr");
9591 emitcode ("push", "b");
9592 emitcode ("push", "acc");
9594 emitcode ("lcall", "__gptrget");
9596 emitcode ("pop", "b");
9601 /*-----------------------------------------------------------------*/
9602 /* emitPtrByteSet - emits code to set a byte from src through a */
9603 /* pointer register (R0, R1, or DPTR). */
9604 /*-----------------------------------------------------------------*/
9606 emitPtrByteSet (char *rname, int p_type, char *src)
9615 emitcode ("mov", "@%s,a", rname);
9618 emitcode ("mov", "@%s,%s", rname, src);
9623 emitcode ("movx", "@%s,a", rname);
9628 emitcode ("movx", "@dptr,a");
9633 emitcode ("lcall", "__gptrput");
9638 /*-----------------------------------------------------------------*/
9639 /* genUnpackBits - generates code for unpacking bits */
9640 /*-----------------------------------------------------------------*/
9642 genUnpackBits (operand * result, char *rname, int ptype)
9644 int offset = 0; /* result byte offset */
9645 int rsize; /* result size */
9646 int rlen = 0; /* remaining bitfield length */
9647 sym_link *etype; /* bitfield type information */
9648 int blen; /* bitfield length */
9649 int bstr; /* bitfield starting bit within byte */
9651 D(emitcode ("; genUnpackBits",""));
9653 etype = getSpec (operandType (result));
9654 rsize = getSize (operandType (result));
9655 blen = SPEC_BLEN (etype);
9656 bstr = SPEC_BSTR (etype);
9658 /* If the bitfield length is less than a byte */
9661 emitPtrByteGet (rname, ptype, FALSE);
9663 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9664 if (!SPEC_USIGN (etype))
9666 /* signed bitfield */
9667 symbol *tlbl = newiTempLabel (NULL);
9669 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9670 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9671 emitcode ("", "%05d$:", tlbl->key + 100);
9673 aopPut (AOP (result), "a", offset++);
9677 /* Bit field did not fit in a byte. Copy all
9678 but the partial byte at the end. */
9679 for (rlen=blen;rlen>=8;rlen-=8)
9681 emitPtrByteGet (rname, ptype, FALSE);
9682 aopPut (AOP (result), "a", offset++);
9684 emitcode ("inc", "%s", rname);
9687 /* Handle the partial byte at the end */
9690 emitPtrByteGet (rname, ptype, FALSE);
9691 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9692 if (!SPEC_USIGN (etype))
9694 /* signed bitfield */
9695 symbol *tlbl = newiTempLabel (NULL);
9697 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9698 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9699 emitcode ("", "%05d$:", tlbl->key + 100);
9701 aopPut (AOP (result), "a", offset++);
9709 if (SPEC_USIGN (etype))
9713 /* signed bitfield: sign extension with 0x00 or 0xff */
9714 emitcode ("rlc", "a");
9715 emitcode ("subb", "a,acc");
9721 aopPut (AOP (result), source, offset++);
9726 /*-----------------------------------------------------------------*/
9727 /* genDataPointerGet - generates code when ptr offset is known */
9728 /*-----------------------------------------------------------------*/
9730 genDataPointerGet (operand * left,
9736 int size, offset = 0;
9737 aopOp (result, ic, TRUE, FALSE);
9739 /* get the string representation of the name */
9740 l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9741 size = AOP_SIZE (result);
9742 _startLazyDPSEvaluation ();
9747 SNPRINTF (buff, sizeof(buff),
9748 "(%s + %d)", l + 1, offset);
9752 SNPRINTF (buff, sizeof(buff),
9755 aopPut (AOP (result), buff, offset++);
9757 _endLazyDPSEvaluation ();
9759 freeAsmop (left, NULL, ic, TRUE);
9760 freeAsmop (result, NULL, ic, TRUE);
9763 /*-----------------------------------------------------------------*/
9764 /* genNearPointerGet - emitcode for near pointer fetch */
9765 /*-----------------------------------------------------------------*/
9767 genNearPointerGet (operand * left,
9775 sym_link *rtype, *retype, *letype;
9776 sym_link *ltype = operandType (left);
9779 rtype = operandType (result);
9780 retype = getSpec (rtype);
9781 letype = getSpec (ltype);
9783 aopOp (left, ic, FALSE, FALSE);
9785 /* if left is rematerialisable and
9786 result is not bitfield variable type and
9787 the left is pointer to data space i.e
9788 lower 128 bytes of space */
9789 if (AOP_TYPE (left) == AOP_IMMD &&
9790 !IS_BITFIELD (retype) &&
9791 !IS_BITFIELD (letype) &&
9792 DCL_TYPE (ltype) == POINTER)
9794 genDataPointerGet (left, result, ic);
9798 /* if the value is already in a pointer register
9799 then don't need anything more */
9800 if (!AOP_INPREG (AOP (left)))
9802 /* otherwise get a free pointer register */
9804 preg = getFreePtr (ic, &aop, FALSE);
9805 emitcode ("mov", "%s,%s",
9807 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9811 rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9813 freeAsmop (left, NULL, ic, TRUE);
9814 aopOp (result, ic, FALSE, FALSE);
9816 /* if bitfield then unpack the bits */
9817 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9818 genUnpackBits (result, rname, POINTER);
9821 /* we have can just get the values */
9822 int size = AOP_SIZE (result);
9827 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9830 emitcode ("mov", "a,@%s", rname);
9831 aopPut (AOP (result), "a", offset);
9835 SNPRINTF (buff, sizeof(buff), "@%s", rname);
9836 aopPut (AOP (result), buff, offset);
9841 emitcode ("inc", "%s", rname);
9846 /* now some housekeeping stuff */
9849 /* we had to allocate for this iCode */
9850 if (pi) { /* post increment present */
9851 aopPut(AOP ( left ),rname,0);
9853 freeAsmop (NULL, aop, ic, TRUE);
9857 /* we did not allocate which means left
9858 already in a pointer register, then
9859 if size > 0 && this could be used again
9860 we have to point it back to where it
9862 if (AOP_SIZE (result) > 1 &&
9863 !OP_SYMBOL (left)->remat &&
9864 (OP_SYMBOL (left)->liveTo > ic->seq ||
9868 int size = AOP_SIZE (result) - 1;
9870 emitcode ("dec", "%s", rname);
9875 freeAsmop (result, NULL, ic, TRUE);
9876 if (pi) pi->generated = 1;
9879 /*-----------------------------------------------------------------*/
9880 /* genPagedPointerGet - emitcode for paged pointer fetch */
9881 /*-----------------------------------------------------------------*/
9883 genPagedPointerGet (operand * left,
9891 sym_link *rtype, *retype, *letype;
9893 rtype = operandType (result);
9894 retype = getSpec (rtype);
9895 letype = getSpec (operandType (left));
9896 aopOp (left, ic, FALSE, FALSE);
9898 /* if the value is already in a pointer register
9899 then don't need anything more */
9900 if (!AOP_INPREG (AOP (left)))
9902 /* otherwise get a free pointer register */
9904 preg = getFreePtr (ic, &aop, FALSE);
9905 emitcode ("mov", "%s,%s",
9907 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9911 rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9913 freeAsmop (left, NULL, ic, TRUE);
9914 aopOp (result, ic, FALSE, FALSE);
9916 /* if bitfield then unpack the bits */
9917 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9918 genUnpackBits (result, rname, PPOINTER);
9921 /* we have can just get the values */
9922 int size = AOP_SIZE (result);
9928 emitcode ("movx", "a,@%s", rname);
9929 aopPut (AOP (result), "a", offset);
9934 emitcode ("inc", "%s", rname);
9938 /* now some housekeeping stuff */
9941 /* we had to allocate for this iCode */
9942 if (pi) aopPut ( AOP (left), rname, 0);
9943 freeAsmop (NULL, aop, ic, TRUE);
9947 /* we did not allocate which means left
9948 already in a pointer register, then
9949 if size > 0 && this could be used again
9950 we have to point it back to where it
9952 if (AOP_SIZE (result) > 1 &&
9953 !OP_SYMBOL (left)->remat &&
9954 (OP_SYMBOL (left)->liveTo > ic->seq ||
9958 int size = AOP_SIZE (result) - 1;
9960 emitcode ("dec", "%s", rname);
9965 freeAsmop (result, NULL, ic, TRUE);
9966 if (pi) pi->generated = 1;
9969 /*-----------------------------------------------------------------*/
9970 /* genFarPointerGet - gget value from far space */
9971 /*-----------------------------------------------------------------*/
9973 genFarPointerGet (operand * left,
9974 operand * result, iCode * ic, iCode *pi)
9976 int size, offset, dopi=1;
9977 sym_link *retype = getSpec (operandType (result));
9978 sym_link *letype = getSpec (operandType (left));
9979 D (emitcode (";", "genFarPointerGet"););
9981 aopOp (left, ic, FALSE, FALSE);
9983 /* if the operand is already in dptr
9984 then we do nothing else we move the value to dptr */
9985 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9987 /* if this is remateriazable */
9988 if (AOP_TYPE (left) == AOP_IMMD)
9990 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9994 /* we need to get it byte by byte */
9995 _startLazyDPSEvaluation ();
9996 if (AOP_TYPE (left) != AOP_DPTR)
9998 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9999 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10000 if (options.model == MODEL_FLAT24)
10001 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10005 /* We need to generate a load to DPTR indirect through DPTR. */
10006 D (emitcode (";", "genFarPointerGet -- indirection special case."););
10007 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
10008 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
10009 if (options.model == MODEL_FLAT24)
10010 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10011 emitcode ("pop", "dph");
10012 emitcode ("pop", "dpl");
10015 _endLazyDPSEvaluation ();
10018 /* so dptr know contains the address */
10019 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10021 /* if bit then unpack */
10022 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10023 if (AOP_INDPTRn(left)) {
10024 genSetDPTR(AOP(left)->aopu.dptr);
10026 genUnpackBits (result, "dptr", FPOINTER);
10027 if (AOP_INDPTRn(left)) {
10032 size = AOP_SIZE (result);
10035 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10037 genSetDPTR(AOP(left)->aopu.dptr);
10038 emitcode ("movx", "a,@dptr");
10039 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10040 emitcode ("inc", "dptr");
10042 aopPut (AOP (result), "a", offset++);
10045 _startLazyDPSEvaluation ();
10047 if (AOP_INDPTRn(left)) {
10048 genSetDPTR(AOP(left)->aopu.dptr);
10054 emitcode ("movx", "a,@dptr");
10055 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10056 emitcode ("inc", "dptr");
10058 aopPut (AOP (result), "a", offset++);
10060 _endLazyDPSEvaluation ();
10063 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10064 if (!AOP_INDPTRn(left)) {
10065 _startLazyDPSEvaluation ();
10066 aopPut ( AOP (left), "dpl", 0);
10067 aopPut ( AOP (left), "dph", 1);
10068 if (options.model == MODEL_FLAT24)
10069 aopPut ( AOP (left), "dpx", 2);
10070 _endLazyDPSEvaluation ();
10073 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
10074 AOP_SIZE(result) > 1 &&
10076 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
10078 size = AOP_SIZE (result) - 1;
10079 if (AOP_INDPTRn(left)) {
10080 genSetDPTR(AOP(left)->aopu.dptr);
10082 while (size--) emitcode ("lcall","__decdptr");
10083 if (AOP_INDPTRn(left)) {
10088 freeAsmop (left, NULL, ic, TRUE);
10089 freeAsmop (result, NULL, ic, TRUE);
10092 /*-----------------------------------------------------------------*/
10093 /* genCodePointerGet - get value from code space */
10094 /*-----------------------------------------------------------------*/
10096 genCodePointerGet (operand * left,
10097 operand * result, iCode * ic, iCode *pi)
10099 int size, offset, dopi=1;
10100 sym_link *retype = getSpec (operandType (result));
10102 aopOp (left, ic, FALSE, FALSE);
10104 /* if the operand is already in dptr
10105 then we do nothing else we move the value to dptr */
10106 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
10108 /* if this is remateriazable */
10109 if (AOP_TYPE (left) == AOP_IMMD)
10111 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10114 { /* we need to get it byte by byte */
10115 _startLazyDPSEvaluation ();
10116 if (AOP_TYPE (left) != AOP_DPTR)
10118 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10119 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10120 if (options.model == MODEL_FLAT24)
10121 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10125 /* We need to generate a load to DPTR indirect through DPTR. */
10126 D (emitcode (";", "gencodePointerGet -- indirection special case."););
10127 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
10128 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
10129 if (options.model == MODEL_FLAT24)
10130 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10131 emitcode ("pop", "dph");
10132 emitcode ("pop", "dpl");
10135 _endLazyDPSEvaluation ();
10138 /* so dptr know contains the address */
10139 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10141 /* if bit then unpack */
10142 if (IS_BITFIELD (retype)) {
10143 if (AOP_INDPTRn(left)) {
10144 genSetDPTR(AOP(left)->aopu.dptr);
10146 genUnpackBits (result, "dptr", CPOINTER);
10147 if (AOP_INDPTRn(left)) {
10152 size = AOP_SIZE (result);
10154 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10156 genSetDPTR(AOP(left)->aopu.dptr);
10157 emitcode ("clr", "a");
10158 emitcode ("movc", "a,@a+dptr");
10159 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10160 emitcode ("inc", "dptr");
10162 aopPut (AOP (result), "a", offset++);
10165 _startLazyDPSEvaluation ();
10168 if (AOP_INDPTRn(left)) {
10169 genSetDPTR(AOP(left)->aopu.dptr);
10175 emitcode ("clr", "a");
10176 emitcode ("movc", "a,@a+dptr");
10177 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10178 emitcode ("inc", "dptr");
10179 aopPut (AOP (result), "a", offset++);
10181 _endLazyDPSEvaluation ();
10184 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10185 if (!AOP_INDPTRn(left)) {
10186 _startLazyDPSEvaluation ();
10188 aopPut ( AOP (left), "dpl", 0);
10189 aopPut ( AOP (left), "dph", 1);
10190 if (options.model == MODEL_FLAT24)
10191 aopPut ( AOP (left), "dpx", 2);
10193 _endLazyDPSEvaluation ();
10196 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
10197 AOP_SIZE(result) > 1 &&
10198 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10200 size = AOP_SIZE (result) - 1;
10201 if (AOP_INDPTRn(left)) {
10202 genSetDPTR(AOP(left)->aopu.dptr);
10204 while (size--) emitcode ("lcall","__decdptr");
10205 if (AOP_INDPTRn(left)) {
10210 freeAsmop (left, NULL, ic, TRUE);
10211 freeAsmop (result, NULL, ic, TRUE);
10214 /*-----------------------------------------------------------------*/
10215 /* genGenPointerGet - gget value from generic pointer space */
10216 /*-----------------------------------------------------------------*/
10218 genGenPointerGet (operand * left,
10219 operand * result, iCode * ic, iCode * pi)
10222 sym_link *retype = getSpec (operandType (result));
10223 sym_link *letype = getSpec (operandType (left));
10225 D (emitcode (";", "genGenPointerGet "); );
10227 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
10229 /* if the operand is already in dptr
10230 then we do nothing else we move the value to dptr */
10231 if (AOP_TYPE (left) != AOP_STR)
10233 /* if this is rematerializable */
10234 if (AOP_TYPE (left) == AOP_IMMD)
10236 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10237 if (AOP(left)->aopu.aop_immd.from_cast_remat)
10239 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
10243 emitcode ("mov", "b,#%d", pointerCode (retype));
10247 { /* we need to get it byte by byte */
10248 _startLazyDPSEvaluation ();
10249 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
10250 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
10251 if (options.model == MODEL_FLAT24) {
10252 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10253 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
10255 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10257 _endLazyDPSEvaluation ();
10261 /* so dptr-b now contains the address */
10263 aopOp (result, ic, FALSE, TRUE);
10266 /* if bit then unpack */
10267 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10269 genUnpackBits (result, "dptr", GPOINTER);
10273 size = AOP_SIZE (result);
10280 // Get two bytes at a time, results in _AP & A.
10281 // dptr will be incremented ONCE by __gptrgetWord.
10283 // Note: any change here must be coordinated
10284 // with the implementation of __gptrgetWord
10285 // in device/lib/_gptrget.c
10286 emitcode ("lcall", "__gptrgetWord");
10287 aopPut (AOP (result), DP2_RESULT_REG, offset++);
10288 aopPut (AOP (result), "a", offset++);
10293 // Only one byte to get.
10294 emitcode ("lcall", "__gptrget");
10295 aopPut (AOP (result), "a", offset++);
10298 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
10300 emitcode ("inc", "dptr");
10305 if (pi && AOP_TYPE (left) != AOP_IMMD) {
10306 _startLazyDPSEvaluation ();
10308 aopPut ( AOP (left), "dpl", 0);
10309 aopPut ( AOP (left), "dph", 1);
10310 if (options.model == MODEL_FLAT24) {
10311 aopPut ( AOP (left), "dpx", 2);
10312 aopPut ( AOP (left), "b", 3);
10313 } else aopPut ( AOP (left), "b", 2);
10315 _endLazyDPSEvaluation ();
10318 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
10319 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10321 size = AOP_SIZE (result) - 1;
10322 while (size--) emitcode ("lcall","__decdptr");
10325 freeAsmop (left, NULL, ic, TRUE);
10326 freeAsmop (result, NULL, ic, TRUE);
10329 /*-----------------------------------------------------------------*/
10330 /* genPointerGet - generate code for pointer get */
10331 /*-----------------------------------------------------------------*/
10333 genPointerGet (iCode * ic, iCode *pi)
10335 operand *left, *result;
10336 sym_link *type, *etype;
10339 D (emitcode (";", "genPointerGet ");
10342 left = IC_LEFT (ic);
10343 result = IC_RESULT (ic);
10345 /* depending on the type of pointer we need to
10346 move it to the correct pointer register */
10347 type = operandType (left);
10348 etype = getSpec (type);
10349 /* if left is of type of pointer then it is simple */
10350 if (IS_PTR (type) && !IS_FUNC (type->next))
10351 p_type = DCL_TYPE (type);
10354 /* we have to go by the storage class */
10355 p_type = PTR_TYPE (SPEC_OCLS (etype));
10357 /* special case when cast remat */
10358 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10359 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10361 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10362 type = operandType (left);
10363 p_type = DCL_TYPE (type);
10365 /* now that we have the pointer type we assign
10366 the pointer values */
10372 genNearPointerGet (left, result, ic, pi);
10376 genPagedPointerGet (left, result, ic, pi);
10380 genFarPointerGet (left, result, ic, pi);
10384 genCodePointerGet (left, result, ic, pi);
10388 genGenPointerGet (left, result, ic, pi);
10394 /*-----------------------------------------------------------------*/
10395 /* genPackBits - generates code for packed bit storage */
10396 /*-----------------------------------------------------------------*/
10398 genPackBits (sym_link * etype,
10400 char *rname, int p_type)
10402 int offset = 0; /* source byte offset */
10403 int rlen = 0; /* remaining bitfield length */
10404 int blen; /* bitfield length */
10405 int bstr; /* bitfield starting bit within byte */
10406 int litval; /* source literal value (if AOP_LIT) */
10407 unsigned char mask; /* bitmask within current byte */
10409 D(emitcode ("; genPackBits",""));
10411 blen = SPEC_BLEN (etype);
10412 bstr = SPEC_BSTR (etype);
10414 /* If the bitfield length is less than a byte */
10417 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10418 (unsigned char) (0xFF >> (8 - bstr)));
10420 if (AOP_TYPE (right) == AOP_LIT)
10422 /* Case with a bitfield length <8 and literal source
10424 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10426 litval &= (~mask) & 0xff;
10427 emitPtrByteGet (rname, p_type, FALSE);
10428 if ((mask|litval)!=0xff)
10429 emitcode ("anl","a,#!constbyte", mask);
10431 emitcode ("orl","a,#!constbyte", litval);
10435 if ((blen==1) && (p_type!=GPOINTER))
10437 /* Case with a bitfield length == 1 and no generic pointer
10439 if (AOP_TYPE (right) == AOP_CRY)
10440 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10443 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10444 emitcode ("rrc","a");
10446 emitPtrByteGet (rname, p_type, FALSE);
10447 emitcode ("mov","acc.%d,c",bstr);
10451 /* Case with a bitfield length < 8 and arbitrary source
10453 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10454 /* shift and mask source value */
10456 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10458 /* transfer A to B and get next byte */
10459 emitPtrByteGet (rname, p_type, TRUE);
10461 emitcode ("anl", "a,#!constbyte", mask);
10462 emitcode ("orl", "a,b");
10463 if (p_type == GPOINTER)
10464 emitcode ("pop", "b");
10468 emitPtrByteSet (rname, p_type, "a");
10472 /* Bit length is greater than 7 bits. In this case, copy */
10473 /* all except the partial byte at the end */
10474 for (rlen=blen;rlen>=8;rlen-=8)
10476 emitPtrByteSet (rname, p_type,
10477 aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
10479 emitcode ("inc", "%s", rname);
10482 /* If there was a partial byte at the end */
10485 mask = (((unsigned char) -1 << rlen) & 0xff);
10487 if (AOP_TYPE (right) == AOP_LIT)
10489 /* Case with partial byte and literal source
10491 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10492 litval >>= (blen-rlen);
10493 litval &= (~mask) & 0xff;
10494 emitPtrByteGet (rname, p_type, FALSE);
10495 if ((mask|litval)!=0xff)
10496 emitcode ("anl","a,#!constbyte", mask);
10498 emitcode ("orl","a,#!constbyte", litval);
10502 /* Case with partial byte and arbitrary source
10504 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10505 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10507 /* transfer A to B and get next byte */
10508 emitPtrByteGet (rname, p_type, TRUE);
10510 emitcode ("anl", "a,#!constbyte", mask);
10511 emitcode ("orl", "a,b");
10512 if (p_type == GPOINTER)
10513 emitcode ("pop", "b");
10515 emitPtrByteSet (rname, p_type, "a");
10521 /*-----------------------------------------------------------------*/
10522 /* genDataPointerSet - remat pointer to data space */
10523 /*-----------------------------------------------------------------*/
10525 genDataPointerSet (operand * right,
10529 int size, offset = 0;
10530 char *l, buff[256];
10532 aopOp (right, ic, FALSE, FALSE);
10534 l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
10535 size = AOP_SIZE (right);
10540 SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
10544 SNPRINTF (buff, sizeof(buff), "%s", l + 1);
10547 emitcode ("mov", "%s,%s", buff,
10548 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10551 freeAsmop (right, NULL, ic, TRUE);
10552 freeAsmop (result, NULL, ic, TRUE);
10555 /*-----------------------------------------------------------------*/
10556 /* genNearPointerSet - emitcode for near pointer put */
10557 /*-----------------------------------------------------------------*/
10559 genNearPointerSet (operand * right,
10566 sym_link *retype, *letype;
10567 sym_link *ptype = operandType (result);
10569 retype = getSpec (operandType (right));
10570 letype = getSpec (ptype);
10572 aopOp (result, ic, FALSE, FALSE);
10574 /* if the result is rematerializable &
10575 in data space & not a bit variable */
10576 if (AOP_TYPE (result) == AOP_IMMD &&
10577 DCL_TYPE (ptype) == POINTER &&
10578 !IS_BITVAR (retype) &&
10579 !IS_BITVAR (letype))
10581 genDataPointerSet (right, result, ic);
10585 /* if the value is already in a pointer register
10586 then don't need anything more */
10587 if (!AOP_INPREG (AOP (result)))
10589 /* otherwise get a free pointer register */
10592 aop = newAsmop (0);
10593 preg = getFreePtr (ic, &aop, FALSE);
10594 emitcode ("mov", "%s,%s",
10596 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10597 rname = preg->name;
10600 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10602 aopOp (right, ic, FALSE, FALSE);
10604 /* if bitfield then unpack the bits */
10605 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10606 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10609 /* we have can just get the values */
10610 int size = AOP_SIZE (right);
10615 l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10619 emitcode ("mov", "@%s,a", rname);
10622 emitcode ("mov", "@%s,%s", rname, l);
10624 emitcode ("inc", "%s", rname);
10629 /* now some housekeeping stuff */
10632 /* we had to allocate for this iCode */
10633 if (pi) aopPut (AOP (result),rname,0);
10634 freeAsmop (NULL, aop, ic, TRUE);
10638 /* we did not allocate which means left
10639 already in a pointer register, then
10640 if size > 0 && this could be used again
10641 we have to point it back to where it
10643 if (AOP_SIZE (right) > 1 &&
10644 !OP_SYMBOL (result)->remat &&
10645 (OP_SYMBOL (result)->liveTo > ic->seq ||
10649 int size = AOP_SIZE (right) - 1;
10651 emitcode ("dec", "%s", rname);
10656 if (pi) pi->generated = 1;
10657 freeAsmop (result, NULL, ic, TRUE);
10658 freeAsmop (right, NULL, ic, TRUE);
10663 /*-----------------------------------------------------------------*/
10664 /* genPagedPointerSet - emitcode for Paged pointer put */
10665 /*-----------------------------------------------------------------*/
10667 genPagedPointerSet (operand * right,
10674 sym_link *retype, *letype;
10676 retype = getSpec (operandType (right));
10677 letype = getSpec (operandType (result));
10679 aopOp (result, ic, FALSE, FALSE);
10681 /* if the value is already in a pointer register
10682 then don't need anything more */
10683 if (!AOP_INPREG (AOP (result)))
10685 /* otherwise get a free pointer register */
10688 aop = newAsmop (0);
10689 preg = getFreePtr (ic, &aop, FALSE);
10690 emitcode ("mov", "%s,%s",
10692 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10693 rname = preg->name;
10696 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10698 aopOp (right, ic, FALSE, FALSE);
10700 /* if bitfield then unpack the bits */
10701 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10702 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10705 /* we have can just get the values */
10706 int size = AOP_SIZE (right);
10711 MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10713 emitcode ("movx", "@%s,a", rname);
10716 emitcode ("inc", "%s", rname);
10722 /* now some housekeeping stuff */
10725 if (pi) aopPut (AOP (result),rname,0);
10726 /* we had to allocate for this iCode */
10727 freeAsmop (NULL, aop, ic, TRUE);
10731 /* we did not allocate which means left
10732 already in a pointer register, then
10733 if size > 0 && this could be used again
10734 we have to point it back to where it
10736 if (AOP_SIZE (right) > 1 &&
10737 !OP_SYMBOL (result)->remat &&
10738 (OP_SYMBOL (result)->liveTo > ic->seq ||
10742 int size = AOP_SIZE (right) - 1;
10744 emitcode ("dec", "%s", rname);
10749 if (pi) pi->generated = 1;
10750 freeAsmop (result, NULL, ic, TRUE);
10751 freeAsmop (right, NULL, ic, TRUE);
10756 /*-----------------------------------------------------------------*/
10757 /* genFarPointerSet - set value from far space */
10758 /*-----------------------------------------------------------------*/
10760 genFarPointerSet (operand * right,
10761 operand * result, iCode * ic, iCode *pi)
10763 int size, offset, dopi=1;
10764 sym_link *retype = getSpec (operandType (right));
10765 sym_link *letype = getSpec (operandType (result));
10767 aopOp (result, ic, FALSE, FALSE);
10769 /* if the operand is already in dptr
10770 then we do nothing else we move the value to dptr */
10771 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10773 /* if this is remateriazable */
10774 if (AOP_TYPE (result) == AOP_IMMD)
10775 emitcode ("mov", "dptr,%s",
10776 aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10779 /* we need to get it byte by byte */
10780 _startLazyDPSEvaluation ();
10781 if (AOP_TYPE (result) != AOP_DPTR)
10783 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10784 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10785 if (options.model == MODEL_FLAT24)
10786 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10790 /* We need to generate a load to DPTR indirect through DPTR. */
10791 D (emitcode (";", "genFarPointerSet -- indirection special case."););
10793 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10794 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10795 if (options.model == MODEL_FLAT24)
10796 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10797 emitcode ("pop", "dph");
10798 emitcode ("pop", "dpl");
10801 _endLazyDPSEvaluation ();
10804 /* so dptr know contains the address */
10805 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10807 /* if bit then unpack */
10808 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10809 if (AOP_INDPTRn(result)) {
10810 genSetDPTR(AOP(result)->aopu.dptr);
10812 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10813 if (AOP_INDPTRn(result)) {
10817 size = AOP_SIZE (right);
10819 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10821 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10823 genSetDPTR(AOP(result)->aopu.dptr);
10824 emitcode ("movx", "@dptr,a");
10825 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10826 emitcode ("inc", "dptr");
10830 _startLazyDPSEvaluation ();
10832 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10834 if (AOP_INDPTRn(result)) {
10835 genSetDPTR(AOP(result)->aopu.dptr);
10841 emitcode ("movx", "@dptr,a");
10842 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10843 emitcode ("inc", "dptr");
10845 _endLazyDPSEvaluation ();
10849 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10850 if (!AOP_INDPTRn(result)) {
10851 _startLazyDPSEvaluation ();
10853 aopPut (AOP(result),"dpl",0);
10854 aopPut (AOP(result),"dph",1);
10855 if (options.model == MODEL_FLAT24)
10856 aopPut (AOP(result),"dpx",2);
10858 _endLazyDPSEvaluation ();
10861 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10862 AOP_SIZE(right) > 1 &&
10863 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10865 size = AOP_SIZE (right) - 1;
10866 if (AOP_INDPTRn(result)) {
10867 genSetDPTR(AOP(result)->aopu.dptr);
10869 while (size--) emitcode ("lcall","__decdptr");
10870 if (AOP_INDPTRn(result)) {
10874 freeAsmop (result, NULL, ic, TRUE);
10875 freeAsmop (right, NULL, ic, TRUE);
10878 /*-----------------------------------------------------------------*/
10879 /* genGenPointerSet - set value from generic pointer space */
10880 /*-----------------------------------------------------------------*/
10882 genGenPointerSet (operand * right,
10883 operand * result, iCode * ic, iCode *pi)
10886 sym_link *retype = getSpec (operandType (right));
10887 sym_link *letype = getSpec (operandType (result));
10889 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10891 /* if the operand is already in dptr
10892 then we do nothing else we move the value to dptr */
10893 if (AOP_TYPE (result) != AOP_STR)
10895 _startLazyDPSEvaluation ();
10896 /* if this is remateriazable */
10897 if (AOP_TYPE (result) == AOP_IMMD)
10899 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10900 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10902 MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10907 "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10911 { /* we need to get it byte by byte */
10912 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10913 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10914 if (options.model == MODEL_FLAT24) {
10915 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10916 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10918 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10921 _endLazyDPSEvaluation ();
10923 /* so dptr + b now contains the address */
10925 aopOp (right, ic, FALSE, TRUE);
10929 /* if bit then unpack */
10930 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10932 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10936 size = AOP_SIZE (right);
10939 _startLazyDPSEvaluation ();
10944 // Set two bytes at a time, passed in _AP & A.
10945 // dptr will be incremented ONCE by __gptrputWord.
10947 // Note: any change here must be coordinated
10948 // with the implementation of __gptrputWord
10949 // in device/lib/_gptrput.c
10950 emitcode("mov", "_ap, %s",
10951 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10952 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10956 emitcode ("lcall", "__gptrputWord");
10961 // Only one byte to put.
10962 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10966 emitcode ("lcall", "__gptrput");
10969 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10971 emitcode ("inc", "dptr");
10974 _endLazyDPSEvaluation ();
10977 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10978 _startLazyDPSEvaluation ();
10980 aopPut (AOP(result),"dpl",0);
10981 aopPut (AOP(result),"dph",1);
10982 if (options.model == MODEL_FLAT24) {
10983 aopPut (AOP(result),"dpx",2);
10984 aopPut (AOP(result),"b",3);
10986 aopPut (AOP(result),"b",2);
10988 _endLazyDPSEvaluation ();
10991 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10992 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10994 size = AOP_SIZE (right) - 1;
10995 while (size--) emitcode ("lcall","__decdptr");
10997 freeAsmop (result, NULL, ic, TRUE);
10998 freeAsmop (right, NULL, ic, TRUE);
11001 /*-----------------------------------------------------------------*/
11002 /* genPointerSet - stores the value into a pointer location */
11003 /*-----------------------------------------------------------------*/
11005 genPointerSet (iCode * ic, iCode *pi)
11007 operand *right, *result;
11008 sym_link *type, *etype;
11011 D (emitcode (";", "genPointerSet "););
11013 right = IC_RIGHT (ic);
11014 result = IC_RESULT (ic);
11016 /* depending on the type of pointer we need to
11017 move it to the correct pointer register */
11018 type = operandType (result);
11019 etype = getSpec (type);
11020 /* if left is of type of pointer then it is simple */
11021 if (IS_PTR (type) && !IS_FUNC (type->next))
11023 p_type = DCL_TYPE (type);
11027 /* we have to go by the storage class */
11028 p_type = PTR_TYPE (SPEC_OCLS (etype));
11030 /* special case when cast remat */
11031 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
11032 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
11033 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
11034 type = operandType (result);
11035 p_type = DCL_TYPE (type);
11038 /* now that we have the pointer type we assign
11039 the pointer values */
11045 genNearPointerSet (right, result, ic, pi);
11049 genPagedPointerSet (right, result, ic, pi);
11053 genFarPointerSet (right, result, ic, pi);
11057 genGenPointerSet (right, result, ic, pi);
11061 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11062 "genPointerSet: illegal pointer type");
11067 /*-----------------------------------------------------------------*/
11068 /* genIfx - generate code for Ifx statement */
11069 /*-----------------------------------------------------------------*/
11071 genIfx (iCode * ic, iCode * popIc)
11073 operand *cond = IC_COND (ic);
11076 D (emitcode (";", "genIfx "););
11078 aopOp (cond, ic, FALSE, FALSE);
11080 /* get the value into acc */
11081 if (AOP_TYPE (cond) != AOP_CRY)
11090 /* the result is now in the accumulator */
11091 freeAsmop (cond, NULL, ic, TRUE);
11093 /* if there was something to be popped then do it */
11097 /* if the condition is a bit variable */
11098 if (isbit && IS_ITEMP (cond) &&
11101 genIfxJump (ic, SPIL_LOC (cond)->rname);
11103 else if (isbit && !IS_ITEMP (cond))
11105 genIfxJump (ic, OP_SYMBOL (cond)->rname);
11109 genIfxJump (ic, "a");
11115 /*-----------------------------------------------------------------*/
11116 /* genAddrOf - generates code for address of */
11117 /*-----------------------------------------------------------------*/
11119 genAddrOf (iCode * ic)
11121 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11124 D (emitcode (";", "genAddrOf ");
11127 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11129 /* if the operand is on the stack then we
11130 need to get the stack offset of this
11132 if (sym->onStack) {
11134 /* if 10 bit stack */
11135 if (options.stack10bit) {
11139 tsprintf(buff, sizeof(buff),
11140 "#!constbyte",(options.stack_loc >> 16) & 0xff);
11141 /* if it has an offset then we need to compute it */
11142 /* emitcode ("subb", "a,#!constbyte", */
11143 /* -((sym->stack < 0) ? */
11144 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11145 /* ((short) sym->stack)) & 0xff); */
11146 /* emitcode ("mov","b,a"); */
11147 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
11148 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11149 /* ((short) sym->stack)) >> 8) & 0xff); */
11151 emitcode ("mov", "a,_bpx");
11152 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
11153 ((char) (sym->stack - _G.nRegsSaved)) :
11154 ((char) sym->stack )) & 0xff);
11155 emitcode ("mov", "b,a");
11156 emitcode ("mov", "a,_bpx+1");
11158 offset = (((sym->stack < 0) ?
11159 ((short) (sym->stack - _G.nRegsSaved)) :
11160 ((short) sym->stack )) >> 8) & 0xff;
11162 emitcode ("addc","a,#!constbyte", offset);
11164 aopPut (AOP (IC_RESULT (ic)), "b", 0);
11165 aopPut (AOP (IC_RESULT (ic)), "a", 1);
11166 aopPut (AOP (IC_RESULT (ic)), buff, 2);
11168 /* we can just move _bp */
11169 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
11170 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
11171 aopPut (AOP (IC_RESULT (ic)), buff, 2);
11174 /* if it has an offset then we need to compute it */
11176 emitcode ("mov", "a,_bp");
11177 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
11178 aopPut (AOP (IC_RESULT (ic)), "a", 0);
11180 /* we can just move _bp */
11181 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
11183 /* fill the result with zero */
11184 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11187 if (options.stack10bit && size < (FPTRSIZE - 1)) {
11189 "*** warning: pointer to stack var truncated.\n");
11194 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
11200 /* object not on stack then we need the name */
11201 size = AOP_SIZE (IC_RESULT (ic));
11206 char s[SDCC_NAME_MAX];
11210 tsprintf(s, sizeof(s), "#!his",sym->rname);
11213 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
11216 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
11218 default: /* should not need this (just in case) */
11219 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
11226 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11229 aopPut (AOP (IC_RESULT (ic)), s, offset++);
11233 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11237 #if 0 // obsolete, and buggy for != xdata
11238 /*-----------------------------------------------------------------*/
11239 /* genArrayInit - generates code for address of */
11240 /*-----------------------------------------------------------------*/
11242 genArrayInit (iCode * ic)
11244 literalList *iLoop;
11246 int elementSize = 0, eIndex;
11247 unsigned val, lastVal;
11249 operand *left=IC_LEFT(ic);
11251 D (emitcode (";", "genArrayInit "););
11253 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
11255 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
11257 // Load immediate value into DPTR.
11258 emitcode("mov", "dptr, %s",
11259 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
11261 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
11264 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11265 "Unexpected operand to genArrayInit.\n");
11268 // a regression because of SDCCcse.c:1.52
11269 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
11270 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
11271 if (options.model == MODEL_FLAT24)
11272 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
11276 type = operandType(IC_LEFT(ic));
11278 if (type && type->next)
11280 elementSize = getSize(type->next);
11284 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11285 "can't determine element size in genArrayInit.\n");
11289 iLoop = IC_ARRAYILIST(ic);
11294 bool firstpass = TRUE;
11296 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
11297 iLoop->count, (int)iLoop->literalValue, elementSize);
11303 symbol *tlbl = NULL;
11305 count = ix > 256 ? 256 : ix;
11309 tlbl = newiTempLabel (NULL);
11310 if (firstpass || (count & 0xff))
11312 emitcode("mov", "b, #!constbyte", count & 0xff);
11315 emitcode ("", "!tlabeldef", tlbl->key + 100);
11320 for (eIndex = 0; eIndex < elementSize; eIndex++)
11322 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
11323 if (val != lastVal)
11325 emitcode("mov", "a, #!constbyte", val);
11329 emitcode("movx", "@dptr, a");
11330 emitcode("inc", "dptr");
11335 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
11341 iLoop = iLoop->next;
11344 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
11348 /*-----------------------------------------------------------------*/
11349 /* genFarFarAssign - assignment when both are in far space */
11350 /*-----------------------------------------------------------------*/
11352 genFarFarAssign (operand * result, operand * right, iCode * ic)
11354 int size = AOP_SIZE (right);
11356 symbol *rSym = NULL;
11360 /* quick & easy case. */
11361 D(emitcode(";","genFarFarAssign (1 byte case)"););
11362 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
11363 freeAsmop (right, NULL, ic, FALSE);
11364 /* now assign DPTR to result */
11366 aopOp(result, ic, FALSE, FALSE);
11368 aopPut(AOP(result), "a", 0);
11369 freeAsmop(result, NULL, ic, FALSE);
11373 /* See if we've got an underlying symbol to abuse. */
11374 if (IS_SYMOP(result) && OP_SYMBOL(result))
11376 if (IS_TRUE_SYMOP(result))
11378 rSym = OP_SYMBOL(result);
11380 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
11382 rSym = OP_SYMBOL(result)->usl.spillLoc;
11386 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
11388 /* We can use the '390 auto-toggle feature to good effect here. */
11390 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
11391 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11392 emitcode ("mov", "dptr,#%s", rSym->rname);
11393 /* DP2 = result, DP1 = right, DP1 is current. */
11396 emitcode("movx", "a,@dptr");
11397 emitcode("movx", "@dptr,a");
11400 emitcode("inc", "dptr");
11401 emitcode("inc", "dptr");
11404 emitcode("mov", "dps,#0");
11405 freeAsmop (right, NULL, ic, FALSE);
11407 some alternative code for processors without auto-toggle
11408 no time to test now, so later well put in...kpb
11409 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
11410 emitcode("mov", "dps,#1"); /* Select DPTR2. */
11411 emitcode ("mov", "dptr,#%s", rSym->rname);
11412 /* DP2 = result, DP1 = right, DP1 is current. */
11416 emitcode("movx", "a,@dptr");
11418 emitcode("inc", "dptr");
11419 emitcode("inc", "dps");
11420 emitcode("movx", "@dptr,a");
11422 emitcode("inc", "dptr");
11423 emitcode("inc", "dps");
11425 emitcode("mov", "dps,#0");
11426 freeAsmop (right, NULL, ic, FALSE);
11431 D (emitcode (";", "genFarFarAssign"););
11432 aopOp (result, ic, TRUE, TRUE);
11434 _startLazyDPSEvaluation ();
11438 aopPut (AOP (result),
11439 aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
11442 _endLazyDPSEvaluation ();
11443 freeAsmop (result, NULL, ic, FALSE);
11444 freeAsmop (right, NULL, ic, FALSE);
11448 /*-----------------------------------------------------------------*/
11449 /* genAssign - generate code for assignment */
11450 /*-----------------------------------------------------------------*/
11452 genAssign (iCode * ic)
11454 operand *result, *right;
11456 unsigned long lit = 0L;
11458 D (emitcode (";", "genAssign ");
11461 result = IC_RESULT (ic);
11462 right = IC_RIGHT (ic);
11464 /* if they are the same */
11465 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11468 aopOp (right, ic, FALSE, FALSE);
11470 emitcode (";", "genAssign: resultIsFar = %s",
11471 isOperandInFarSpace (result) ?
11474 /* special case both in far space */
11475 if ((AOP_TYPE (right) == AOP_DPTR ||
11476 AOP_TYPE (right) == AOP_DPTR2) &&
11477 /* IS_TRUE_SYMOP(result) && */
11478 isOperandInFarSpace (result))
11480 genFarFarAssign (result, right, ic);
11484 aopOp (result, ic, TRUE, FALSE);
11486 /* if they are the same registers */
11487 if (sameRegs (AOP (right), AOP (result)))
11490 /* if the result is a bit */
11491 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
11493 /* if the right size is a literal then
11494 we know what the value is */
11495 if (AOP_TYPE (right) == AOP_LIT)
11497 if (((int) operandLitValue (right)))
11498 aopPut (AOP (result), one, 0);
11500 aopPut (AOP (result), zero, 0);
11504 /* the right is also a bit variable */
11505 if (AOP_TYPE (right) == AOP_CRY)
11507 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11508 aopPut (AOP (result), "c", 0);
11512 /* we need to or */
11514 aopPut (AOP (result), "a", 0);
11518 /* bit variables done */
11520 size = AOP_SIZE (result);
11522 if (AOP_TYPE (right) == AOP_LIT)
11523 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11526 (AOP_TYPE (result) != AOP_REG) &&
11527 (AOP_TYPE (right) == AOP_LIT) &&
11528 !IS_FLOAT (operandType (right)))
11530 _startLazyDPSEvaluation ();
11531 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
11533 aopPut (AOP (result),
11534 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11539 /* And now fill the rest with zeros. */
11542 emitcode ("clr", "a");
11546 aopPut (AOP (result), "a", offset++);
11548 _endLazyDPSEvaluation ();
11552 _startLazyDPSEvaluation ();
11555 aopPut (AOP (result),
11556 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11560 _endLazyDPSEvaluation ();
11564 freeAsmop (right, NULL, ic, FALSE);
11565 freeAsmop (result, NULL, ic, TRUE);
11568 /*-----------------------------------------------------------------*/
11569 /* genJumpTab - generates code for jump table */
11570 /*-----------------------------------------------------------------*/
11572 genJumpTab (iCode * ic)
11577 D (emitcode (";", "genJumpTab ");
11580 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11581 /* get the condition into accumulator */
11582 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11584 /* multiply by four! */
11585 emitcode ("add", "a,acc");
11586 emitcode ("add", "a,acc");
11587 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11589 jtab = newiTempLabel (NULL);
11590 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11591 emitcode ("jmp", "@a+dptr");
11592 emitcode ("", "!tlabeldef", jtab->key + 100);
11593 /* now generate the jump labels */
11594 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11595 jtab = setNextItem (IC_JTLABELS (ic)))
11596 emitcode ("ljmp", "!tlabel", jtab->key + 100);
11600 /*-----------------------------------------------------------------*/
11601 /* genCast - gen code for casting */
11602 /*-----------------------------------------------------------------*/
11604 genCast (iCode * ic)
11606 operand *result = IC_RESULT (ic);
11607 sym_link *ctype = operandType (IC_LEFT (ic));
11608 sym_link *rtype = operandType (IC_RIGHT (ic));
11609 operand *right = IC_RIGHT (ic);
11612 D (emitcode (";", "genCast "););
11614 /* if they are equivalent then do nothing */
11615 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11618 aopOp (right, ic, FALSE, AOP_IS_STR (result));
11619 aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
11621 /* if the result is a bit */
11622 if (IS_BITVAR (OP_SYMBOL (result)->type)
11623 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11625 /* if the right size is a literal then
11626 we know what the value is */
11627 if (AOP_TYPE (right) == AOP_LIT)
11629 if (((int) operandLitValue (right)))
11630 aopPut (AOP (result), one, 0);
11632 aopPut (AOP (result), zero, 0);
11637 /* the right is also a bit variable */
11638 if (AOP_TYPE (right) == AOP_CRY)
11640 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11641 aopPut (AOP (result), "c", 0);
11645 /* we need to or */
11647 aopPut (AOP (result), "a", 0);
11651 /* if they are the same size : or less */
11652 if (AOP_SIZE (result) <= AOP_SIZE (right))
11655 /* if they are in the same place */
11656 if (sameRegs (AOP (right), AOP (result)))
11659 /* if they in different places then copy */
11660 size = AOP_SIZE (result);
11662 _startLazyDPSEvaluation ();
11665 aopPut (AOP (result),
11666 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11670 _endLazyDPSEvaluation ();
11675 /* if the result is of type pointer */
11676 if (IS_PTR (ctype))
11680 sym_link *type = operandType (right);
11682 /* pointer to generic pointer */
11683 if (IS_GENPTR (ctype))
11687 p_type = DCL_TYPE (type);
11691 #if OLD_CAST_BEHAVIOR
11692 /* KV: we are converting a non-pointer type to
11693 * a generic pointer. This (ifdef'd out) code
11694 * says that the resulting generic pointer
11695 * should have the same class as the storage
11696 * location of the non-pointer variable.
11698 * For example, converting an int (which happens
11699 * to be stored in DATA space) to a pointer results
11700 * in a DATA generic pointer; if the original int
11701 * in XDATA space, so will be the resulting pointer.
11703 * I don't like that behavior, and thus this change:
11704 * all such conversions will be forced to XDATA and
11705 * throw a warning. If you want some non-XDATA
11706 * type, or you want to suppress the warning, you
11707 * must go through an intermediate cast, like so:
11709 * char _generic *gp = (char _xdata *)(intVar);
11711 sym_link *etype = getSpec (type);
11713 /* we have to go by the storage class */
11714 if (SPEC_OCLS (etype) != generic)
11716 p_type = PTR_TYPE (SPEC_OCLS (etype));
11721 /* Converting unknown class (i.e. register variable)
11722 * to generic pointer. This is not good, but
11723 * we'll make a guess (and throw a warning).
11726 werror (W_INT_TO_GEN_PTR_CAST);
11730 /* the first two bytes are known */
11731 size = GPTRSIZE - 1;
11733 _startLazyDPSEvaluation ();
11736 aopPut (AOP (result),
11737 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11741 _endLazyDPSEvaluation ();
11743 /* the last byte depending on type */
11745 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11750 // pointerTypeToGPByte will have bitched.
11754 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%x", gpVal);
11755 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11760 /* just copy the pointers */
11761 size = AOP_SIZE (result);
11763 _startLazyDPSEvaluation ();
11766 aopPut (AOP (result),
11767 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11771 _endLazyDPSEvaluation ();
11775 /* so we now know that the size of destination is greater
11776 than the size of the source */
11777 /* we move to result for the size of source */
11778 size = AOP_SIZE (right);
11780 _startLazyDPSEvaluation ();
11783 aopPut (AOP (result),
11784 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11788 _endLazyDPSEvaluation ();
11790 /* now depending on the sign of the source && destination */
11791 size = AOP_SIZE (result) - AOP_SIZE (right);
11792 /* if unsigned or not an integral type */
11793 /* also, if the source is a bit, we don't need to sign extend, because
11794 * it can't possibly have set the sign bit.
11796 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11800 aopPut (AOP (result), zero, offset++);
11805 /* we need to extend the sign :{ */
11806 MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11807 FALSE, FALSE, NULL));
11808 emitcode ("rlc", "a");
11809 emitcode ("subb", "a,acc");
11811 aopPut (AOP (result), "a", offset++);
11814 /* we are done hurray !!!! */
11817 freeAsmop (right, NULL, ic, TRUE);
11818 freeAsmop (result, NULL, ic, TRUE);
11822 /*-----------------------------------------------------------------*/
11823 /* genDjnz - generate decrement & jump if not zero instrucion */
11824 /*-----------------------------------------------------------------*/
11826 genDjnz (iCode * ic, iCode * ifx)
11828 symbol *lbl, *lbl1;
11832 /* if the if condition has a false label
11833 then we cannot save */
11834 if (IC_FALSE (ifx))
11837 /* if the minus is not of the form
11839 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11840 !IS_OP_LITERAL (IC_RIGHT (ic)))
11843 if (operandLitValue (IC_RIGHT (ic)) != 1)
11846 /* if the size of this greater than one then no
11848 if (getSize (operandType (IC_RESULT (ic))) > 1)
11851 /* otherwise we can save BIG */
11852 D(emitcode(";", "genDjnz"););
11854 lbl = newiTempLabel (NULL);
11855 lbl1 = newiTempLabel (NULL);
11857 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11859 if (AOP_NEEDSACC(IC_RESULT(ic)))
11861 /* If the result is accessed indirectly via
11862 * the accumulator, we must explicitly write
11863 * it back after the decrement.
11865 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11867 if (strcmp(rByte, "a"))
11869 /* Something is hopelessly wrong */
11870 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11871 __FILE__, __LINE__);
11872 /* We can just give up; the generated code will be inefficient,
11873 * but what the hey.
11875 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11878 emitcode ("dec", "%s", rByte);
11879 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11880 emitcode ("jnz", "!tlabel", lbl->key + 100);
11882 else if (IS_AOP_PREG (IC_RESULT (ic)))
11884 emitcode ("dec", "%s",
11885 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11886 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11887 emitcode ("jnz", "!tlabel", lbl->key + 100);
11891 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11894 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11895 emitcode ("", "!tlabeldef", lbl->key + 100);
11896 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11897 emitcode ("", "!tlabeldef", lbl1->key + 100);
11899 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11900 ifx->generated = 1;
11904 /*-----------------------------------------------------------------*/
11905 /* genReceive - generate code for a receive iCode */
11906 /*-----------------------------------------------------------------*/
11908 genReceive (iCode * ic)
11910 int size = getSize (operandType (IC_RESULT (ic)));
11914 D (emitcode (";", "genReceive "););
11916 if (ic->argreg == 1)
11918 /* first parameter */
11919 if (AOP_IS_STR(IC_RESULT(ic)))
11921 /* Nothing to do: it's already in the proper place. */
11928 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11929 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11930 IS_TRUE_SYMOP (IC_RESULT (ic)));
11933 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11936 /* Sanity checking... */
11937 if (AOP_USESDPTR(IC_RESULT(ic)))
11939 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11940 "genReceive got unexpected DPTR.");
11942 assignResultValue (IC_RESULT (ic));
11947 /* second receive onwards */
11948 /* this gets a little tricky since unused recevies will be
11949 eliminated, we have saved the reg in the type field . and
11950 we use that to figure out which register to use */
11951 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11952 rb1off = ic->argreg;
11955 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11958 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11961 /*-----------------------------------------------------------------*/
11962 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11963 /*-----------------------------------------------------------------*/
11964 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11966 operand *from , *to , *count;
11971 /* we know it has to be 3 parameters */
11972 assert (nparms == 3);
11974 rsave = newBitVect(16);
11975 /* save DPTR if it needs to be saved */
11976 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11977 if (bitVectBitValue(ic->rMask,i))
11978 rsave = bitVectSetBit(rsave,i);
11980 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11981 ds390_rUmaskForOp (IC_RESULT(ic))));
11988 aopOp (from, ic->next, FALSE, FALSE);
11990 /* get from into DPTR1 */
11991 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11992 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11993 if (options.model == MODEL_FLAT24) {
11994 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11997 freeAsmop (from, NULL, ic, FALSE);
11998 aopOp (to, ic, FALSE, FALSE);
11999 /* get "to" into DPTR */
12000 /* if the operand is already in dptr
12001 then we do nothing else we move the value to dptr */
12002 if (AOP_TYPE (to) != AOP_STR) {
12003 /* if already in DPTR then we need to push */
12004 if (AOP_TYPE(to) == AOP_DPTR) {
12005 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12006 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12007 if (options.model == MODEL_FLAT24)
12008 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12009 emitcode ("pop", "dph");
12010 emitcode ("pop", "dpl");
12012 _startLazyDPSEvaluation ();
12013 /* if this is remateriazable */
12014 if (AOP_TYPE (to) == AOP_IMMD) {
12015 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12016 } else { /* we need to get it byte by byte */
12017 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12018 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12019 if (options.model == MODEL_FLAT24) {
12020 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12023 _endLazyDPSEvaluation ();
12026 freeAsmop (to, NULL, ic, FALSE);
12027 _G.dptrInUse = _G.dptr1InUse = 1;
12028 aopOp (count, ic->next->next, FALSE,FALSE);
12029 lbl =newiTempLabel(NULL);
12031 /* now for the actual copy */
12032 if (AOP_TYPE(count) == AOP_LIT &&
12033 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12034 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12036 emitcode ("lcall","__bi_memcpyc2x_s");
12038 emitcode ("lcall","__bi_memcpyx2x_s");
12040 freeAsmop (count, NULL, ic, FALSE);
12042 symbol *lbl1 = newiTempLabel(NULL);
12044 emitcode (";"," Auto increment but no djnz");
12045 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12046 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12047 freeAsmop (count, NULL, ic, FALSE);
12048 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12049 emitcode ("","!tlabeldef",lbl->key+100);
12051 emitcode ("clr","a");
12052 emitcode ("movc", "a,@a+dptr");
12054 emitcode ("movx", "a,@dptr");
12055 emitcode ("movx", "@dptr,a");
12056 emitcode ("inc", "dptr");
12057 emitcode ("inc", "dptr");
12058 emitcode ("mov","a,b");
12059 emitcode ("orl","a,_ap");
12060 emitcode ("jz","!tlabel",lbl1->key+100);
12061 emitcode ("mov","a,_ap");
12062 emitcode ("add","a,#!constbyte",0xFF);
12063 emitcode ("mov","_ap,a");
12064 emitcode ("mov","a,b");
12065 emitcode ("addc","a,#!constbyte",0xFF);
12066 emitcode ("mov","b,a");
12067 emitcode ("sjmp","!tlabel",lbl->key+100);
12068 emitcode ("","!tlabeldef",lbl1->key+100);
12070 emitcode ("mov", "dps,#0");
12071 _G.dptrInUse = _G.dptr1InUse = 0;
12072 unsavermask(rsave);
12076 /*-----------------------------------------------------------------*/
12077 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
12078 /*-----------------------------------------------------------------*/
12079 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
12081 operand *from , *to , *count;
12086 /* we know it has to be 3 parameters */
12087 assert (nparms == 3);
12089 rsave = newBitVect(16);
12090 /* save DPTR if it needs to be saved */
12091 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12092 if (bitVectBitValue(ic->rMask,i))
12093 rsave = bitVectSetBit(rsave,i);
12095 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12096 ds390_rUmaskForOp (IC_RESULT(ic))));
12103 aopOp (from, ic->next, FALSE, FALSE);
12105 /* get from into DPTR1 */
12106 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12107 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12108 if (options.model == MODEL_FLAT24) {
12109 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12112 freeAsmop (from, NULL, ic, FALSE);
12113 aopOp (to, ic, FALSE, FALSE);
12114 /* get "to" into DPTR */
12115 /* if the operand is already in dptr
12116 then we do nothing else we move the value to dptr */
12117 if (AOP_TYPE (to) != AOP_STR) {
12118 /* if already in DPTR then we need to push */
12119 if (AOP_TYPE(to) == AOP_DPTR) {
12120 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12121 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12122 if (options.model == MODEL_FLAT24)
12123 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12124 emitcode ("pop", "dph");
12125 emitcode ("pop", "dpl");
12127 _startLazyDPSEvaluation ();
12128 /* if this is remateriazable */
12129 if (AOP_TYPE (to) == AOP_IMMD) {
12130 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12131 } else { /* we need to get it byte by byte */
12132 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12133 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12134 if (options.model == MODEL_FLAT24) {
12135 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12138 _endLazyDPSEvaluation ();
12141 freeAsmop (to, NULL, ic, FALSE);
12142 _G.dptrInUse = _G.dptr1InUse = 1;
12143 aopOp (count, ic->next->next, FALSE,FALSE);
12144 lbl =newiTempLabel(NULL);
12145 lbl2 =newiTempLabel(NULL);
12147 /* now for the actual compare */
12148 if (AOP_TYPE(count) == AOP_LIT &&
12149 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12150 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12152 emitcode("lcall","__bi_memcmpc2x_s");
12154 emitcode("lcall","__bi_memcmpx2x_s");
12155 freeAsmop (count, NULL, ic, FALSE);
12156 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12157 aopPut(AOP(IC_RESULT(ic)),"a",0);
12158 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12160 symbol *lbl1 = newiTempLabel(NULL);
12162 emitcode("push","ar0");
12163 emitcode (";"," Auto increment but no djnz");
12164 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12165 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12166 freeAsmop (count, NULL, ic, FALSE);
12167 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12168 emitcode ("","!tlabeldef",lbl->key+100);
12170 emitcode ("clr","a");
12171 emitcode ("movc", "a,@a+dptr");
12173 emitcode ("movx", "a,@dptr");
12174 emitcode ("mov","r0,a");
12175 emitcode ("movx", "a,@dptr");
12176 emitcode ("clr","c");
12177 emitcode ("subb","a,r0");
12178 emitcode ("jnz","!tlabel",lbl2->key+100);
12179 emitcode ("inc", "dptr");
12180 emitcode ("inc", "dptr");
12181 emitcode ("mov","a,b");
12182 emitcode ("orl","a,_ap");
12183 emitcode ("jz","!tlabel",lbl1->key+100);
12184 emitcode ("mov","a,_ap");
12185 emitcode ("add","a,#!constbyte",0xFF);
12186 emitcode ("mov","_ap,a");
12187 emitcode ("mov","a,b");
12188 emitcode ("addc","a,#!constbyte",0xFF);
12189 emitcode ("mov","b,a");
12190 emitcode ("sjmp","!tlabel",lbl->key+100);
12191 emitcode ("","!tlabeldef",lbl1->key+100);
12192 emitcode ("clr","a");
12193 emitcode ("","!tlabeldef",lbl2->key+100);
12194 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12195 aopPut(AOP(IC_RESULT(ic)),"a",0);
12196 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12197 emitcode("pop","ar0");
12198 emitcode ("mov", "dps,#0");
12200 _G.dptrInUse = _G.dptr1InUse = 0;
12201 unsavermask(rsave);
12205 /*-----------------------------------------------------------------*/
12206 /* genInp - gen code for __builtin_inp read data from a mem mapped */
12207 /* port, first parameter output area second parameter pointer to */
12208 /* port third parameter count */
12209 /*-----------------------------------------------------------------*/
12210 static void genInp( iCode *ic, int nparms, operand **parms)
12212 operand *from , *to , *count;
12217 /* we know it has to be 3 parameters */
12218 assert (nparms == 3);
12220 rsave = newBitVect(16);
12221 /* save DPTR if it needs to be saved */
12222 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12223 if (bitVectBitValue(ic->rMask,i))
12224 rsave = bitVectSetBit(rsave,i);
12226 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12227 ds390_rUmaskForOp (IC_RESULT(ic))));
12234 aopOp (from, ic->next, FALSE, FALSE);
12236 /* get from into DPTR1 */
12237 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12238 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12239 if (options.model == MODEL_FLAT24) {
12240 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12243 freeAsmop (from, NULL, ic, FALSE);
12244 aopOp (to, ic, FALSE, FALSE);
12245 /* get "to" into DPTR */
12246 /* if the operand is already in dptr
12247 then we do nothing else we move the value to dptr */
12248 if (AOP_TYPE (to) != AOP_STR) {
12249 /* if already in DPTR then we need to push */
12250 if (AOP_TYPE(to) == AOP_DPTR) {
12251 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12252 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12253 if (options.model == MODEL_FLAT24)
12254 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12255 emitcode ("pop", "dph");
12256 emitcode ("pop", "dpl");
12258 _startLazyDPSEvaluation ();
12259 /* if this is remateriazable */
12260 if (AOP_TYPE (to) == AOP_IMMD) {
12261 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12262 } else { /* we need to get it byte by byte */
12263 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12264 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12265 if (options.model == MODEL_FLAT24) {
12266 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12269 _endLazyDPSEvaluation ();
12272 freeAsmop (to, NULL, ic, FALSE);
12274 _G.dptrInUse = _G.dptr1InUse = 1;
12275 aopOp (count, ic->next->next, FALSE,FALSE);
12276 lbl =newiTempLabel(NULL);
12278 /* now for the actual copy */
12279 if (AOP_TYPE(count) == AOP_LIT &&
12280 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12281 emitcode (";","OH JOY auto increment with djnz (very fast)");
12282 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12283 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12284 freeAsmop (count, NULL, ic, FALSE);
12285 emitcode ("","!tlabeldef",lbl->key+100);
12286 emitcode ("movx", "a,@dptr"); /* read data from port */
12287 emitcode ("dec","dps"); /* switch to DPTR */
12288 emitcode ("movx", "@dptr,a"); /* save into location */
12289 emitcode ("inc", "dptr"); /* point to next area */
12290 emitcode ("inc","dps"); /* switch to DPTR2 */
12291 emitcode ("djnz","b,!tlabel",lbl->key+100);
12293 symbol *lbl1 = newiTempLabel(NULL);
12295 emitcode (";"," Auto increment but no djnz");
12296 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12297 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12298 freeAsmop (count, NULL, ic, FALSE);
12299 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12300 emitcode ("","!tlabeldef",lbl->key+100);
12301 emitcode ("movx", "a,@dptr");
12302 emitcode ("dec","dps"); /* switch to DPTR */
12303 emitcode ("movx", "@dptr,a");
12304 emitcode ("inc", "dptr");
12305 emitcode ("inc","dps"); /* switch to DPTR2 */
12306 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
12307 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
12308 emitcode ("mov","a,b");
12309 emitcode ("orl","a,_ap");
12310 emitcode ("jz","!tlabel",lbl1->key+100);
12311 emitcode ("mov","a,_ap");
12312 emitcode ("add","a,#!constbyte",0xFF);
12313 emitcode ("mov","_ap,a");
12314 emitcode ("mov","a,b");
12315 emitcode ("addc","a,#!constbyte",0xFF);
12316 emitcode ("mov","b,a");
12317 emitcode ("sjmp","!tlabel",lbl->key+100);
12318 emitcode ("","!tlabeldef",lbl1->key+100);
12320 emitcode ("mov", "dps,#0");
12321 _G.dptrInUse = _G.dptr1InUse = 0;
12322 unsavermask(rsave);
12326 /*-----------------------------------------------------------------*/
12327 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
12328 /* port, first parameter output area second parameter pointer to */
12329 /* port third parameter count */
12330 /*-----------------------------------------------------------------*/
12331 static void genOutp( iCode *ic, int nparms, operand **parms)
12333 operand *from , *to , *count;
12338 /* we know it has to be 3 parameters */
12339 assert (nparms == 3);
12341 rsave = newBitVect(16);
12342 /* save DPTR if it needs to be saved */
12343 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12344 if (bitVectBitValue(ic->rMask,i))
12345 rsave = bitVectSetBit(rsave,i);
12347 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12348 ds390_rUmaskForOp (IC_RESULT(ic))));
12355 aopOp (from, ic->next, FALSE, FALSE);
12357 /* get from into DPTR1 */
12358 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12359 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12360 if (options.model == MODEL_FLAT24) {
12361 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12364 freeAsmop (from, NULL, ic, FALSE);
12365 aopOp (to, ic, FALSE, FALSE);
12366 /* get "to" into DPTR */
12367 /* if the operand is already in dptr
12368 then we do nothing else we move the value to dptr */
12369 if (AOP_TYPE (to) != AOP_STR) {
12370 /* if already in DPTR then we need to push */
12371 if (AOP_TYPE(to) == AOP_DPTR) {
12372 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12373 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12374 if (options.model == MODEL_FLAT24)
12375 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12376 emitcode ("pop", "dph");
12377 emitcode ("pop", "dpl");
12379 _startLazyDPSEvaluation ();
12380 /* if this is remateriazable */
12381 if (AOP_TYPE (to) == AOP_IMMD) {
12382 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12383 } else { /* we need to get it byte by byte */
12384 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12385 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12386 if (options.model == MODEL_FLAT24) {
12387 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12390 _endLazyDPSEvaluation ();
12393 freeAsmop (to, NULL, ic, FALSE);
12395 _G.dptrInUse = _G.dptr1InUse = 1;
12396 aopOp (count, ic->next->next, FALSE,FALSE);
12397 lbl =newiTempLabel(NULL);
12399 /* now for the actual copy */
12400 if (AOP_TYPE(count) == AOP_LIT &&
12401 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12402 emitcode (";","OH JOY auto increment with djnz (very fast)");
12403 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12404 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12405 emitcode ("","!tlabeldef",lbl->key+100);
12406 emitcode ("movx", "a,@dptr"); /* read data from port */
12407 emitcode ("inc","dps"); /* switch to DPTR2 */
12408 emitcode ("movx", "@dptr,a"); /* save into location */
12409 emitcode ("inc", "dptr"); /* point to next area */
12410 emitcode ("dec","dps"); /* switch to DPTR */
12411 emitcode ("djnz","b,!tlabel",lbl->key+100);
12412 freeAsmop (count, NULL, ic, FALSE);
12414 symbol *lbl1 = newiTempLabel(NULL);
12416 emitcode (";"," Auto increment but no djnz");
12417 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12418 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12419 freeAsmop (count, NULL, ic, FALSE);
12420 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12421 emitcode ("","!tlabeldef",lbl->key+100);
12422 emitcode ("movx", "a,@dptr");
12423 emitcode ("inc", "dptr");
12424 emitcode ("inc","dps"); /* switch to DPTR2 */
12425 emitcode ("movx", "@dptr,a");
12426 emitcode ("dec","dps"); /* switch to DPTR */
12427 emitcode ("mov","a,b");
12428 emitcode ("orl","a,_ap");
12429 emitcode ("jz","!tlabel",lbl1->key+100);
12430 emitcode ("mov","a,_ap");
12431 emitcode ("add","a,#!constbyte",0xFF);
12432 emitcode ("mov","_ap,a");
12433 emitcode ("mov","a,b");
12434 emitcode ("addc","a,#!constbyte",0xFF);
12435 emitcode ("mov","b,a");
12436 emitcode ("sjmp","!tlabel",lbl->key+100);
12437 emitcode ("","!tlabeldef",lbl1->key+100);
12439 emitcode ("mov", "dps,#0");
12440 _G.dptrInUse = _G.dptr1InUse = 0;
12441 unsavermask(rsave);
12445 /*-----------------------------------------------------------------*/
12446 /* genSwapW - swap lower & high order bytes */
12447 /*-----------------------------------------------------------------*/
12448 static void genSwapW(iCode *ic, int nparms, operand **parms)
12452 assert (nparms==1);
12455 dest=IC_RESULT(ic);
12457 assert(getSize(operandType(src))==2);
12459 aopOp (src, ic, FALSE, FALSE);
12460 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
12462 MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
12464 freeAsmop (src, NULL, ic, FALSE);
12466 aopOp (dest,ic, FALSE, FALSE);
12467 aopPut(AOP(dest),"b",0);
12468 aopPut(AOP(dest),"a",1);
12469 freeAsmop (dest, NULL, ic, FALSE);
12472 /*-----------------------------------------------------------------*/
12473 /* genMemsetX - gencode for memSetX data */
12474 /*-----------------------------------------------------------------*/
12475 static void genMemsetX(iCode *ic, int nparms, operand **parms)
12477 operand *to , *val , *count;
12483 /* we know it has to be 3 parameters */
12484 assert (nparms == 3);
12490 /* save DPTR if it needs to be saved */
12491 rsave = newBitVect(16);
12492 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12493 if (bitVectBitValue(ic->rMask,i))
12494 rsave = bitVectSetBit(rsave,i);
12496 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12497 ds390_rUmaskForOp (IC_RESULT(ic))));
12500 aopOp (to, ic, FALSE, FALSE);
12501 /* get "to" into DPTR */
12502 /* if the operand is already in dptr
12503 then we do nothing else we move the value to dptr */
12504 if (AOP_TYPE (to) != AOP_STR) {
12505 /* if already in DPTR then we need to push */
12506 if (AOP_TYPE(to) == AOP_DPTR) {
12507 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12508 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12509 if (options.model == MODEL_FLAT24)
12510 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12511 emitcode ("pop", "dph");
12512 emitcode ("pop", "dpl");
12514 _startLazyDPSEvaluation ();
12515 /* if this is remateriazable */
12516 if (AOP_TYPE (to) == AOP_IMMD) {
12517 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12518 } else { /* we need to get it byte by byte */
12519 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12520 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12521 if (options.model == MODEL_FLAT24) {
12522 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12525 _endLazyDPSEvaluation ();
12528 freeAsmop (to, NULL, ic, FALSE);
12530 aopOp (val, ic->next->next, FALSE,FALSE);
12531 aopOp (count, ic->next->next, FALSE,FALSE);
12532 lbl =newiTempLabel(NULL);
12533 /* now for the actual copy */
12534 if (AOP_TYPE(count) == AOP_LIT &&
12535 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12536 l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
12537 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12539 emitcode ("","!tlabeldef",lbl->key+100);
12540 emitcode ("movx", "@dptr,a");
12541 emitcode ("inc", "dptr");
12542 emitcode ("djnz","b,!tlabel",lbl->key+100);
12544 symbol *lbl1 = newiTempLabel(NULL);
12546 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12547 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12548 emitcode ("","!tlabeldef",lbl->key+100);
12549 MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
12550 emitcode ("movx", "@dptr,a");
12551 emitcode ("inc", "dptr");
12552 emitcode ("mov","a,b");
12553 emitcode ("orl","a,_ap");
12554 emitcode ("jz","!tlabel",lbl1->key+100);
12555 emitcode ("mov","a,_ap");
12556 emitcode ("add","a,#!constbyte",0xFF);
12557 emitcode ("mov","_ap,a");
12558 emitcode ("mov","a,b");
12559 emitcode ("addc","a,#!constbyte",0xFF);
12560 emitcode ("mov","b,a");
12561 emitcode ("sjmp","!tlabel",lbl->key+100);
12562 emitcode ("","!tlabeldef",lbl1->key+100);
12564 freeAsmop (count, NULL, ic, FALSE);
12565 unsavermask(rsave);
12568 /*-----------------------------------------------------------------*/
12569 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12570 /*-----------------------------------------------------------------*/
12571 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12574 operand *pnum, *result;
12577 assert (nparms==1);
12578 /* save registers that need to be saved */
12579 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12580 ds390_rUmaskForOp (IC_RESULT(ic))));
12583 aopOp (pnum, ic, FALSE, FALSE);
12584 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12585 freeAsmop (pnum, NULL, ic, FALSE);
12586 emitcode ("lcall","NatLib_LoadPrimitive");
12587 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12588 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
12589 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12590 for (i = (size-1) ; i >= 0 ; i-- ) {
12591 emitcode ("push","a%s",javaRet[i]);
12593 for (i=0; i < size ; i++ ) {
12594 emitcode ("pop","a%s",
12595 aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12598 for (i = 0 ; i < size ; i++ ) {
12599 aopPut(AOP(result),javaRet[i],i);
12602 freeAsmop (result, NULL, ic, FALSE);
12603 unsavermask(rsave);
12606 /*-----------------------------------------------------------------*/
12607 /* genNatLibLoadPointer - calls TINI api function to load pointer */
12608 /*-----------------------------------------------------------------*/
12609 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12612 operand *pnum, *result;
12616 assert (nparms==1);
12617 /* save registers that need to be saved */
12618 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12619 ds390_rUmaskForOp (IC_RESULT(ic))));
12622 aopOp (pnum, ic, FALSE, FALSE);
12623 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12624 freeAsmop (pnum, NULL, ic, FALSE);
12625 emitcode ("lcall","NatLib_LoadPointer");
12626 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12627 if (AOP_TYPE(result)!=AOP_STR) {
12628 for (i = 0 ; i < size ; i++ ) {
12629 aopPut(AOP(result),fReturn[i],i);
12632 freeAsmop (result, NULL, ic, FALSE);
12633 unsavermask(rsave);
12636 /*-----------------------------------------------------------------*/
12637 /* genNatLibInstallStateBlock - */
12638 /*-----------------------------------------------------------------*/
12639 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
12640 operand **parms, const char *name)
12643 operand *psb, *handle;
12644 assert (nparms==2);
12646 /* save registers that need to be saved */
12647 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12648 ds390_rUmaskForOp (IC_RESULT(ic))));
12652 /* put pointer to state block into DPTR1 */
12653 aopOp (psb, ic, FALSE, FALSE);
12654 if (AOP_TYPE (psb) == AOP_IMMD) {
12655 emitcode ("mov","dps,#1");
12656 emitcode ("mov", "dptr,%s",
12657 aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12658 emitcode ("mov","dps,#0");
12660 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12661 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12662 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12664 freeAsmop (psb, NULL, ic, FALSE);
12666 /* put libraryID into DPTR */
12667 emitcode ("mov","dptr,#LibraryID");
12669 /* put handle into r3:r2 */
12670 aopOp (handle, ic, FALSE, FALSE);
12671 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12672 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12673 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12674 emitcode ("pop","ar3");
12675 emitcode ("pop","ar2");
12677 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12678 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12680 freeAsmop (psb, NULL, ic, FALSE);
12682 /* make the call */
12683 emitcode ("lcall","NatLib_Install%sStateBlock",name);
12685 /* put return value into place*/
12687 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12689 aopPut(AOP(IC_RESULT(ic)),"a",0);
12690 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12691 unsavermask(rsave);
12694 /*-----------------------------------------------------------------*/
12695 /* genNatLibRemoveStateBlock - */
12696 /*-----------------------------------------------------------------*/
12697 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12703 /* save registers that need to be saved */
12704 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12705 ds390_rUmaskForOp (IC_RESULT(ic))));
12707 /* put libraryID into DPTR */
12708 emitcode ("mov","dptr,#LibraryID");
12709 /* make the call */
12710 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12711 unsavermask(rsave);
12714 /*-----------------------------------------------------------------*/
12715 /* genNatLibGetStateBlock - */
12716 /*-----------------------------------------------------------------*/
12717 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12718 operand **parms,const char *name)
12721 symbol *lbl = newiTempLabel(NULL);
12724 /* save registers that need to be saved */
12725 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12726 ds390_rUmaskForOp (IC_RESULT(ic))));
12728 /* put libraryID into DPTR */
12729 emitcode ("mov","dptr,#LibraryID");
12730 /* make the call */
12731 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12732 emitcode ("jnz","!tlabel",lbl->key+100);
12734 /* put return value into place */
12735 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12736 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12737 emitcode ("push","ar3");
12738 emitcode ("push","ar2");
12739 emitcode ("pop","%s",
12740 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12741 emitcode ("pop","%s",
12742 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12744 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12745 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12747 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12748 emitcode ("","!tlabeldef",lbl->key+100);
12749 unsavermask(rsave);
12752 /*-----------------------------------------------------------------*/
12753 /* genMMMalloc - */
12754 /*-----------------------------------------------------------------*/
12755 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12756 int size, const char *name)
12761 symbol *lbl = newiTempLabel(NULL);
12763 assert (nparms == 1);
12764 /* save registers that need to be saved */
12765 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12766 ds390_rUmaskForOp (IC_RESULT(ic))));
12769 aopOp (bsize,ic,FALSE,FALSE);
12771 /* put the size in R4-R2 */
12772 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12773 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12774 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12776 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12777 emitcode("pop","ar4");
12779 emitcode("pop","ar3");
12780 emitcode("pop","ar2");
12782 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12783 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12785 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12788 freeAsmop (bsize, NULL, ic, FALSE);
12790 /* make the call */
12791 emitcode ("lcall","MM_%s",name);
12792 emitcode ("jz","!tlabel",lbl->key+100);
12793 emitcode ("mov","r2,#!constbyte",0xff);
12794 emitcode ("mov","r3,#!constbyte",0xff);
12795 emitcode ("","!tlabeldef",lbl->key+100);
12796 /* we don't care about the pointer : we just save the handle */
12797 rsym = OP_SYMBOL(IC_RESULT(ic));
12798 if (rsym->liveFrom != rsym->liveTo) {
12799 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12800 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12801 emitcode ("push","ar3");
12802 emitcode ("push","ar2");
12803 emitcode ("pop","%s",
12804 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12805 emitcode ("pop","%s",
12806 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12808 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12809 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12811 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12813 unsavermask(rsave);
12816 /*-----------------------------------------------------------------*/
12818 /*-----------------------------------------------------------------*/
12819 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12824 assert (nparms == 1);
12825 /* save registers that need to be saved */
12826 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12827 ds390_rUmaskForOp (IC_RESULT(ic))));
12830 aopOp (handle,ic,FALSE,FALSE);
12832 /* put the size in R4-R2 */
12833 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12834 emitcode("push","%s",
12835 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12836 emitcode("push","%s",
12837 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12838 emitcode("pop","ar3");
12839 emitcode("pop","ar2");
12841 emitcode ("mov","r2,%s",
12842 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12843 emitcode ("mov","r3,%s",
12844 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12846 freeAsmop (handle, NULL, ic, FALSE);
12848 /* make the call */
12849 emitcode ("lcall","MM_Deref");
12852 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12853 if (rsym->liveFrom != rsym->liveTo) {
12854 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12855 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12856 _startLazyDPSEvaluation ();
12858 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12859 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12860 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12862 _endLazyDPSEvaluation ();
12867 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12868 unsavermask(rsave);
12871 /*-----------------------------------------------------------------*/
12872 /* genMMUnrestrictedPersist - */
12873 /*-----------------------------------------------------------------*/
12874 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12879 assert (nparms == 1);
12880 /* save registers that need to be saved */
12881 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12882 ds390_rUmaskForOp (IC_RESULT(ic))));
12885 aopOp (handle,ic,FALSE,FALSE);
12887 /* put the size in R3-R2 */
12888 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12889 emitcode("push","%s",
12890 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12891 emitcode("push","%s",
12892 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12893 emitcode("pop","ar3");
12894 emitcode("pop","ar2");
12896 emitcode ("mov","r2,%s",
12897 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12898 emitcode ("mov","r3,%s",
12899 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12901 freeAsmop (handle, NULL, ic, FALSE);
12903 /* make the call */
12904 emitcode ("lcall","MM_UnrestrictedPersist");
12907 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12908 if (rsym->liveFrom != rsym->liveTo) {
12909 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12910 aopPut(AOP(IC_RESULT(ic)),"a",0);
12911 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12914 unsavermask(rsave);
12917 /*-----------------------------------------------------------------*/
12918 /* genSystemExecJavaProcess - */
12919 /*-----------------------------------------------------------------*/
12920 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12923 operand *handle, *pp;
12925 assert (nparms==2);
12926 /* save registers that need to be saved */
12927 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12928 ds390_rUmaskForOp (IC_RESULT(ic))));
12933 /* put the handle in R3-R2 */
12934 aopOp (handle,ic,FALSE,FALSE);
12935 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12936 emitcode("push","%s",
12937 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12938 emitcode("push","%s",
12939 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12940 emitcode("pop","ar3");
12941 emitcode("pop","ar2");
12943 emitcode ("mov","r2,%s",
12944 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12945 emitcode ("mov","r3,%s",
12946 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12948 freeAsmop (handle, NULL, ic, FALSE);
12950 /* put pointer in DPTR */
12951 aopOp (pp,ic,FALSE,FALSE);
12952 if (AOP_TYPE(pp) == AOP_IMMD) {
12953 emitcode ("mov", "dptr,%s",
12954 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12955 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12956 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12957 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12958 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12960 freeAsmop (handle, NULL, ic, FALSE);
12962 /* make the call */
12963 emitcode ("lcall","System_ExecJavaProcess");
12965 /* put result in place */
12967 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12968 if (rsym->liveFrom != rsym->liveTo) {
12969 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12970 aopPut(AOP(IC_RESULT(ic)),"a",0);
12971 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12975 unsavermask(rsave);
12978 /*-----------------------------------------------------------------*/
12979 /* genSystemRTCRegisters - */
12980 /*-----------------------------------------------------------------*/
12981 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12987 assert (nparms==1);
12988 /* save registers that need to be saved */
12989 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12990 ds390_rUmaskForOp (IC_RESULT(ic))));
12993 /* put pointer in DPTR */
12994 aopOp (pp,ic,FALSE,FALSE);
12995 if (AOP_TYPE (pp) == AOP_IMMD) {
12996 emitcode ("mov","dps,#1");
12997 emitcode ("mov", "dptr,%s",
12998 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12999 emitcode ("mov","dps,#0");
13001 emitcode ("mov","dpl1,%s",
13002 aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
13003 emitcode ("mov","dph1,%s",
13004 aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
13005 emitcode ("mov","dpx1,%s",
13006 aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
13008 freeAsmop (pp, NULL, ic, FALSE);
13010 /* make the call */
13011 emitcode ("lcall","System_%sRTCRegisters",name);
13013 unsavermask(rsave);
13016 /*-----------------------------------------------------------------*/
13017 /* genSystemThreadSleep - */
13018 /*-----------------------------------------------------------------*/
13019 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
13024 assert (nparms==1);
13025 /* save registers that need to be saved */
13026 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13027 ds390_rUmaskForOp (IC_RESULT(ic))));
13030 aopOp(to,ic,FALSE,FALSE);
13031 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
13032 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
13033 emitcode ("push","%s",
13034 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
13035 emitcode ("push","%s",
13036 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
13037 emitcode ("push","%s",
13038 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
13039 emitcode ("push","%s",
13040 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
13041 emitcode ("pop","ar3");
13042 emitcode ("pop","ar2");
13043 emitcode ("pop","ar1");
13044 emitcode ("pop","ar0");
13046 emitcode ("mov","r0,%s",
13047 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
13048 emitcode ("mov","r1,%s",
13049 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
13050 emitcode ("mov","r2,%s",
13051 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
13052 emitcode ("mov","r3,%s",
13053 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
13055 freeAsmop (to, NULL, ic, FALSE);
13057 /* suspend in acc */
13059 aopOp(s,ic,FALSE,FALSE);
13060 emitcode ("mov","a,%s",
13061 aopGet(AOP(s),0,FALSE,TRUE,NULL));
13062 freeAsmop (s, NULL, ic, FALSE);
13064 /* make the call */
13065 emitcode ("lcall","System_%s",name);
13067 unsavermask(rsave);
13070 /*-----------------------------------------------------------------*/
13071 /* genSystemThreadResume - */
13072 /*-----------------------------------------------------------------*/
13073 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
13078 assert (nparms==2);
13079 /* save registers that need to be saved */
13080 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13081 ds390_rUmaskForOp (IC_RESULT(ic))));
13087 aopOp(pid,ic,FALSE,FALSE);
13088 emitcode ("mov","r0,%s",
13089 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13090 freeAsmop (pid, NULL, ic, FALSE);
13093 aopOp(tid,ic,FALSE,FALSE);
13094 emitcode ("mov","a,%s",
13095 aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
13096 freeAsmop (tid, NULL, ic, FALSE);
13098 emitcode ("lcall","System_ThreadResume");
13100 /* put result into place */
13102 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13103 if (rsym->liveFrom != rsym->liveTo) {
13104 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13105 aopPut(AOP(IC_RESULT(ic)),"a",0);
13106 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13109 unsavermask(rsave);
13112 /*-----------------------------------------------------------------*/
13113 /* genSystemProcessResume - */
13114 /*-----------------------------------------------------------------*/
13115 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
13120 assert (nparms==1);
13121 /* save registers that need to be saved */
13122 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13123 ds390_rUmaskForOp (IC_RESULT(ic))));
13128 aopOp(pid,ic,FALSE,FALSE);
13129 emitcode ("mov","a,%s",
13130 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13131 freeAsmop (pid, NULL, ic, FALSE);
13133 emitcode ("lcall","System_ProcessResume");
13135 unsavermask(rsave);
13138 /*-----------------------------------------------------------------*/
13140 /*-----------------------------------------------------------------*/
13141 static void genSystem (iCode *ic,int nparms,char *name)
13143 assert(nparms == 0);
13145 emitcode ("lcall","System_%s",name);
13148 /*-----------------------------------------------------------------*/
13149 /* genSystemPoll - */
13150 /*-----------------------------------------------------------------*/
13151 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
13156 assert (nparms==1);
13157 /* save registers that need to be saved */
13158 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13159 ds390_rUmaskForOp (IC_RESULT(ic))));
13162 aopOp (fp,ic,FALSE,FALSE);
13163 if (AOP_TYPE (fp) == AOP_IMMD) {
13164 emitcode ("mov", "dptr,%s",
13165 aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
13166 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
13167 emitcode ("mov","dpl,%s",
13168 aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
13169 emitcode ("mov","dph,%s",
13170 aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
13171 emitcode ("mov","dpx,%s",
13172 aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
13174 freeAsmop (fp, NULL, ic, FALSE);
13176 emitcode ("lcall","System_%sPoll",name);
13178 /* put result into place */
13180 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13181 if (rsym->liveFrom != rsym->liveTo) {
13182 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13183 aopPut(AOP(IC_RESULT(ic)),"a",0);
13184 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13187 unsavermask(rsave);
13190 /*-----------------------------------------------------------------*/
13191 /* genSystemGetCurrentID - */
13192 /*-----------------------------------------------------------------*/
13193 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
13195 assert (nparms==0);
13197 emitcode ("lcall","System_GetCurrent%sId",name);
13198 /* put result into place */
13200 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13201 if (rsym->liveFrom != rsym->liveTo) {
13202 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13203 aopPut(AOP(IC_RESULT(ic)),"a",0);
13204 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13209 /*-----------------------------------------------------------------*/
13210 /* genDummyRead - generate code for dummy read of volatiles */
13211 /*-----------------------------------------------------------------*/
13213 genDummyRead (iCode * ic)
13218 D(emitcode("; genDummyRead",""));
13220 op = IC_RIGHT (ic);
13221 if (op && IS_SYMOP (op))
13223 aopOp (op, ic, FALSE, FALSE);
13225 /* if the result is a bit */
13226 if (AOP_TYPE (op) == AOP_CRY)
13227 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13230 /* bit variables done */
13232 size = AOP_SIZE (op);
13236 MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13241 freeAsmop (op, NULL, ic, TRUE);
13245 if (op && IS_SYMOP (op))
13247 aopOp (op, ic, FALSE, FALSE);
13249 /* if the result is a bit */
13250 if (AOP_TYPE (op) == AOP_CRY)
13251 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13254 /* bit variables done */
13256 size = AOP_SIZE (op);
13260 MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13265 freeAsmop (op, NULL, ic, TRUE);
13270 /*-----------------------------------------------------------------*/
13271 /* genCritical - generate code for start of a critical sequence */
13272 /*-----------------------------------------------------------------*/
13274 genCritical (iCode *ic)
13276 symbol *tlbl = newiTempLabel (NULL);
13278 D(emitcode("; genCritical",""));
13280 if (IC_RESULT (ic))
13281 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
13283 emitcode ("setb", "c");
13284 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
13285 emitcode ("clr", "c");
13286 emitcode ("", "%05d$:", (tlbl->key + 100));
13288 if (IC_RESULT (ic))
13289 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
13291 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
13293 if (IC_RESULT (ic))
13294 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13297 /*-----------------------------------------------------------------*/
13298 /* genEndCritical - generate code for end of a critical sequence */
13299 /*-----------------------------------------------------------------*/
13301 genEndCritical (iCode *ic)
13303 D(emitcode("; genEndCritical",""));
13307 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
13308 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
13310 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
13311 emitcode ("mov", "ea,c");
13315 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE));
13316 emitcode ("rrc", "a");
13317 emitcode ("mov", "ea,c");
13319 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
13323 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
13324 emitcode ("mov", "ea,c");
13330 /*-----------------------------------------------------------------*/
13331 /* genBuiltIn - calls the appropriate function to generating code */
13332 /* for a built in function */
13333 /*-----------------------------------------------------------------*/
13334 static void genBuiltIn (iCode *ic)
13336 operand *bi_parms[MAX_BUILTIN_ARGS];
13341 /* get all the arguments for a built in function */
13342 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
13344 /* which function is it */
13345 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
13346 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
13347 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
13348 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
13349 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
13350 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
13351 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
13352 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
13353 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
13354 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
13355 genMemsetX(bi_iCode,nbi_parms,bi_parms);
13356 } else if (strcmp(bif->name,"__builtin_inp")==0) {
13357 genInp(bi_iCode,nbi_parms,bi_parms);
13358 } else if (strcmp(bif->name,"__builtin_outp")==0) {
13359 genOutp(bi_iCode,nbi_parms,bi_parms);
13360 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
13361 genSwapW(bi_iCode,nbi_parms,bi_parms);
13362 /* JavaNative builtIns */
13363 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
13364 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
13365 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
13366 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
13367 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
13368 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
13369 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
13370 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
13371 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
13372 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13373 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
13374 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13375 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
13376 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
13377 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
13378 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
13379 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
13380 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13381 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
13382 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13383 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
13384 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
13385 } else if (strcmp(bif->name,"MM_Malloc")==0) {
13386 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
13387 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
13388 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
13389 } else if (strcmp(bif->name,"MM_Free")==0) {
13390 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
13391 } else if (strcmp(bif->name,"MM_Deref")==0) {
13392 genMMDeref(bi_iCode,nbi_parms,bi_parms);
13393 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
13394 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
13395 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
13396 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
13397 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
13398 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
13399 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
13400 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
13401 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
13402 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
13403 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
13404 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
13405 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
13406 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
13407 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
13408 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
13409 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13410 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13411 } else if (strcmp(bif->name,"System_SaveThread")==0) {
13412 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13413 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13414 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13415 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
13416 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
13417 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
13418 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
13419 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
13420 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
13421 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
13422 genSystem(bi_iCode,nbi_parms,"ProcessYield");
13423 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
13424 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
13425 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
13426 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
13427 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
13428 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
13429 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
13430 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
13431 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
13432 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
13434 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
13440 /*-----------------------------------------------------------------*/
13441 /* gen390Code - generate code for Dallas 390 based controllers */
13442 /*-----------------------------------------------------------------*/
13444 gen390Code (iCode * lic)
13449 lineHead = lineCurr = NULL;
13450 dptrn[1][0] = "dpl1";
13451 dptrn[1][1] = "dph1";
13452 dptrn[1][2] = "dpx1";
13454 if (options.model == MODEL_FLAT24) {
13455 fReturnSizeDS390 = 5;
13456 fReturn = fReturn24;
13458 fReturnSizeDS390 = 4;
13459 fReturn = fReturn16;
13460 options.stack10bit=0;
13463 /* print the allocation information */
13464 if (allocInfo && currFunc)
13465 printAllocInfo (currFunc, codeOutFile);
13467 /* if debug information required */
13468 if (options.debug && currFunc)
13470 debugFile->writeFunction (currFunc, lic);
13472 /* stack pointer name */
13473 if (options.useXstack)
13479 for (ic = lic; ic; ic = ic->next)
13481 _G.current_iCode = ic;
13483 if (ic->lineno && cln != ic->lineno)
13487 debugFile->writeCLine (ic);
13489 if (!options.noCcodeInAsm) {
13490 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
13491 printCLine(ic->filename, ic->lineno));
13495 if (options.iCodeInAsm) {
13496 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
13498 /* if the result is marked as
13499 spilt and rematerializable or code for
13500 this has already been generated then
13502 if (resultRemat (ic) || ic->generated)
13505 /* depending on the operation */
13525 /* IPOP happens only when trying to restore a
13526 spilt live range, if there is an ifx statement
13527 following this pop then the if statement might
13528 be using some of the registers being popped which
13529 would destory the contents of the register so
13530 we need to check for this condition and handle it */
13532 ic->next->op == IFX &&
13533 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
13534 genIfx (ic->next, ic);
13552 genEndFunction (ic);
13572 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
13589 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
13593 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
13600 /* note these two are xlated by algebraic equivalence
13601 during parsing SDCC.y */
13602 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13603 "got '>=' or '<=' shouldn't have come here");
13607 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
13619 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
13623 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
13627 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
13651 genRightShift (ic);
13654 case GET_VALUE_AT_ADDRESS:
13655 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13659 if (POINTER_SET (ic))
13660 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13686 if (ic->builtinSEND) genBuiltIn(ic);
13687 else addSet (&_G.sendSet, ic);
13690 case DUMMY_READ_VOLATILE:
13699 genEndCritical (ic);
13706 #if 0 // obsolete, and buggy for != xdata
13718 /* now we are ready to call the
13719 peep hole optimizer */
13720 if (!options.nopeep)
13721 peepHole (&lineHead);
13723 /* now do the actual printing */
13724 printLine (lineHead, codeOutFile);