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 (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2195 rsave = newBitVect(ic->rMask->size);
2196 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2197 if (bitVectBitValue(ic->rMask,i))
2198 rsave = bitVectSetBit(rsave,i);
2200 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2202 /* restore the registers in use at this time but skip the
2203 ones for the result */
2204 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2205 ds390_rUmaskForOp (IC_RESULT(ic)));
2211 /*-----------------------------------------------------------------*/
2213 /*-----------------------------------------------------------------*/
2215 pushSide (operand * oper, int size)
2218 _startLazyDPSEvaluation ();
2221 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2222 if (AOP_TYPE (oper) != AOP_REG &&
2223 AOP_TYPE (oper) != AOP_DIR &&
2226 emitcode ("mov", "a,%s", l);
2227 emitcode ("push", "acc");
2230 emitcode ("push", "%s", l);
2232 _endLazyDPSEvaluation ();
2235 /*-----------------------------------------------------------------*/
2236 /* assignResultValue - */
2237 /*-----------------------------------------------------------------*/
2239 assignResultValue (operand * oper)
2242 int size = AOP_SIZE (oper);
2243 bool pushedAcc = FALSE;
2245 if (size == fReturnSizeDS390)
2247 /* I don't think this case can ever happen... */
2248 /* ACC is the last part of this. If writing the result
2249 * uses AC, we must preserve it.
2251 if (AOP_NEEDSACC(oper))
2253 emitcode(";", "assignResultValue special case for ACC.");
2254 emitcode("push", "acc");
2261 _startLazyDPSEvaluation ();
2264 aopPut (AOP (oper), fReturn[offset], offset);
2267 _endLazyDPSEvaluation ();
2271 emitcode("pop", "acc");
2272 aopPut(AOP(oper), "a", offset);
2277 /*-----------------------------------------------------------------*/
2278 /* genXpush - pushes onto the external stack */
2279 /*-----------------------------------------------------------------*/
2281 genXpush (iCode * ic)
2283 asmop *aop = newAsmop (0);
2285 int size, offset = 0;
2287 D (emitcode (";", "genXpush ");
2290 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2291 r = getFreePtr (ic, &aop, FALSE);
2294 emitcode ("mov", "%s,_spx", r->name);
2296 size = AOP_SIZE (IC_LEFT (ic));
2297 _startLazyDPSEvaluation ();
2301 MOVA (aopGet (AOP (IC_LEFT (ic)),
2302 offset++, FALSE, FALSE, NULL));
2303 emitcode ("movx", "@%s,a", r->name);
2304 emitcode ("inc", "%s", r->name);
2307 _endLazyDPSEvaluation ();
2310 emitcode ("mov", "_spx,%s", r->name);
2312 freeAsmop (NULL, aop, ic, TRUE);
2313 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2316 /*-----------------------------------------------------------------*/
2317 /* genIpush - generate code for pushing this gets a little complex */
2318 /*-----------------------------------------------------------------*/
2320 genIpush (iCode * ic)
2322 int size, offset = 0;
2325 D (emitcode (";", "genIpush ");
2328 /* if this is not a parm push : ie. it is spill push
2329 and spill push is always done on the local stack */
2333 /* and the item is spilt then do nothing */
2334 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2337 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2338 size = AOP_SIZE (IC_LEFT (ic));
2339 /* push it on the stack */
2340 _startLazyDPSEvaluation ();
2343 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2349 emitcode ("push", "%s", l);
2351 _endLazyDPSEvaluation ();
2355 /* this is a paramter push: in this case we call
2356 the routine to find the call and save those
2357 registers that need to be saved */
2360 /* if use external stack then call the external
2361 stack pushing routine */
2362 if (options.useXstack)
2368 /* then do the push */
2369 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2371 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2372 size = AOP_SIZE (IC_LEFT (ic));
2374 _startLazyDPSEvaluation ();
2377 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2378 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2379 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2382 emitcode ("mov", "a,%s", l);
2383 emitcode ("push", "acc");
2387 emitcode ("push", "%s", l);
2390 _endLazyDPSEvaluation ();
2392 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2395 /*-----------------------------------------------------------------*/
2396 /* genIpop - recover the registers: can happen only for spilling */
2397 /*-----------------------------------------------------------------*/
2399 genIpop (iCode * ic)
2403 D (emitcode (";", "genIpop ");
2407 /* if the temp was not pushed then */
2408 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2411 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2412 size = AOP_SIZE (IC_LEFT (ic));
2413 offset = (size - 1);
2414 _startLazyDPSEvaluation ();
2417 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2418 FALSE, TRUE, NULL));
2420 _endLazyDPSEvaluation ();
2422 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2425 /*-----------------------------------------------------------------*/
2426 /* unsaveRBank - restores the resgister bank from stack */
2427 /*-----------------------------------------------------------------*/
2429 unsaveRBank (int bank, iCode * ic, bool popPsw)
2435 if (options.useXstack)
2439 /* Assume r0 is available for use. */
2440 r = ds390_regWithIdx (R0_IDX);;
2445 r = getFreePtr (ic, &aop, FALSE);
2447 emitcode ("mov", "%s,_spx", r->name);
2452 if (options.useXstack)
2454 emitcode ("movx", "a,@%s", r->name);
2455 emitcode ("mov", "psw,a");
2456 emitcode ("dec", "%s", r->name);
2460 emitcode ("pop", "psw");
2464 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2466 if (options.useXstack)
2468 emitcode ("movx", "a,@%s", r->name);
2469 emitcode ("mov", "(%s+%d),a",
2470 regs390[i].base, 8 * bank + regs390[i].offset);
2471 emitcode ("dec", "%s", r->name);
2475 emitcode ("pop", "(%s+%d)",
2476 regs390[i].base, 8 * bank + regs390[i].offset);
2479 if (options.useXstack)
2481 emitcode ("mov", "_spx,%s", r->name);
2486 freeAsmop (NULL, aop, ic, TRUE);
2490 /*-----------------------------------------------------------------*/
2491 /* saveRBank - saves an entire register bank on the stack */
2492 /*-----------------------------------------------------------------*/
2494 saveRBank (int bank, iCode * ic, bool pushPsw)
2500 if (options.useXstack)
2504 /* Assume r0 is available for use. */
2505 r = ds390_regWithIdx (R0_IDX);;
2510 r = getFreePtr (ic, &aop, FALSE);
2512 emitcode ("mov", "%s,_spx", r->name);
2515 for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2517 if (options.useXstack)
2519 emitcode ("inc", "%s", r->name);
2520 emitcode ("mov", "a,(%s+%d)",
2521 regs390[i].base, 8 * bank + regs390[i].offset);
2522 emitcode ("movx", "@%s,a", r->name);
2525 emitcode ("push", "(%s+%d)",
2526 regs390[i].base, 8 * bank + regs390[i].offset);
2531 if (options.useXstack)
2533 emitcode ("mov", "a,psw");
2534 emitcode ("movx", "@%s,a", r->name);
2535 emitcode ("inc", "%s", r->name);
2536 emitcode ("mov", "_spx,%s", r->name);
2540 emitcode ("push", "psw");
2543 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2548 freeAsmop (NULL, aop, ic, TRUE);
2557 /*-----------------------------------------------------------------*/
2558 /* genSend - gen code for SEND */
2559 /*-----------------------------------------------------------------*/
2560 static void genSend(set *sendSet)
2564 static int rb1_count = 0;
2566 for (sic = setFirstItem (sendSet); sic;
2567 sic = setNextItem (sendSet)) {
2568 int size, offset = 0;
2570 size=getSize(operandType(IC_LEFT(sic)));
2571 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2572 if (sendCount == 0) { /* first parameter */
2573 // we know that dpl(hxb) is the result, so
2575 _startLazyDPSEvaluation ();
2577 aopOp (IC_LEFT (sic), sic, FALSE,
2578 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2580 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2583 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2584 FALSE, FALSE, NULL);
2585 if (strcmp (l, fReturn[offset])) {
2586 emitcode ("mov", "%s,%s",
2592 _endLazyDPSEvaluation ();
2593 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2595 } else { /* if more parameter in registers */
2596 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2598 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2599 FALSE, FALSE, NULL));
2601 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2608 adjustEsp(const char *reg)
2610 emitcode ("anl","%s,#3", reg);
2611 if (TARGET_IS_DS400)
2613 emitcode ("orl","%s,#!constbyte",
2615 (options.stack_loc >> 8) & 0xff);
2619 /*-----------------------------------------------------------------*/
2620 /* genCall - generates a call statement */
2621 /*-----------------------------------------------------------------*/
2623 genCall (iCode * ic)
2626 bool restoreBank = FALSE;
2627 bool swapBanks = FALSE;
2629 D (emitcode (";", "genCall "););
2631 /* if we are calling a not _naked function that is not using
2632 the same register bank then we need to save the
2633 destination registers on the stack */
2634 dtype = operandType (IC_LEFT (ic));
2635 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2636 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2637 IFFUNC_ISISR (currFunc->type))
2641 /* This is unexpected; the bank should have been saved in
2644 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2650 /* if caller saves & we have not saved then */
2654 /* if send set is not empty then assign */
2655 /* We've saved all the registers we care about;
2656 * therefore, we may clobber any register not used
2657 * in the calling convention (i.e. anything not in
2662 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2663 genSend(reverseSet(_G.sendSet));
2665 genSend(_G.sendSet);
2672 emitcode ("mov", "psw,#!constbyte",
2673 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2677 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2678 OP_SYMBOL (IC_LEFT (ic))->rname :
2679 OP_SYMBOL (IC_LEFT (ic))->name));
2683 emitcode ("mov", "psw,#!constbyte",
2684 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2687 /* if we need assign a result value */
2688 if ((IS_ITEMP (IC_RESULT (ic)) &&
2689 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2690 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2691 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2692 IS_TRUE_SYMOP (IC_RESULT (ic)))
2694 if (isOperandInFarSpace (IC_RESULT (ic))
2695 && getSize (operandType (IC_RESULT (ic))) <= 2)
2697 int size = getSize (operandType (IC_RESULT (ic)));
2699 /* Special case for 1 or 2 byte return in far space. */
2703 emitcode ("mov", "b,%s", fReturn[1]);
2708 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2714 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2718 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2720 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2725 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2728 assignResultValue (IC_RESULT (ic));
2730 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2734 /* adjust the stack for parameters if
2736 if (ic->parmBytes) {
2738 if (options.stack10bit) {
2739 if (ic->parmBytes <= 10) {
2740 emitcode(";","stack adjustment for parms");
2741 for (i=0; i < ic->parmBytes ; i++) {
2742 emitcode("pop","acc");
2746 emitcode ("clr","c");
2747 emitcode ("mov","a,sp");
2748 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2749 emitcode ("mov","sp,a");
2750 emitcode ("mov","a,esp");
2752 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2753 emitcode ("mov","esp,a");
2757 if (ic->parmBytes > 3) {
2758 emitcode ("mov", "a,%s", spname);
2759 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2760 emitcode ("mov", "%s,a", spname);
2762 for (i = 0; i < ic->parmBytes; i++)
2763 emitcode ("dec", "%s", spname);
2767 /* if we hade saved some registers then unsave them */
2769 unsaveRegisters (ic);
2771 /* if register bank was saved then pop them */
2773 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2776 /*-----------------------------------------------------------------*/
2777 /* genPcall - generates a call by pointer statement */
2778 /*-----------------------------------------------------------------*/
2780 genPcall (iCode * ic)
2783 symbol *rlbl = newiTempLabel (NULL);
2784 bool restoreBank=FALSE;
2786 D (emitcode (";", "genPcall ");
2790 /* if caller saves & we have not saved then */
2794 /* if we are calling a function that is not using
2795 the same register bank then we need to save the
2796 destination registers on the stack */
2797 dtype = operandType (IC_LEFT (ic));
2798 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2799 IFFUNC_ISISR (currFunc->type) &&
2800 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2801 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2805 /* push the return address on to the stack */
2806 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2807 emitcode ("push", "acc");
2808 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2809 emitcode ("push", "acc");
2811 if (options.model == MODEL_FLAT24)
2813 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2814 emitcode ("push", "acc");
2817 /* now push the calling address */
2818 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2820 pushSide (IC_LEFT (ic), FPTRSIZE);
2822 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2824 /* if send set is not empty the assign */
2827 genSend(reverseSet(_G.sendSet));
2831 emitcode ("ret", "");
2832 emitcode ("", "!tlabeldef", (rlbl->key + 100));
2835 /* if we need assign a result value */
2836 if ((IS_ITEMP (IC_RESULT (ic)) &&
2837 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2838 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2839 IS_TRUE_SYMOP (IC_RESULT (ic)))
2843 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2846 assignResultValue (IC_RESULT (ic));
2848 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2851 /* adjust the stack for parameters if
2856 if (options.stack10bit) {
2857 if (ic->parmBytes <= 10) {
2858 emitcode(";","stack adjustment for parms");
2859 for (i=0; i < ic->parmBytes ; i++) {
2860 emitcode("pop","acc");
2864 emitcode ("clr","c");
2865 emitcode ("mov","a,sp");
2866 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2867 emitcode ("mov","sp,a");
2868 emitcode ("mov","a,esp");
2870 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2871 emitcode ("mov","esp,a");
2875 if (ic->parmBytes > 3) {
2876 emitcode ("mov", "a,%s", spname);
2877 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2878 emitcode ("mov", "%s,a", spname);
2881 for (i = 0; i < ic->parmBytes; i++)
2882 emitcode ("dec", "%s", spname);
2886 /* if register bank was saved then unsave them */
2888 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2890 /* if we hade saved some registers then
2893 unsaveRegisters (ic);
2897 /*-----------------------------------------------------------------*/
2898 /* resultRemat - result is rematerializable */
2899 /*-----------------------------------------------------------------*/
2901 resultRemat (iCode * ic)
2903 if (SKIP_IC (ic) || ic->op == IFX)
2906 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2908 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2909 if (sym->remat && !POINTER_SET (ic))
2916 #if defined(__BORLANDC__) || defined(_MSC_VER)
2917 #define STRCASECMP stricmp
2919 #define STRCASECMP strcasecmp
2922 /*-----------------------------------------------------------------*/
2923 /* inExcludeList - return 1 if the string is in exclude Reg list */
2924 /*-----------------------------------------------------------------*/
2926 regsCmp(void *p1, void *p2)
2928 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2932 inExcludeList (char *s)
2934 const char *p = setFirstItem(options.excludeRegsSet);
2936 if (p == NULL || STRCASECMP(p, "none") == 0)
2940 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2943 /*-----------------------------------------------------------------*/
2944 /* genFunction - generated code for function entry */
2945 /*-----------------------------------------------------------------*/
2947 genFunction (iCode * ic)
2951 bool switchedPSW = FALSE;
2953 D (emitcode (";", "genFunction "););
2956 /* create the function header */
2957 emitcode (";", "-----------------------------------------");
2958 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2959 emitcode (";", "-----------------------------------------");
2961 emitcode ("", "%s:", sym->rname);
2962 ftype = operandType (IC_LEFT (ic));
2964 if (IFFUNC_ISNAKED(ftype))
2966 emitcode(";", "naked function: no prologue.");
2970 if (options.stack_probe)
2971 emitcode ("lcall","__stack_probe");
2973 /* here we need to generate the equates for the
2974 register bank if required */
2975 if (FUNC_REGBANK (ftype) != rbank)
2979 rbank = FUNC_REGBANK (ftype);
2980 for (i = 0; i < ds390_nRegs; i++)
2982 if (regs390[i].print) {
2983 if (strcmp (regs390[i].base, "0") == 0)
2984 emitcode ("", "%s !equ !constbyte",
2986 8 * rbank + regs390[i].offset);
2988 emitcode ("", "%s !equ %s + !constbyte",
2991 8 * rbank + regs390[i].offset);
2996 /* if this is an interrupt service routine then
2997 save acc, b, dpl, dph */
2998 if (IFFUNC_ISISR (sym->type))
3000 if (!inExcludeList ("acc"))
3001 emitcode ("push", "acc");
3002 if (!inExcludeList ("b"))
3003 emitcode ("push", "b");
3004 if (!inExcludeList ("dpl"))
3005 emitcode ("push", "dpl");
3006 if (!inExcludeList ("dph"))
3007 emitcode ("push", "dph");
3008 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3010 emitcode ("push", "dpx");
3011 /* Make sure we're using standard DPTR */
3012 emitcode ("push", "dps");
3013 emitcode ("mov", "dps,#0");
3014 if (options.stack10bit)
3016 /* This ISR could conceivably use DPTR2. Better save it. */
3017 emitcode ("push", "dpl1");
3018 emitcode ("push", "dph1");
3019 emitcode ("push", "dpx1");
3020 emitcode ("push", DP2_RESULT_REG);
3023 /* if this isr has no bank i.e. is going to
3024 run with bank 0 , then we need to save more
3026 if (!FUNC_REGBANK (sym->type))
3030 /* if this function does not call any other
3031 function then we can be economical and
3032 save only those registers that are used */
3033 if (!IFFUNC_HASFCALL(sym->type))
3036 /* if any registers used */
3039 /* save the registers used */
3040 for (i = 0; i < sym->regsUsed->size; i++)
3042 if (bitVectBitValue (sym->regsUsed, i))
3043 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3049 /* this function has a function call cannot
3050 determines register usage so we will have to push the
3052 saveRBank (0, ic, FALSE);
3053 if (options.parms_in_bank1) {
3054 for (i=0; i < 8 ; i++ ) {
3055 emitcode ("push","%s",rb1regs[i]);
3062 /* This ISR uses a non-zero bank.
3064 * We assume that the bank is available for our
3067 * However, if this ISR calls a function which uses some
3068 * other bank, we must save that bank entirely.
3070 unsigned long banksToSave = 0;
3072 if (IFFUNC_HASFCALL(sym->type))
3075 #define MAX_REGISTER_BANKS 4
3080 for (i = ic; i; i = i->next)
3082 if (i->op == ENDFUNCTION)
3084 /* we got to the end OK. */
3092 dtype = operandType (IC_LEFT(i));
3094 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3096 /* Mark this bank for saving. */
3097 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3099 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3103 banksToSave |= (1 << FUNC_REGBANK(dtype));
3106 /* And note that we don't need to do it in
3114 /* This is a mess; we have no idea what
3115 * register bank the called function might
3118 * The only thing I can think of to do is
3119 * throw a warning and hope.
3121 werror(W_FUNCPTR_IN_USING_ISR);
3125 if (banksToSave && options.useXstack)
3127 /* Since we aren't passing it an ic,
3128 * saveRBank will assume r0 is available to abuse.
3130 * So switch to our (trashable) bank now, so
3131 * the caller's R0 isn't trashed.
3133 emitcode ("push", "psw");
3134 emitcode ("mov", "psw,#!constbyte",
3135 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3139 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3141 if (banksToSave & (1 << ix))
3143 saveRBank(ix, NULL, FALSE);
3147 // TODO: this needs a closer look
3148 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3153 /* if callee-save to be used for this function
3154 then save the registers being used in this function */
3155 if (IFFUNC_CALLEESAVES(sym->type))
3159 /* if any registers used */
3162 /* save the registers used */
3163 for (i = 0; i < sym->regsUsed->size; i++)
3165 if (bitVectBitValue (sym->regsUsed, i))
3167 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3175 /* set the register bank to the desired value */
3176 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3179 emitcode ("push", "psw");
3180 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3183 if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3184 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3185 if (options.stack10bit) {
3186 emitcode ("push","_bpx");
3187 emitcode ("push","_bpx+1");
3188 emitcode ("mov","_bpx,%s",spname);
3189 emitcode ("mov","_bpx+1,esp");
3190 adjustEsp("_bpx+1");
3192 if (options.useXstack) {
3193 emitcode ("mov", "r0,%s", spname);
3194 emitcode ("mov", "a,_bp");
3195 emitcode ("movx", "@r0,a");
3196 emitcode ("inc", "%s", spname);
3198 /* set up the stack */
3199 emitcode ("push", "_bp"); /* save the callers stack */
3201 emitcode ("mov", "_bp,%s", spname);
3205 /* adjust the stack for the function */
3208 if (options.stack10bit) {
3209 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3210 assert (sym->recvSize <= 4);
3211 if (sym->stack <= 8) {
3212 while (i--) emitcode ("push","acc");
3215 emitcode ("mov","a,sp");
3216 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3217 emitcode ("mov","sp,a");
3218 emitcode ("mov","a,esp");
3220 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3221 emitcode ("mov","esp,a");
3226 werror (W_STACK_OVERFLOW, sym->name);
3228 if (i > 3 && sym->recvSize < 4) {
3230 emitcode ("mov", "a,sp");
3231 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3232 emitcode ("mov", "sp,a");
3236 emitcode ("inc", "sp");
3243 emitcode ("mov", "a,_spx");
3244 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3245 emitcode ("mov", "_spx,a");
3248 /* if critical function then turn interrupts off */
3249 if (IFFUNC_ISCRITICAL (ftype))
3251 symbol *tlbl = newiTempLabel (NULL);
3252 emitcode ("setb", "c");
3253 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3254 emitcode ("clr", "c");
3255 emitcode ("", "%05d$:", (tlbl->key + 100));
3256 emitcode ("push", "psw"); /* save old ea via c in psw */
3261 /*-----------------------------------------------------------------*/
3262 /* genEndFunction - generates epilogue for functions */
3263 /*-----------------------------------------------------------------*/
3265 genEndFunction (iCode * ic)
3267 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3268 lineNode *lnp = lineCurr;
3270 bitVect *regsUsedPrologue;
3271 bitVect *regsUnneeded;
3274 D (emitcode (";", "genEndFunction "););
3276 if (IFFUNC_ISNAKED(sym->type))
3278 emitcode(";", "naked function: no epilogue.");
3279 if (options.debug && currFunc)
3280 debugFile->writeEndFunction (currFunc, ic, 0);
3284 if (IFFUNC_ISCRITICAL (sym->type))
3286 emitcode ("pop", "psw"); /* restore ea via c in psw */
3287 emitcode ("mov", "ea,c");
3290 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3291 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3293 if (options.stack10bit) {
3295 emitcode ("mov", "sp,_bpx", spname);
3296 emitcode ("mov", "esp,_bpx+1", spname);
3299 emitcode ("mov", "%s,_bp", spname);
3303 /* if use external stack but some variables were
3304 added to the local stack then decrement the
3306 if (options.useXstack && sym->stack) {
3307 emitcode ("mov", "a,sp");
3308 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3309 emitcode ("mov", "sp,a");
3313 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3314 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3316 if (options.useXstack) {
3317 emitcode ("mov", "r0,%s", spname);
3318 emitcode ("movx", "a,@r0");
3319 emitcode ("mov", "_bp,a");
3320 emitcode ("dec", "%s", spname);
3322 if (options.stack10bit) {
3323 emitcode ("pop", "_bpx+1");
3324 emitcode ("pop", "_bpx");
3326 emitcode ("pop", "_bp");
3331 /* restore the register bank */
3332 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3334 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3335 || !options.useXstack)
3337 /* Special case of ISR using non-zero bank with useXstack
3340 emitcode ("pop", "psw");
3344 if (IFFUNC_ISISR (sym->type))
3347 /* now we need to restore the registers */
3348 /* if this isr has no bank i.e. is going to
3349 run with bank 0 , then we need to save more
3351 if (!FUNC_REGBANK (sym->type))
3354 /* if this function does not call any other
3355 function then we can be economical and
3356 save only those registers that are used */
3357 if (!IFFUNC_HASFCALL(sym->type))
3360 /* if any registers used */
3363 /* save the registers used */
3364 for (i = sym->regsUsed->size; i >= 0; i--)
3366 if (bitVectBitValue (sym->regsUsed, i))
3367 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3373 /* this function has a function call cannot
3374 determines register usage so we will have to pop the
3376 if (options.parms_in_bank1) {
3377 for (i = 7 ; i >= 0 ; i-- ) {
3378 emitcode ("pop","%s",rb1regs[i]);
3381 unsaveRBank (0, ic, FALSE);
3386 /* This ISR uses a non-zero bank.
3388 * Restore any register banks saved by genFunction
3391 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3394 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3396 if (savedBanks & (1 << ix))
3398 unsaveRBank(ix, NULL, FALSE);
3402 if (options.useXstack)
3404 /* Restore bank AFTER calling unsaveRBank,
3405 * since it can trash r0.
3407 emitcode ("pop", "psw");
3411 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3413 if (options.stack10bit)
3415 emitcode ("pop", DP2_RESULT_REG);
3416 emitcode ("pop", "dpx1");
3417 emitcode ("pop", "dph1");
3418 emitcode ("pop", "dpl1");
3420 emitcode ("pop", "dps");
3421 emitcode ("pop", "dpx");
3423 if (!inExcludeList ("dph"))
3424 emitcode ("pop", "dph");
3425 if (!inExcludeList ("dpl"))
3426 emitcode ("pop", "dpl");
3427 if (!inExcludeList ("b"))
3428 emitcode ("pop", "b");
3429 if (!inExcludeList ("acc"))
3430 emitcode ("pop", "acc");
3432 /* if debug then send end of function */
3433 if (options.debug && currFunc) {
3434 debugFile->writeEndFunction (currFunc, ic, 1);
3437 emitcode ("reti", "");
3441 if (IFFUNC_CALLEESAVES(sym->type))
3445 /* if any registers used */
3448 /* save the registers used */
3449 for (i = sym->regsUsed->size; i >= 0; i--)
3451 if (bitVectBitValue (sym->regsUsed, i))
3452 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3457 /* if debug then send end of function */
3458 if (options.debug && currFunc)
3460 debugFile->writeEndFunction (currFunc, ic, 1);
3463 emitcode ("ret", "");
3466 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3469 /* If this was an interrupt handler using bank 0 that called another */
3470 /* function, then all registers must be saved; nothing to optimized. */
3471 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3472 && !FUNC_REGBANK(sym->type))
3475 /* There are no push/pops to optimize if not callee-saves or ISR */
3476 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3479 /* If there were stack parameters, we cannot optimize without also */
3480 /* fixing all of the stack offsets; this is too dificult to consider. */
3481 if (FUNC_HASSTACKPARM(sym->type))
3484 /* Compute the registers actually used */
3485 regsUsed = newBitVect (ds390_nRegs);
3486 regsUsedPrologue = newBitVect (ds390_nRegs);
3489 if (lnp->ic && lnp->ic->op == FUNCTION)
3490 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3492 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3494 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3495 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3502 if (bitVectBitValue (regsUsedPrologue, DPS_IDX)
3503 && !bitVectBitValue (regsUsed, DPS_IDX))
3505 bitVectUnSetBit (regsUsedPrologue, DPS_IDX);
3508 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3509 && !bitVectBitValue (regsUsed, CND_IDX))
3511 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3512 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3513 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3514 bitVectUnSetBit (regsUsed, CND_IDX);
3517 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3519 /* If this was an interrupt handler that called another function */
3520 /* function, then assume working registers may be modified by it. */
3521 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3523 regsUsed = bitVectSetBit (regsUsed, AP_IDX);
3524 regsUsed = bitVectSetBit (regsUsed, DPX1_IDX);
3525 regsUsed = bitVectSetBit (regsUsed, DPL1_IDX);
3526 regsUsed = bitVectSetBit (regsUsed, DPH1_IDX);
3527 regsUsed = bitVectSetBit (regsUsed, DPX_IDX);
3528 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3529 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3530 regsUsed = bitVectSetBit (regsUsed, DPS_IDX);
3531 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3532 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3533 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3536 /* Remove the unneeded push/pops */
3537 regsUnneeded = newBitVect (ds390_nRegs);
3540 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3542 if (!strncmp(lnp->line, "push", 4))
3544 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3545 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3547 connectLine (lnp->prev, lnp->next);
3548 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3551 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3553 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3554 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3556 connectLine (lnp->prev, lnp->next);
3557 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3564 for (idx = 0; idx < regsUnneeded->size; idx++)
3565 if (bitVectBitValue (regsUnneeded, idx))
3566 emitcode ("", ";\teliminated unneeded push/pop %s", ds390_regWithIdx (idx)->dname);
3568 freeBitVect (regsUnneeded);
3569 freeBitVect (regsUsed);
3570 freeBitVect (regsUsedPrologue);
3573 /*-----------------------------------------------------------------*/
3574 /* genJavaNativeRet - generate code for return JavaNative */
3575 /*-----------------------------------------------------------------*/
3576 static void genJavaNativeRet(iCode *ic)
3580 aopOp (IC_LEFT (ic), ic, FALSE,
3581 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3582 size = AOP_SIZE (IC_LEFT (ic));
3586 /* it is assigned to GPR0-R3 then push them */
3587 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3588 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3589 for (i = 0 ; i < size ; i++ ) {
3590 emitcode ("push","%s",
3591 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3593 for (i = (size-1) ; i >= 0 ; i--) {
3594 emitcode ("pop","a%s",javaRet[i]);
3597 for (i = 0 ; i < size ; i++)
3598 emitcode ("mov","%s,%s",javaRet[i],
3599 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3601 for (i = size ; i < 4 ; i++ )
3602 emitcode ("mov","%s,#0",javaRet[i]);
3606 /*-----------------------------------------------------------------*/
3607 /* genRet - generate code for return statement */
3608 /*-----------------------------------------------------------------*/
3612 int size, offset = 0, pushed = 0;
3614 D (emitcode (";", "genRet "););
3616 /* if we have no return value then
3617 just generate the "ret" */
3621 /* if this is a JavaNative function then return
3622 value in different register */
3623 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3624 genJavaNativeRet(ic);
3627 /* we have something to return then
3628 move the return value into place */
3629 aopOp (IC_LEFT (ic), ic, FALSE,
3630 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3631 size = AOP_SIZE (IC_LEFT (ic));
3633 _startLazyDPSEvaluation ();
3637 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3639 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3641 emitcode ("push", "%s", l);
3646 /* Since A is the last element of fReturn,
3647 * is is OK to clobber it in the aopGet.
3649 l = aopGet (AOP (IC_LEFT (ic)), offset,
3650 FALSE, FALSE, NULL);
3651 if (strcmp (fReturn[offset], l))
3652 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3655 _endLazyDPSEvaluation ();
3662 if (strcmp (fReturn[pushed], "a"))
3663 emitcode ("pop", fReturn[pushed]);
3665 emitcode ("pop", "acc");
3668 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3671 /* generate a jump to the return label
3672 if the next is not the return statement */
3673 if (!(ic->next && ic->next->op == LABEL &&
3674 IC_LABEL (ic->next) == returnLabel))
3676 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3680 /*-----------------------------------------------------------------*/
3681 /* genLabel - generates a label */
3682 /*-----------------------------------------------------------------*/
3684 genLabel (iCode * ic)
3686 /* special case never generate */
3687 if (IC_LABEL (ic) == entryLabel)
3690 D (emitcode (";", "genLabel ");
3693 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3696 /*-----------------------------------------------------------------*/
3697 /* genGoto - generates a ljmp */
3698 /*-----------------------------------------------------------------*/
3700 genGoto (iCode * ic)
3702 D (emitcode (";", "genGoto ");
3704 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3707 /*-----------------------------------------------------------------*/
3708 /* findLabelBackwards: walks back through the iCode chain looking */
3709 /* for the given label. Returns number of iCode instructions */
3710 /* between that label and given ic. */
3711 /* Returns zero if label not found. */
3712 /*-----------------------------------------------------------------*/
3714 findLabelBackwards (iCode * ic, int key)
3723 /* If we have any pushes or pops, we cannot predict the distance.
3724 I don't like this at all, this should be dealt with in the
3726 if (ic->op == IPUSH || ic->op == IPOP) {
3730 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3732 /* printf("findLabelBackwards = %d\n", count); */
3740 /*-----------------------------------------------------------------*/
3741 /* genPlusIncr :- does addition with increment if possible */
3742 /*-----------------------------------------------------------------*/
3744 genPlusIncr (iCode * ic)
3746 unsigned int icount;
3747 unsigned int size = getDataSize (IC_RESULT (ic));
3749 /* will try to generate an increment */
3750 /* if the right side is not a literal
3752 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3755 /* if the literal value of the right hand side
3756 is greater than 4 then it is not worth it */
3757 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3760 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3761 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3763 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3767 /* if increment 16 bits in register */
3769 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3770 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3771 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3780 /* If the next instruction is a goto and the goto target
3781 * is <= 5 instructions previous to this, we can generate
3782 * jumps straight to that target.
3784 if (ic->next && ic->next->op == GOTO
3785 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3788 D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3789 tlbl = IC_LABEL (ic->next);
3794 tlbl = newiTempLabel (NULL);
3798 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3799 emitcode ("inc", "%s", l);
3801 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3802 IS_AOP_PREG (IC_RESULT (ic)))
3804 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3808 emitcode ("clr", "a");
3809 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3812 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
3813 emitcode ("inc", "%s", l);
3816 if (!strcmp(l, "acc"))
3818 emitcode("jnz", "!tlabel", tlbl->key + 100);
3820 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3821 IS_AOP_PREG (IC_RESULT (ic)))
3823 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3827 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3830 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3831 emitcode ("inc", "%s", l);
3835 if (!strcmp(l, "acc"))
3837 emitcode("jnz", "!tlabel", tlbl->key + 100);
3839 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3840 IS_AOP_PREG (IC_RESULT (ic)))
3842 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3846 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3849 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3850 emitcode ("inc", "%s", l);
3855 emitcode ("", "!tlabeldef", tlbl->key + 100);
3860 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3861 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
3862 options.model == MODEL_FLAT24 )
3864 if (IC_RESULT(ic)->isGptr)
3866 emitcode ("mov","b,%s",aopGet(AOP (IC_LEFT (ic)), 3, FALSE, FALSE, NULL));
3870 emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3872 emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3874 emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3877 while (icount--) emitcode ("inc","dptr");
3881 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3882 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3884 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3885 while (icount--) emitcode ("inc","dptr");
3886 emitcode ("mov","dps,#0");
3890 /* if the sizes are greater than 1 then we cannot */
3891 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3892 AOP_SIZE (IC_LEFT (ic)) > 1)
3895 /* we can if the aops of the left & result match or
3896 if they are in registers and the registers are the
3899 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3900 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3901 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3906 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3907 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3908 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3913 _startLazyDPSEvaluation ();
3916 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3918 _endLazyDPSEvaluation ();
3927 /*-----------------------------------------------------------------*/
3928 /* outBitAcc - output a bit in acc */
3929 /*-----------------------------------------------------------------*/
3931 outBitAcc (operand * result)
3933 symbol *tlbl = newiTempLabel (NULL);
3934 /* if the result is a bit */
3935 if (AOP_TYPE (result) == AOP_CRY)
3937 aopPut (AOP (result), "a", 0);
3941 emitcode ("jz", "!tlabel", tlbl->key + 100);
3942 emitcode ("mov", "a,%s", one);
3943 emitcode ("", "!tlabeldef", tlbl->key + 100);
3948 /*-----------------------------------------------------------------*/
3949 /* genPlusBits - generates code for addition of two bits */
3950 /*-----------------------------------------------------------------*/
3952 genPlusBits (iCode * ic)
3954 D (emitcode (";", "genPlusBits "););
3956 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3958 symbol *lbl = newiTempLabel (NULL);
3959 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3960 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3961 emitcode ("cpl", "c");
3962 emitcode ("", "!tlabeldef", (lbl->key + 100));
3963 outBitC (IC_RESULT (ic));
3967 emitcode ("clr", "a");
3968 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3969 emitcode ("rlc", "a");
3970 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3971 emitcode ("addc", "a,#0");
3972 outAcc (IC_RESULT (ic));
3977 adjustArithmeticResult (iCode * ic)
3979 if (opIsGptr (IC_RESULT (ic)) &&
3980 opIsGptr (IC_LEFT (ic)) &&
3981 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3983 aopPut (AOP (IC_RESULT (ic)),
3984 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3988 if (opIsGptr (IC_RESULT (ic)) &&
3989 opIsGptr (IC_RIGHT (ic)) &&
3990 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3992 aopPut (AOP (IC_RESULT (ic)),
3993 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3997 if (opIsGptr (IC_RESULT (ic)) &&
3998 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3999 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4000 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4001 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4004 SNPRINTF (buff, sizeof(buff),
4005 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4006 aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
4010 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
4011 // generates the result if possible. If result is generated, returns TRUE; otherwise
4012 // returns false and caller must deal with fact that result isn't aopOp'd.
4013 bool aopOp3(iCode * ic)
4015 bool dp1InUse, dp2InUse;
4018 // First, generate the right opcode. DPTR may be used if neither left nor result are
4021 // D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
4022 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
4023 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
4024 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
4026 // D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
4027 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
4028 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
4029 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
4032 // Right uses DPTR unless left or result is an AOP_STR; however,
4033 // if right is an AOP_STR, it must use DPTR regardless.
4034 if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
4035 && !AOP_IS_STR(IC_RIGHT(ic)))
4044 aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
4046 // if the right used DPTR, left MUST use DPTR2.
4047 // if the right used DPTR2, left MUST use DPTR.
4048 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
4049 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
4050 // enabling us to assign DPTR to result.
4052 if (AOP_USESDPTR(IC_RIGHT(ic)))
4056 else if (AOP_USESDPTR2(IC_RIGHT(ic)))
4062 if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
4072 aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
4075 // We've op'd the left & right. So, if left or right are the same operand as result,
4076 // we know aopOp will succeed, and we can just do it & bail.
4077 if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))
4079 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4082 if (isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
4084 // D(emitcode(";", "aopOp3: (left | right) & result equal"););
4085 aopOp(IC_RESULT(ic),ic,TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4089 // Operands may be equivalent (but not equal) if they share a spill location. If
4090 // so, use the same DPTR or DPTR2.
4091 if (operandsEqu (IC_LEFT(ic), IC_RESULT(ic)))
4093 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4096 if (operandsEqu (IC_RIGHT(ic), IC_RESULT(ic)))
4098 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4102 // Note which dptrs are currently in use.
4103 dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
4104 dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
4106 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
4108 if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
4113 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
4114 if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
4119 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
4120 if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
4125 aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
4127 // Some sanity checking...
4128 if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
4131 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
4132 __FILE__, __LINE__, ic->filename, ic->lineno);
4133 emitcode(";", ">>> unexpected DPTR here.");
4136 if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
4139 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
4140 __FILE__, __LINE__, ic->filename, ic->lineno);
4141 emitcode(";", ">>> unexpected DPTR2 here.");
4147 // Macro to aopOp all three operands of an ic. If this cannot be done,
4148 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
4149 // will be set TRUE. The caller must then handle the case specially, noting
4150 // that the IC_RESULT operand is not aopOp'd.
4152 #define AOP_OP_3_NOFATAL(ic, rc) \
4153 do { rc = !aopOp3(ic); } while (0)
4155 // aopOp the left & right operands of an ic.
4156 #define AOP_OP_2(ic) \
4157 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
4158 aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
4160 // convienience macro.
4161 #define AOP_SET_LOCALS(ic) \
4162 left = IC_LEFT(ic); \
4163 right = IC_RIGHT(ic); \
4164 result = IC_RESULT(ic);
4167 // Given an integer value of pushedSize bytes on the stack,
4168 // adjust it to be resultSize bytes, either by discarding
4169 // the most significant bytes or by zero-padding.
4171 // On exit from this macro, pushedSize will have been adjusted to
4172 // equal resultSize, and ACC may be trashed.
4173 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
4174 /* If the pushed data is bigger than the result, \
4175 * simply discard unused bytes. Icky, but works. \
4177 while (pushedSize > resultSize) \
4179 D (emitcode (";", "discarding unused result byte."););\
4180 emitcode ("pop", "acc"); \
4183 if (pushedSize < resultSize) \
4185 emitcode ("clr", "a"); \
4186 /* Conversly, we haven't pushed enough here. \
4187 * just zero-pad, and all is well. \
4189 while (pushedSize < resultSize) \
4191 emitcode("push", "acc"); \
4195 assert(pushedSize == resultSize);
4197 /*-----------------------------------------------------------------*/
4198 /* genPlus - generates code for addition */
4199 /*-----------------------------------------------------------------*/
4201 genPlus (iCode * ic)
4203 int size, offset = 0;
4207 D (emitcode (";", "genPlus "););
4209 /* special cases :- */
4210 if ( AOP_IS_STR(IC_LEFT(ic)) &&
4211 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4212 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4213 size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4215 while (size--) emitcode ("inc","dptr");
4217 emitcode ("mov","a,dpl");
4218 emitcode ("add","a,#!constbyte",size & 0xff);
4219 emitcode ("mov","dpl,a");
4220 emitcode ("mov","a,dph");
4221 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4222 emitcode ("mov","dph,a");
4223 emitcode ("mov","a,dpx");
4224 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4225 emitcode ("mov","dpx,a");
4227 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4230 if ( IS_SYMOP(IC_LEFT(ic)) &&
4231 OP_SYMBOL(IC_LEFT(ic))->remat &&
4232 isOperandInFarSpace(IC_RIGHT(ic))) {
4233 operand *op = IC_RIGHT(ic);
4234 IC_RIGHT(ic) = IC_LEFT(ic);
4238 AOP_OP_3_NOFATAL (ic, pushResult);
4242 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4247 /* if literal, literal on the right or
4248 if left requires ACC or right is already
4250 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4251 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4252 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4254 operand *t = IC_RIGHT (ic);
4255 IC_RIGHT (ic) = IC_LEFT (ic);
4257 emitcode (";", "Swapped plus args.");
4260 /* if both left & right are in bit
4262 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4263 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4269 /* if left in bit space & right literal */
4270 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4271 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4273 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4274 /* if result in bit space */
4275 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4277 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4278 emitcode ("cpl", "c");
4279 outBitC (IC_RESULT (ic));
4283 size = getDataSize (IC_RESULT (ic));
4284 _startLazyDPSEvaluation ();
4287 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4288 emitcode ("addc", "a,#0");
4289 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4291 _endLazyDPSEvaluation ();
4296 /* if I can do an increment instead
4297 of add then GOOD for ME */
4298 if (genPlusIncr (ic) == TRUE)
4300 emitcode (";", "did genPlusIncr");
4305 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4307 _startLazyDPSEvaluation ();
4310 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4312 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4314 emitcode ("add", "a,%s",
4315 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4317 emitcode ("addc", "a,%s",
4318 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4322 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4324 /* right is going to use ACC or we would have taken the
4327 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4329 D(emitcode(";", "+ AOP_ACC special case."););
4330 emitcode("xch", "a, %s", DP2_RESULT_REG);
4332 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4335 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4338 emitcode("add", "a, %s", DP2_RESULT_REG);
4342 emitcode ("add", "a,%s",
4343 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4349 emitcode ("addc", "a,%s",
4350 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4356 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4360 emitcode ("push", "acc");
4364 _endLazyDPSEvaluation ();
4368 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4370 size = getDataSize (IC_LEFT (ic));
4371 rSize = getDataSize (IC_RESULT (ic));
4373 ADJUST_PUSHED_RESULT(size, rSize);
4375 _startLazyDPSEvaluation ();
4378 emitcode ("pop", "acc");
4379 aopPut (AOP (IC_RESULT (ic)), "a", size);
4381 _endLazyDPSEvaluation ();
4384 adjustArithmeticResult (ic);
4387 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4388 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4389 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4392 /*-----------------------------------------------------------------*/
4393 /* genMinusDec :- does subtraction with deccrement if possible */
4394 /*-----------------------------------------------------------------*/
4396 genMinusDec (iCode * ic)
4398 unsigned int icount;
4399 unsigned int size = getDataSize (IC_RESULT (ic));
4401 /* will try to generate an increment */
4402 /* if the right side is not a literal
4404 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4407 /* if the literal value of the right hand side
4408 is greater than 4 then it is not worth it */
4409 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4412 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4413 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4415 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4419 /* if decrement 16 bits in register */
4420 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4421 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4422 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4431 /* If the next instruction is a goto and the goto target
4432 * is <= 5 instructions previous to this, we can generate
4433 * jumps straight to that target.
4435 if (ic->next && ic->next->op == GOTO
4436 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4439 emitcode (";", "tail decrement optimized (range %d)", labelRange);
4440 tlbl = IC_LABEL (ic->next);
4445 tlbl = newiTempLabel (NULL);
4449 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4450 emitcode ("dec", "%s", l);
4452 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4453 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4454 IS_AOP_PREG (IC_RESULT (ic)))
4456 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4460 emitcode ("mov", "a,#!constbyte",0xff);
4461 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4463 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4464 emitcode ("dec", "%s", l);
4467 if (!strcmp(l, "acc"))
4469 emitcode("jnz", "!tlabel", tlbl->key + 100);
4471 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4472 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4473 IS_AOP_PREG (IC_RESULT (ic)))
4475 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4479 emitcode ("mov", "a,#!constbyte",0xff);
4480 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4482 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4483 emitcode ("dec", "%s", l);
4487 if (!strcmp(l, "acc"))
4489 emitcode("jnz", "!tlabel", tlbl->key + 100);
4491 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4492 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4493 IS_AOP_PREG (IC_RESULT (ic)))
4495 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4499 emitcode ("mov", "a,#!constbyte",0xff);
4500 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4502 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4503 emitcode ("dec", "%s", l);
4507 emitcode ("", "!tlabeldef", tlbl->key + 100);
4512 /* if the sizes are greater than 1 then we cannot */
4513 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4514 AOP_SIZE (IC_LEFT (ic)) > 1)
4517 /* we can if the aops of the left & result match or
4518 if they are in registers and the registers are the
4521 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4522 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4523 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4526 _startLazyDPSEvaluation ();
4529 emitcode ("dec", "%s",
4530 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4532 _endLazyDPSEvaluation ();
4540 /*-----------------------------------------------------------------*/
4541 /* addSign - complete with sign */
4542 /*-----------------------------------------------------------------*/
4544 addSign (operand * result, int offset, int sign)
4546 int size = (getDataSize (result) - offset);
4549 _startLazyDPSEvaluation();
4552 emitcode ("rlc", "a");
4553 emitcode ("subb", "a,acc");
4556 aopPut (AOP (result), "a", offset++);
4563 aopPut (AOP (result), zero, offset++);
4566 _endLazyDPSEvaluation();
4570 /*-----------------------------------------------------------------*/
4571 /* genMinusBits - generates code for subtraction of two bits */
4572 /*-----------------------------------------------------------------*/
4574 genMinusBits (iCode * ic)
4576 symbol *lbl = newiTempLabel (NULL);
4578 D (emitcode (";", "genMinusBits "););
4580 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4582 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4583 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4584 emitcode ("cpl", "c");
4585 emitcode ("", "!tlabeldef", (lbl->key + 100));
4586 outBitC (IC_RESULT (ic));
4590 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4591 emitcode ("subb", "a,acc");
4592 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4593 emitcode ("inc", "a");
4594 emitcode ("", "!tlabeldef", (lbl->key + 100));
4595 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4596 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4600 /*-----------------------------------------------------------------*/
4601 /* genMinus - generates code for subtraction */
4602 /*-----------------------------------------------------------------*/
4604 genMinus (iCode * ic)
4606 int size, offset = 0;
4611 D (emitcode (";", "genMinus "););
4613 AOP_OP_3_NOFATAL(ic, pushResult);
4617 /* special cases :- */
4618 /* if both left & right are in bit space */
4619 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4620 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4626 /* if I can do an decrement instead
4627 of subtract then GOOD for ME */
4628 if (genMinusDec (ic) == TRUE)
4633 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4635 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4641 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4646 /* if literal, add a,#-lit, else normal subb */
4647 _startLazyDPSEvaluation ();
4649 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4650 if (AOP_USESDPTR(IC_RIGHT(ic))) {
4651 emitcode ("mov","b,%s",
4652 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4653 MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4654 emitcode ("subb","a,b");
4656 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4657 emitcode ("subb", "a,%s",
4658 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE,
4662 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4663 /* first add without previous c */
4665 if (!size && lit==-1) {
4666 emitcode ("dec", "a");
4668 emitcode ("add", "a,#!constbyte",
4669 (unsigned int) (lit & 0x0FFL));
4672 emitcode ("addc", "a,#!constbyte",
4673 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4678 emitcode ("push", "acc");
4680 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4684 _endLazyDPSEvaluation ();
4688 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4690 size = getDataSize (IC_LEFT (ic));
4691 rSize = getDataSize (IC_RESULT (ic));
4693 ADJUST_PUSHED_RESULT(size, rSize);
4695 _startLazyDPSEvaluation ();
4698 emitcode ("pop", "acc");
4699 aopPut (AOP (IC_RESULT (ic)), "a", size);
4701 _endLazyDPSEvaluation ();
4704 adjustArithmeticResult (ic);
4707 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4708 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4709 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4713 /*-----------------------------------------------------------------*/
4714 /* genMultbits :- multiplication of bits */
4715 /*-----------------------------------------------------------------*/
4717 genMultbits (operand * left,
4722 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4723 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4724 aopOp(result, ic, TRUE, FALSE);
4729 /*-----------------------------------------------------------------*/
4730 /* genMultOneByte : 8*8=8/16 bit multiplication */
4731 /*-----------------------------------------------------------------*/
4733 genMultOneByte (operand * left,
4740 bool runtimeSign, compiletimeSign;
4741 bool lUnsigned, rUnsigned;
4744 /* (if two literals: the value is computed before) */
4745 /* if one literal, literal on the right */
4746 if (AOP_TYPE (left) == AOP_LIT)
4751 emitcode (";", "swapped left and right");
4754 /* (if two literals: the value is computed before) */
4755 /* if one literal, literal on the right */
4756 if (AOP_TYPE (left) == AOP_LIT)
4761 /* emitcode (";", "swapped left and right"); */
4763 /* if no literal, unsigned on the right: shorter code */
4764 if ( AOP_TYPE (right) != AOP_LIT
4765 && SPEC_USIGN (getSpec (operandType (left))))
4772 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4773 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4775 if ((lUnsigned && rUnsigned)
4776 /* sorry, I don't know how to get size
4777 without calling aopOp (result,...);
4778 see Feature Request */
4779 /* || size == 1 */ ) /* no, this is not a bug; with a 1 byte result there's
4780 no need to take care about the signedness! */
4782 /* just an unsigned 8 * 8 = 8 multiply
4784 /* emitcode (";","unsigned"); */
4785 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4786 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4787 emitcode ("mul", "ab");
4789 _G.accInUse++; _G.bInUse++;
4790 aopOp (result, ic, TRUE, FALSE);
4791 size = AOP_SIZE (result);
4793 if (size < 1 || size > 2)
4795 /* this should never happen */
4796 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4797 size, __FILE__, lineno);
4801 aopPut (AOP (result), "a", 0);
4802 _G.accInUse--; _G.bInUse--;
4804 aopPut (AOP (result), "b", 1);
4808 /* we have to do a signed multiply */
4809 /* emitcode (";", "signed"); */
4811 /* now sign adjust for both left & right */
4813 /* let's see what's needed: */
4814 /* apply negative sign during runtime */
4815 runtimeSign = FALSE;
4816 /* negative sign from literals */
4817 compiletimeSign = FALSE;
4821 if (AOP_TYPE(left) == AOP_LIT)
4823 /* signed literal */
4824 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4826 compiletimeSign = TRUE;
4829 /* signed but not literal */
4835 if (AOP_TYPE(right) == AOP_LIT)
4837 /* signed literal */
4838 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4840 compiletimeSign ^= TRUE;
4843 /* signed but not literal */
4847 /* initialize F0, which stores the runtime sign */
4850 if (compiletimeSign)
4851 emitcode ("setb", "F0"); /* set sign flag */
4853 emitcode ("clr", "F0"); /* reset sign flag */
4856 /* save the signs of the operands */
4857 if (AOP_TYPE(right) == AOP_LIT)
4859 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4861 if (!rUnsigned && val < 0)
4862 emitcode ("mov", "b,#!constbyte", -val);
4864 emitcode ("mov", "b,#!constbyte", (unsigned char) val);
4866 else /* ! literal */
4868 if (rUnsigned) /* emitcode (";", "signed"); */
4869 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4872 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4873 lbl = newiTempLabel (NULL);
4874 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
4875 emitcode ("cpl", "F0"); /* complement sign flag */
4876 emitcode ("cpl", "a"); /* 2's complement */
4877 emitcode ("inc", "a");
4878 emitcode ("", "!tlabeldef", lbl->key + 100);
4879 emitcode ("mov", "b,a");
4883 if (AOP_TYPE(left) == AOP_LIT)
4885 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4887 if (!lUnsigned && val < 0)
4888 emitcode ("mov", "a,#!constbyte", -val);
4890 emitcode ("mov", "a,#!constbyte", (unsigned char) val);
4892 else /* ! literal */
4894 if (lUnsigned) /* emitcode (";", "signed"); */
4896 emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4899 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4900 lbl = newiTempLabel (NULL);
4901 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
4902 emitcode ("cpl", "F0"); /* complement sign flag */
4903 emitcode ("cpl", "a"); /* 2's complement */
4904 emitcode ("inc", "a");
4905 emitcode ("", "!tlabeldef", lbl->key + 100);
4909 /* now the multiplication */
4910 emitcode ("mul", "ab");
4911 _G.accInUse++;_G.bInUse++;
4912 aopOp(result, ic, TRUE, FALSE);
4913 size = AOP_SIZE (result);
4915 if (size < 1 || size > 2)
4917 /* this should never happen */
4918 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4919 size, __FILE__, lineno);
4923 if (runtimeSign || compiletimeSign)
4925 lbl = newiTempLabel (NULL);
4927 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
4928 emitcode ("cpl", "a"); /* lsb 2's complement */
4930 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4933 emitcode ("add", "a,#1"); /* this sets carry flag */
4934 emitcode ("xch", "a,b");
4935 emitcode ("cpl", "a"); /* msb 2's complement */
4936 emitcode ("addc", "a,#0");
4937 emitcode ("xch", "a,b");
4939 emitcode ("", "!tlabeldef", lbl->key + 100);
4941 aopPut (AOP (result), "a", 0);
4942 _G.accInUse--;_G.bInUse--;
4944 aopPut (AOP (result), "b", 1);
4947 /*-----------------------------------------------------------------*/
4948 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4949 /*-----------------------------------------------------------------*/
4950 static void genMultTwoByte (operand *left, operand *right,
4951 operand *result, iCode *ic)
4953 sym_link *retype = getSpec(operandType(right));
4954 sym_link *letype = getSpec(operandType(left));
4955 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4958 if (AOP_TYPE (left) == AOP_LIT) {
4963 /* save EA bit in F1 */
4964 lbl = newiTempLabel(NULL);
4965 emitcode ("setb","F1");
4966 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4967 emitcode ("clr","F1");
4968 emitcode("","!tlabeldef",lbl->key+100);
4970 /* load up MB with right */
4972 emitcode("clr","F0");
4973 if (AOP_TYPE(right) == AOP_LIT) {
4974 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4976 emitcode("setb","F0");
4979 emitcode ("mov","mb,#!constbyte",val & 0xff);
4980 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4982 lbl = newiTempLabel(NULL);
4983 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4984 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4985 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4986 emitcode ("xch", "a,b");
4987 emitcode ("cpl","a");
4988 emitcode ("add", "a,#1");
4989 emitcode ("xch", "a,b");
4990 emitcode ("cpl", "a"); // msb
4991 emitcode ("addc", "a,#0");
4992 emitcode ("setb","F0");
4993 emitcode ("","!tlabeldef",lbl->key+100);
4994 emitcode ("mov","mb,b");
4995 emitcode ("mov","mb,a");
4998 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4999 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5001 /* load up MA with left */
5003 lbl = newiTempLabel(NULL);
5004 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5005 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5006 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5007 emitcode ("xch", "a,b");
5008 emitcode ("cpl","a");
5009 emitcode ("add", "a,#1");
5010 emitcode ("xch", "a,b");
5011 emitcode ("cpl", "a"); // msb
5012 emitcode ("addc","a,#0");
5013 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5014 emitcode ("setb","F0");
5015 emitcode ("","!tlabeldef",lbl->key+100);
5016 emitcode ("mov","ma,b");
5017 emitcode ("mov","ma,a");
5019 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5020 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5022 /* wait for multiplication to finish */
5023 lbl = newiTempLabel(NULL);
5024 emitcode("","!tlabeldef", lbl->key+100);
5025 emitcode("mov","a,mcnt1");
5026 emitcode("anl","a,#!constbyte",0x80);
5027 emitcode("jnz","!tlabel",lbl->key+100);
5029 freeAsmop (left, NULL, ic, TRUE);
5030 freeAsmop (right, NULL, ic,TRUE);
5031 aopOp(result, ic, TRUE, FALSE);
5033 /* if unsigned then simple */
5035 emitcode ("mov","a,ma");
5036 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
5037 emitcode ("mov","a,ma");
5038 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
5039 aopPut(AOP(result),"ma",1);
5040 aopPut(AOP(result),"ma",0);
5042 emitcode("push","ma");
5043 emitcode("push","ma");
5044 emitcode("push","ma");
5046 /* negate result if needed */
5047 lbl = newiTempLabel(NULL);
5048 emitcode("jnb","F0,!tlabel",lbl->key+100);
5049 emitcode("cpl","a");
5050 emitcode("add","a,#1");
5051 emitcode("","!tlabeldef", lbl->key+100);
5052 if (AOP_TYPE(result) == AOP_ACC)
5054 D(emitcode(";", "ACC special case."););
5055 /* We know result is the only live aop, and
5056 * it's obviously not a DPTR2, so AP is available.
5058 emitcode("mov", "%s,acc", DP2_RESULT_REG);
5062 aopPut(AOP(result),"a",0);
5065 emitcode("pop","acc");
5066 lbl = newiTempLabel(NULL);
5067 emitcode("jnb","F0,!tlabel",lbl->key+100);
5068 emitcode("cpl","a");
5069 emitcode("addc","a,#0");
5070 emitcode("","!tlabeldef", lbl->key+100);
5071 aopPut(AOP(result),"a",1);
5072 emitcode("pop","acc");
5073 if (AOP_SIZE(result) >= 3) {
5074 lbl = newiTempLabel(NULL);
5075 emitcode("jnb","F0,!tlabel",lbl->key+100);
5076 emitcode("cpl","a");
5077 emitcode("addc","a,#0");
5078 emitcode("","!tlabeldef", lbl->key+100);
5079 aopPut(AOP(result),"a",2);
5081 emitcode("pop","acc");
5082 if (AOP_SIZE(result) >= 4) {
5083 lbl = newiTempLabel(NULL);
5084 emitcode("jnb","F0,!tlabel",lbl->key+100);
5085 emitcode("cpl","a");
5086 emitcode("addc","a,#0");
5087 emitcode("","!tlabeldef", lbl->key+100);
5088 aopPut(AOP(result),"a",3);
5090 if (AOP_TYPE(result) == AOP_ACC)
5092 /* We stashed the result away above. */
5093 emitcode("mov", "acc,%s", DP2_RESULT_REG);
5097 freeAsmop (result, NULL, ic, TRUE);
5099 /* restore EA bit in F1 */
5100 lbl = newiTempLabel(NULL);
5101 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5102 emitcode ("setb","EA");
5103 emitcode("","!tlabeldef",lbl->key+100);
5107 /*-----------------------------------------------------------------*/
5108 /* genMult - generates code for multiplication */
5109 /*-----------------------------------------------------------------*/
5111 genMult (iCode * ic)
5113 operand *left = IC_LEFT (ic);
5114 operand *right = IC_RIGHT (ic);
5115 operand *result = IC_RESULT (ic);
5117 D (emitcode (";", "genMult "););
5119 /* assign the amsops */
5122 /* special cases first */
5124 if (AOP_TYPE (left) == AOP_CRY &&
5125 AOP_TYPE (right) == AOP_CRY)
5127 genMultbits (left, right, result, ic);
5131 /* if both are of size == 1 */
5132 if (AOP_SIZE (left) == 1 &&
5133 AOP_SIZE (right) == 1)
5135 genMultOneByte (left, right, result, ic);
5139 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5140 /* use the ds390 ARITHMETIC accel UNIT */
5141 genMultTwoByte (left, right, result, ic);
5144 /* should have been converted to function call */
5148 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5149 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5150 freeAsmop (result, NULL, ic, TRUE);
5153 /*-----------------------------------------------------------------*/
5154 /* genDivbits :- division of bits */
5155 /*-----------------------------------------------------------------*/
5157 genDivbits (operand * left,
5165 /* the result must be bit */
5166 LOAD_AB_FOR_DIV (left, right, l);
5167 emitcode ("div", "ab");
5168 emitcode ("rrc", "a");
5169 aopOp(result, ic, TRUE, FALSE);
5171 aopPut (AOP (result), "c", 0);
5174 /*-----------------------------------------------------------------*/
5175 /* genDivOneByte : 8 bit division */
5176 /*-----------------------------------------------------------------*/
5178 genDivOneByte (operand * left,
5183 bool lUnsigned, rUnsigned;
5184 bool runtimeSign, compiletimeSign;
5190 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5191 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5193 /* signed or unsigned */
5194 if (lUnsigned && rUnsigned)
5196 /* unsigned is easy */
5197 LOAD_AB_FOR_DIV (left, right, l);
5198 emitcode ("div", "ab");
5201 aopOp (result, ic, TRUE, FALSE);
5202 aopPut (AOP (result), "a", 0);
5205 size = AOP_SIZE (result) - 1;
5208 aopPut (AOP (result), zero, offset++);
5212 /* signed is a little bit more difficult */
5214 /* now sign adjust for both left & right */
5216 /* let's see what's needed: */
5217 /* apply negative sign during runtime */
5218 runtimeSign = FALSE;
5219 /* negative sign from literals */
5220 compiletimeSign = FALSE;
5224 if (AOP_TYPE(left) == AOP_LIT)
5226 /* signed literal */
5227 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5229 compiletimeSign = TRUE;
5232 /* signed but not literal */
5238 if (AOP_TYPE(right) == AOP_LIT)
5240 /* signed literal */
5241 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5243 compiletimeSign ^= TRUE;
5246 /* signed but not literal */
5250 /* initialize F0, which stores the runtime sign */
5253 if (compiletimeSign)
5254 emitcode ("setb", "F0"); /* set sign flag */
5256 emitcode ("clr", "F0"); /* reset sign flag */
5259 /* save the signs of the operands */
5260 if (AOP_TYPE(right) == AOP_LIT)
5262 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5264 if (!rUnsigned && val < 0)
5265 emitcode ("mov", "b,#0x%02x", -val);
5267 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5269 else /* ! literal */
5272 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5275 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5276 lbl = newiTempLabel (NULL);
5277 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5278 emitcode ("cpl", "F0"); /* complement sign flag */
5279 emitcode ("cpl", "a"); /* 2's complement */
5280 emitcode ("inc", "a");
5281 emitcode ("", "!tlabeldef", lbl->key + 100);
5282 emitcode ("mov", "b,a");
5286 if (AOP_TYPE(left) == AOP_LIT)
5288 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5290 if (!lUnsigned && val < 0)
5291 emitcode ("mov", "a,#0x%02x", -val);
5293 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5295 else /* ! literal */
5298 emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5301 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5302 lbl = newiTempLabel (NULL);
5303 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5304 emitcode ("cpl", "F0"); /* complement sign flag */
5305 emitcode ("cpl", "a"); /* 2's complement */
5306 emitcode ("inc", "a");
5307 emitcode ("", "!tlabeldef", lbl->key + 100);
5311 /* now the division */
5312 emitcode ("nop", "; workaround for DS80C390 div bug.");
5313 emitcode ("div", "ab");
5315 if (runtimeSign || compiletimeSign)
5317 lbl = newiTempLabel (NULL);
5319 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5320 emitcode ("cpl", "a"); /* lsb 2's complement */
5321 emitcode ("inc", "a");
5322 emitcode ("", "!tlabeldef", lbl->key + 100);
5324 _G.accInUse++; _G.bInUse++;
5325 aopOp (result, ic, TRUE, FALSE);
5326 size = AOP_SIZE (result) - 1;
5330 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5331 then the result will be in b, a */
5332 emitcode ("mov", "b,a"); /* 1 */
5333 /* msb is 0x00 or 0xff depending on the sign */
5336 emitcode ("mov", "c,F0");
5337 emitcode ("subb", "a,acc");
5338 emitcode ("xch", "a,b"); /* 2 */
5340 aopPut (AOP (result), "b", offset++); /* write msb's */
5342 else /* compiletimeSign */
5344 aopPut (AOP (result), "#0xff", offset++); /* write msb's */
5346 aopPut (AOP (result), "a", 0); /* 3: write lsb */
5350 _G.accInUse++; _G.bInUse++;
5351 aopOp(result, ic, TRUE, FALSE);
5352 size = AOP_SIZE (result) - 1;
5354 aopPut (AOP (result), "a", 0);
5356 aopPut (AOP (result), zero, offset++);
5358 _G.accInUse--; _G.bInUse--;
5362 /*-----------------------------------------------------------------*/
5363 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
5364 /*-----------------------------------------------------------------*/
5365 static void genDivTwoByte (operand *left, operand *right,
5366 operand *result, iCode *ic)
5368 sym_link *retype = getSpec(operandType(right));
5369 sym_link *letype = getSpec(operandType(left));
5370 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5373 /* save EA bit in F1 */
5374 lbl = newiTempLabel(NULL);
5375 emitcode ("setb","F1");
5376 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5377 emitcode ("clr","F1");
5378 emitcode("","!tlabeldef",lbl->key+100);
5380 /* load up MA with left */
5382 emitcode("clr","F0");
5383 lbl = newiTempLabel(NULL);
5384 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5385 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5386 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5387 emitcode ("xch", "a,b");
5388 emitcode ("cpl","a");
5389 emitcode ("add", "a,#1");
5390 emitcode ("xch", "a,b");
5391 emitcode ("cpl", "a"); // msb
5392 emitcode ("addc","a,#0");
5393 emitcode ("setb","F0");
5394 emitcode ("","!tlabeldef",lbl->key+100);
5395 emitcode ("mov","ma,b");
5396 emitcode ("mov","ma,a");
5398 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5399 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5402 /* load up MB with right */
5404 if (AOP_TYPE(right) == AOP_LIT) {
5405 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5407 lbl = newiTempLabel(NULL);
5408 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5409 emitcode("setb","F0");
5410 emitcode ("","!tlabeldef",lbl->key+100);
5413 emitcode ("mov","mb,#!constbyte",val & 0xff);
5414 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5416 lbl = newiTempLabel(NULL);
5417 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5418 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5419 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5420 emitcode ("xch", "a,b");
5421 emitcode ("cpl","a");
5422 emitcode ("add", "a,#1");
5423 emitcode ("xch", "a,b");
5424 emitcode ("cpl", "a"); // msb
5425 emitcode ("addc", "a,#0");
5426 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5427 emitcode ("setb","F0");
5428 emitcode ("","!tlabeldef",lbl->key+100);
5429 emitcode ("mov","mb,b");
5430 emitcode ("mov","mb,a");
5433 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5434 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5437 /* wait for multiplication to finish */
5438 lbl = newiTempLabel(NULL);
5439 emitcode("","!tlabeldef", lbl->key+100);
5440 emitcode("mov","a,mcnt1");
5441 emitcode("anl","a,#!constbyte",0x80);
5442 emitcode("jnz","!tlabel",lbl->key+100);
5444 freeAsmop (left, NULL, ic, TRUE);
5445 freeAsmop (right, NULL, ic,TRUE);
5446 aopOp(result, ic, TRUE, FALSE);
5448 /* if unsigned then simple */
5450 aopPut(AOP(result),"ma",1);
5451 aopPut(AOP(result),"ma",0);
5453 emitcode("push","ma");
5455 /* negate result if needed */
5456 lbl = newiTempLabel(NULL);
5457 emitcode("jnb","F0,!tlabel",lbl->key+100);
5458 emitcode("cpl","a");
5459 emitcode("add","a,#1");
5460 emitcode("","!tlabeldef", lbl->key+100);
5461 aopPut(AOP(result),"a",0);
5462 emitcode("pop","acc");
5463 lbl = newiTempLabel(NULL);
5464 emitcode("jnb","F0,!tlabel",lbl->key+100);
5465 emitcode("cpl","a");
5466 emitcode("addc","a,#0");
5467 emitcode("","!tlabeldef", lbl->key+100);
5468 aopPut(AOP(result),"a",1);
5470 freeAsmop (result, NULL, ic, TRUE);
5471 /* restore EA bit in F1 */
5472 lbl = newiTempLabel(NULL);
5473 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5474 emitcode ("setb","EA");
5475 emitcode("","!tlabeldef",lbl->key+100);
5479 /*-----------------------------------------------------------------*/
5480 /* genDiv - generates code for division */
5481 /*-----------------------------------------------------------------*/
5485 operand *left = IC_LEFT (ic);
5486 operand *right = IC_RIGHT (ic);
5487 operand *result = IC_RESULT (ic);
5489 D (emitcode (";", "genDiv "););
5491 /* assign the amsops */
5494 /* special cases first */
5496 if (AOP_TYPE (left) == AOP_CRY &&
5497 AOP_TYPE (right) == AOP_CRY)
5499 genDivbits (left, right, result, ic);
5503 /* if both are of size == 1 */
5504 if (AOP_SIZE (left) == 1 &&
5505 AOP_SIZE (right) == 1)
5507 genDivOneByte (left, right, result, ic);
5511 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5512 /* use the ds390 ARITHMETIC accel UNIT */
5513 genDivTwoByte (left, right, result, ic);
5516 /* should have been converted to function call */
5519 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5520 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5521 freeAsmop (result, NULL, ic, TRUE);
5524 /*-----------------------------------------------------------------*/
5525 /* genModbits :- modulus of bits */
5526 /*-----------------------------------------------------------------*/
5528 genModbits (operand * left,
5536 /* the result must be bit */
5537 LOAD_AB_FOR_DIV (left, right, l);
5538 emitcode ("div", "ab");
5539 emitcode ("mov", "a,b");
5540 emitcode ("rrc", "a");
5541 aopOp(result, ic, TRUE, FALSE);
5542 aopPut (AOP (result), "c", 0);
5545 /*-----------------------------------------------------------------*/
5546 /* genModOneByte : 8 bit modulus */
5547 /*-----------------------------------------------------------------*/
5549 genModOneByte (operand * left,
5554 bool lUnsigned, rUnsigned;
5555 bool runtimeSign, compiletimeSign;
5561 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5562 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5564 /* signed or unsigned */
5565 if (lUnsigned && rUnsigned)
5567 /* unsigned is easy */
5568 LOAD_AB_FOR_DIV (left, right, l);
5569 emitcode ("div", "ab");
5570 aopOp (result, ic, TRUE, FALSE);
5571 aopPut (AOP (result), "b", 0);
5573 for (size = AOP_SIZE (result) - 1; size--;)
5574 aopPut (AOP (result), zero, offset++);
5578 /* signed is a little bit more difficult */
5580 /* now sign adjust for both left & right */
5582 /* modulus: sign of the right operand has no influence on the result! */
5583 if (AOP_TYPE(right) == AOP_LIT)
5585 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5587 if (!rUnsigned && val < 0)
5588 emitcode ("mov", "b,#0x%02x", -val);
5590 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5592 else /* ! literal */
5595 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5598 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5599 lbl = newiTempLabel (NULL);
5600 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5601 emitcode ("cpl", "a"); /* 2's complement */
5602 emitcode ("inc", "a");
5603 emitcode ("", "!tlabeldef", lbl->key + 100);
5604 emitcode ("mov", "b,a");
5608 /* let's see what's needed: */
5609 /* apply negative sign during runtime */
5610 runtimeSign = FALSE;
5611 /* negative sign from literals */
5612 compiletimeSign = FALSE;
5614 /* sign adjust left side */
5615 if (AOP_TYPE(left) == AOP_LIT)
5617 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5619 if (!lUnsigned && val < 0)
5621 compiletimeSign = TRUE; /* set sign flag */
5622 emitcode ("mov", "a,#0x%02x", -val);
5625 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5627 else /* ! literal */
5629 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5634 emitcode ("clr", "F0"); /* clear sign flag */
5636 lbl = newiTempLabel (NULL);
5637 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5638 emitcode ("setb", "F0"); /* set sign flag */
5639 emitcode ("cpl", "a"); /* 2's complement */
5640 emitcode ("inc", "a");
5641 emitcode ("", "!tlabeldef", lbl->key + 100);
5645 /* now the modulus */
5646 emitcode ("nop", "; workaround for DS80C390 div bug.");
5647 emitcode ("div", "ab");
5649 if (runtimeSign || compiletimeSign)
5651 emitcode ("mov", "a,b");
5652 lbl = newiTempLabel (NULL);
5654 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5655 emitcode ("cpl", "a"); /* lsb 2's complement */
5656 emitcode ("inc", "a");
5657 emitcode ("", "!tlabeldef", lbl->key + 100);
5659 _G.accInUse++; _G.bInUse++;
5660 aopOp (result, ic, TRUE, FALSE);
5661 size = AOP_SIZE (result) - 1;
5665 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5666 then the result will be in b, a */
5667 emitcode ("mov", "b,a"); /* 1 */
5668 /* msb is 0x00 or 0xff depending on the sign */
5671 emitcode ("mov", "c,F0");
5672 emitcode ("subb", "a,acc");
5673 emitcode ("xch", "a,b"); /* 2 */
5675 aopPut (AOP (result), "b", offset++); /* write msb's */
5677 else /* compiletimeSign */
5679 aopPut (AOP (result), "#0xff", offset++); /* write msb's */
5681 aopPut (AOP (result), "a", 0); /* 3: write lsb */
5685 _G.accInUse++; _G.bInUse++;
5686 aopOp(result, ic, TRUE, FALSE);
5687 size = AOP_SIZE (result) - 1;
5689 aopPut (AOP (result), "b", 0);
5691 aopPut (AOP (result), zero, offset++);
5693 _G.accInUse--; _G.bInUse--;
5697 /*-----------------------------------------------------------------*/
5698 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
5699 /*-----------------------------------------------------------------*/
5700 static void genModTwoByte (operand *left, operand *right,
5701 operand *result, iCode *ic)
5703 sym_link *retype = getSpec(operandType(right));
5704 sym_link *letype = getSpec(operandType(left));
5705 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5708 /* load up MA with left */
5709 /* save EA bit in F1 */
5710 lbl = newiTempLabel(NULL);
5711 emitcode ("setb","F1");
5712 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5713 emitcode ("clr","F1");
5714 emitcode("","!tlabeldef",lbl->key+100);
5717 lbl = newiTempLabel(NULL);
5718 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5719 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5720 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5721 emitcode ("xch", "a,b");
5722 emitcode ("cpl","a");
5723 emitcode ("add", "a,#1");
5724 emitcode ("xch", "a,b");
5725 emitcode ("cpl", "a"); // msb
5726 emitcode ("addc","a,#0");
5727 emitcode ("","!tlabeldef",lbl->key+100);
5728 emitcode ("mov","ma,b");
5729 emitcode ("mov","ma,a");
5731 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5732 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5735 /* load up MB with right */
5737 if (AOP_TYPE(right) == AOP_LIT) {
5738 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5742 emitcode ("mov","mb,#!constbyte",val & 0xff);
5743 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5745 lbl = newiTempLabel(NULL);
5746 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5747 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5748 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5749 emitcode ("xch", "a,b");
5750 emitcode ("cpl","a");
5751 emitcode ("add", "a,#1");
5752 emitcode ("xch", "a,b");
5753 emitcode ("cpl", "a"); // msb
5754 emitcode ("addc", "a,#0");
5755 emitcode ("","!tlabeldef",lbl->key+100);
5756 emitcode ("mov","mb,b");
5757 emitcode ("mov","mb,a");
5760 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5761 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5764 /* wait for multiplication to finish */
5765 lbl = newiTempLabel(NULL);
5766 emitcode("","!tlabeldef", lbl->key+100);
5767 emitcode("mov","a,mcnt1");
5768 emitcode("anl","a,#!constbyte",0x80);
5769 emitcode("jnz","!tlabel",lbl->key+100);
5771 freeAsmop (left, NULL, ic, TRUE);
5772 freeAsmop (right, NULL, ic,TRUE);
5773 aopOp(result, ic, TRUE, FALSE);
5775 aopPut(AOP(result),"mb",1);
5776 aopPut(AOP(result),"mb",0);
5777 freeAsmop (result, NULL, ic, TRUE);
5779 /* restore EA bit in F1 */
5780 lbl = newiTempLabel(NULL);
5781 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5782 emitcode ("setb","EA");
5783 emitcode("","!tlabeldef",lbl->key+100);
5787 /*-----------------------------------------------------------------*/
5788 /* genMod - generates code for division */
5789 /*-----------------------------------------------------------------*/
5793 operand *left = IC_LEFT (ic);
5794 operand *right = IC_RIGHT (ic);
5795 operand *result = IC_RESULT (ic);
5797 D (emitcode (";", "genMod "); );
5799 /* assign the amsops */
5802 /* special cases first */
5804 if (AOP_TYPE (left) == AOP_CRY &&
5805 AOP_TYPE (right) == AOP_CRY)
5807 genModbits (left, right, result, ic);
5811 /* if both are of size == 1 */
5812 if (AOP_SIZE (left) == 1 &&
5813 AOP_SIZE (right) == 1)
5815 genModOneByte (left, right, result, ic);
5819 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5820 /* use the ds390 ARITHMETIC accel UNIT */
5821 genModTwoByte (left, right, result, ic);
5825 /* should have been converted to function call */
5829 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5830 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5831 freeAsmop (result, NULL, ic, TRUE);
5834 /*-----------------------------------------------------------------*/
5835 /* genIfxJump :- will create a jump depending on the ifx */
5836 /*-----------------------------------------------------------------*/
5838 genIfxJump (iCode * ic, char *jval)
5841 symbol *tlbl = newiTempLabel (NULL);
5844 D (emitcode (";", "genIfxJump"););
5846 /* if true label then we jump if condition
5850 jlbl = IC_TRUE (ic);
5851 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5852 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5856 /* false label is present */
5857 jlbl = IC_FALSE (ic);
5858 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5859 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5861 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5862 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5864 emitcode (inst, "!tlabel", tlbl->key + 100);
5865 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5866 emitcode ("", "!tlabeldef", tlbl->key + 100);
5868 /* mark the icode as generated */
5872 /*-----------------------------------------------------------------*/
5873 /* genCmp :- greater or less than comparison */
5874 /*-----------------------------------------------------------------*/
5876 genCmp (operand * left, operand * right,
5877 iCode * ic, iCode * ifx, int sign)
5879 int size, offset = 0;
5880 unsigned long lit = 0L;
5883 D (emitcode (";", "genCmp"););
5885 result = IC_RESULT (ic);
5887 /* if left & right are bit variables */
5888 if (AOP_TYPE (left) == AOP_CRY &&
5889 AOP_TYPE (right) == AOP_CRY)
5891 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5892 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5896 /* subtract right from left if at the
5897 end the carry flag is set then we know that
5898 left is greater than right */
5899 size = max (AOP_SIZE (left), AOP_SIZE (right));
5901 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5902 if ((size == 1) && !sign
5903 && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5905 symbol *lbl = newiTempLabel (NULL);
5906 emitcode ("cjne", "%s,%s,!tlabel",
5907 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5908 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5910 emitcode ("", "!tlabeldef", lbl->key + 100);
5914 if (AOP_TYPE (right) == AOP_LIT)
5916 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5917 /* optimize if(x < 0) or if(x >= 0) */
5926 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5928 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5929 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5931 aopOp (result, ic, FALSE, FALSE);
5933 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5935 freeAsmop (result, NULL, ic, TRUE);
5936 genIfxJump (ifx, "acc.7");
5941 emitcode ("rlc", "a");
5943 goto release_freedLR;
5951 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5952 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5953 // emitcode (";", "genCmp #2");
5954 if (sign && (size == 0))
5956 // emitcode (";", "genCmp #3");
5957 emitcode ("xrl", "a,#!constbyte",0x80);
5958 if (AOP_TYPE (right) == AOP_LIT)
5960 unsigned long lit = (unsigned long)
5961 floatFromVal (AOP (right)->aopu.aop_lit);
5962 // emitcode (";", "genCmp #3.1");
5963 emitcode ("subb", "a,#!constbyte",
5964 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5968 // emitcode (";", "genCmp #3.2");
5970 MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5971 saveAccWarn = DEFAULT_ACC_WARNING;
5972 emitcode ("xrl", "b,#!constbyte",0x80);
5973 emitcode ("subb", "a,b");
5980 // emitcode (";", "genCmp #4");
5982 s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5983 saveAccWarn = DEFAULT_ACC_WARNING;
5985 emitcode ("subb", "a,%s", s);
5992 /* Don't need the left & right operands any more; do need the result. */
5993 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5994 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5996 aopOp (result, ic, FALSE, FALSE);
6000 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6006 /* if the result is used in the next
6007 ifx conditional branch then generate
6008 code a little differently */
6011 genIfxJump (ifx, "c");
6017 /* leave the result in acc */
6019 freeAsmop (result, NULL, ic, TRUE);
6022 /*-----------------------------------------------------------------*/
6023 /* genCmpGt :- greater than comparison */
6024 /*-----------------------------------------------------------------*/
6026 genCmpGt (iCode * ic, iCode * ifx)
6028 operand *left, *right;
6029 sym_link *letype, *retype;
6032 D (emitcode (";", "genCmpGt ");
6035 left = IC_LEFT (ic);
6036 right = IC_RIGHT (ic);
6038 letype = getSpec (operandType (left));
6039 retype = getSpec (operandType (right));
6040 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6042 /* assign the left & right amsops */
6045 genCmp (right, left, ic, ifx, sign);
6048 /*-----------------------------------------------------------------*/
6049 /* genCmpLt - less than comparisons */
6050 /*-----------------------------------------------------------------*/
6052 genCmpLt (iCode * ic, iCode * ifx)
6054 operand *left, *right;
6055 sym_link *letype, *retype;
6058 D (emitcode (";", "genCmpLt "););
6060 left = IC_LEFT (ic);
6061 right = IC_RIGHT (ic);
6063 letype = getSpec (operandType (left));
6064 retype = getSpec (operandType (right));
6065 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6067 /* assign the left & right amsops */
6070 genCmp (left, right, ic, ifx, sign);
6073 /*-----------------------------------------------------------------*/
6074 /* gencjneshort - compare and jump if not equal */
6075 /*-----------------------------------------------------------------*/
6077 gencjneshort (operand * left, operand * right, symbol * lbl)
6079 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6081 unsigned long lit = 0L;
6083 D (emitcode (";", "gencjneshort");
6086 /* if the left side is a literal or
6087 if the right is in a pointer register and left
6089 if ((AOP_TYPE (left) == AOP_LIT) ||
6090 (AOP_TYPE (left) == AOP_IMMD) ||
6091 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6098 if (AOP_TYPE (right) == AOP_LIT)
6099 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6101 if (opIsGptr (left) || opIsGptr (right))
6103 /* We are comparing a generic pointer to something.
6104 * Exclude the generic type byte from the comparison.
6107 D (emitcode (";", "cjneshort: generic ptr special case."););
6111 /* if the right side is a literal then anything goes */
6112 if (AOP_TYPE (right) == AOP_LIT &&
6113 AOP_TYPE (left) != AOP_DIR)
6117 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6118 emitcode ("cjne", "a,%s,!tlabel",
6119 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
6125 /* if the right side is in a register or in direct space or
6126 if the left is a pointer register & right is not */
6127 else if (AOP_TYPE (right) == AOP_REG ||
6128 AOP_TYPE (right) == AOP_DIR ||
6129 AOP_TYPE (right) == AOP_LIT ||
6130 AOP_TYPE (right) == AOP_IMMD ||
6131 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6132 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6136 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6137 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6138 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6139 emitcode ("jnz", "!tlabel", lbl->key + 100);
6141 emitcode ("cjne", "a,%s,!tlabel",
6142 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
6149 /* right is a pointer reg need both a & b */
6152 MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6153 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6154 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
6160 /*-----------------------------------------------------------------*/
6161 /* gencjne - compare and jump if not equal */
6162 /*-----------------------------------------------------------------*/
6164 gencjne (operand * left, operand * right, symbol * lbl)
6166 symbol *tlbl = newiTempLabel (NULL);
6168 D (emitcode (";", "gencjne");
6171 gencjneshort (left, right, lbl);
6173 emitcode ("mov", "a,%s", one);
6174 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
6175 emitcode ("", "!tlabeldef", lbl->key + 100);
6176 emitcode ("clr", "a");
6177 emitcode ("", "!tlabeldef", tlbl->key + 100);
6180 /*-----------------------------------------------------------------*/
6181 /* genCmpEq - generates code for equal to */
6182 /*-----------------------------------------------------------------*/
6184 genCmpEq (iCode * ic, iCode * ifx)
6186 operand *left, *right, *result;
6188 D (emitcode (";", "genCmpEq ");
6192 AOP_SET_LOCALS (ic);
6194 /* if literal, literal on the right or
6195 if the right is in a pointer register and left
6197 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6198 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6200 operand *t = IC_RIGHT (ic);
6201 IC_RIGHT (ic) = IC_LEFT (ic);
6205 if (ifx && /* !AOP_SIZE(result) */
6206 OP_SYMBOL (result) &&
6207 OP_SYMBOL (result)->regType == REG_CND)
6210 /* if they are both bit variables */
6211 if (AOP_TYPE (left) == AOP_CRY &&
6212 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6214 if (AOP_TYPE (right) == AOP_LIT)
6216 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6219 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6220 emitcode ("cpl", "c");
6224 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6228 emitcode ("clr", "c");
6230 /* AOP_TYPE(right) == AOP_CRY */
6234 symbol *lbl = newiTempLabel (NULL);
6235 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6236 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6237 emitcode ("cpl", "c");
6238 emitcode ("", "!tlabeldef", (lbl->key + 100));
6240 /* if true label then we jump if condition
6242 tlbl = newiTempLabel (NULL);
6245 emitcode ("jnc", "!tlabel", tlbl->key + 100);
6246 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6250 emitcode ("jc", "!tlabel", tlbl->key + 100);
6251 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6253 emitcode ("", "!tlabeldef", tlbl->key + 100);
6257 tlbl = newiTempLabel (NULL);
6258 gencjneshort (left, right, tlbl);
6261 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6262 emitcode ("", "!tlabeldef", tlbl->key + 100);
6266 symbol *lbl = newiTempLabel (NULL);
6267 emitcode ("sjmp", "!tlabel", lbl->key + 100);
6268 emitcode ("", "!tlabeldef", tlbl->key + 100);
6269 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6270 emitcode ("", "!tlabeldef", lbl->key + 100);
6273 /* mark the icode as generated */
6276 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6277 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6281 /* if they are both bit variables */
6282 if (AOP_TYPE (left) == AOP_CRY &&
6283 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6285 if (AOP_TYPE (right) == AOP_LIT)
6287 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6290 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6291 emitcode ("cpl", "c");
6295 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6299 emitcode ("clr", "c");
6301 /* AOP_TYPE(right) == AOP_CRY */
6305 symbol *lbl = newiTempLabel (NULL);
6306 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6307 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6308 emitcode ("cpl", "c");
6309 emitcode ("", "!tlabeldef", (lbl->key + 100));
6312 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6313 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6315 aopOp (result, ic, TRUE, FALSE);
6318 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6325 genIfxJump (ifx, "c");
6328 /* if the result is used in an arithmetic operation
6329 then put the result in place */
6334 gencjne (left, right, newiTempLabel (NULL));
6336 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6337 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6339 aopOp (result, ic, TRUE, FALSE);
6341 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6343 aopPut (AOP (result), "a", 0);
6348 genIfxJump (ifx, "a");
6351 /* if the result is used in an arithmetic operation
6352 then put the result in place */
6353 if (AOP_TYPE (result) != AOP_CRY)
6355 /* leave the result in acc */
6359 freeAsmop (result, NULL, ic, TRUE);
6362 /*-----------------------------------------------------------------*/
6363 /* ifxForOp - returns the icode containing the ifx for operand */
6364 /*-----------------------------------------------------------------*/
6366 ifxForOp (operand * op, iCode * ic)
6368 /* if true symbol then needs to be assigned */
6369 if (IS_TRUE_SYMOP (op))
6372 /* if this has register type condition and
6373 the next instruction is ifx with the same operand
6374 and live to of the operand is upto the ifx only then */
6376 ic->next->op == IFX &&
6377 IC_COND (ic->next)->key == op->key &&
6378 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6383 /*-----------------------------------------------------------------*/
6384 /* hasInc - operand is incremented before any other use */
6385 /*-----------------------------------------------------------------*/
6387 hasInc (operand *op, iCode *ic, int osize)
6389 sym_link *type = operandType(op);
6390 sym_link *retype = getSpec (type);
6391 iCode *lic = ic->next;
6394 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6395 if (!IS_SYMOP(op)) return NULL;
6397 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6398 if (IS_AGGREGATE(type->next)) return NULL;
6399 if (osize != (isize = getSize(type->next))) return NULL;
6402 /* if operand of the form op = op + <sizeof *op> */
6403 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6404 isOperandEqual(IC_RESULT(lic),op) &&
6405 isOperandLiteral(IC_RIGHT(lic)) &&
6406 operandLitValue(IC_RIGHT(lic)) == isize) {
6409 /* if the operand used or deffed */
6410 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6413 /* if GOTO or IFX */
6414 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6420 /*-----------------------------------------------------------------*/
6421 /* genAndOp - for && operation */
6422 /*-----------------------------------------------------------------*/
6424 genAndOp (iCode * ic)
6426 operand *left, *right, *result;
6429 D (emitcode (";", "genAndOp "););
6431 /* note here that && operations that are in an
6432 if statement are taken away by backPatchLabels
6433 only those used in arthmetic operations remain */
6435 AOP_SET_LOCALS (ic);
6437 /* if both are bit variables */
6438 if (AOP_TYPE (left) == AOP_CRY &&
6439 AOP_TYPE (right) == AOP_CRY)
6441 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6442 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6443 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6444 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6446 aopOp (result,ic,FALSE, FALSE);
6451 tlbl = newiTempLabel (NULL);
6453 emitcode ("jz", "!tlabel", tlbl->key + 100);
6455 emitcode ("", "!tlabeldef", tlbl->key + 100);
6456 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6457 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6459 aopOp (result,ic,FALSE, FALSE);
6462 freeAsmop (result, NULL, ic, TRUE);
6466 /*-----------------------------------------------------------------*/
6467 /* genOrOp - for || operation */
6468 /*-----------------------------------------------------------------*/
6470 genOrOp (iCode * ic)
6472 operand *left, *right, *result;
6475 D (emitcode (";", "genOrOp "););
6477 /* note here that || operations that are in an
6478 if statement are taken away by backPatchLabels
6479 only those used in arthmetic operations remain */
6481 AOP_SET_LOCALS (ic);
6483 /* if both are bit variables */
6484 if (AOP_TYPE (left) == AOP_CRY &&
6485 AOP_TYPE (right) == AOP_CRY)
6487 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6488 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6489 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6490 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6492 aopOp (result,ic,FALSE, FALSE);
6498 tlbl = newiTempLabel (NULL);
6500 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6502 emitcode ("", "!tlabeldef", tlbl->key + 100);
6503 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6504 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6506 aopOp (result,ic,FALSE, FALSE);
6511 freeAsmop (result, NULL, ic, TRUE);
6514 /*-----------------------------------------------------------------*/
6515 /* isLiteralBit - test if lit == 2^n */
6516 /*-----------------------------------------------------------------*/
6518 isLiteralBit (unsigned long lit)
6520 unsigned long pw[32] =
6521 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6522 0x100L, 0x200L, 0x400L, 0x800L,
6523 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6524 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6525 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6526 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6527 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6530 for (idx = 0; idx < 32; idx++)
6536 /*-----------------------------------------------------------------*/
6537 /* continueIfTrue - */
6538 /*-----------------------------------------------------------------*/
6540 continueIfTrue (iCode * ic)
6543 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6547 /*-----------------------------------------------------------------*/
6549 /*-----------------------------------------------------------------*/
6551 jumpIfTrue (iCode * ic)
6554 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6558 /*-----------------------------------------------------------------*/
6559 /* jmpTrueOrFalse - */
6560 /*-----------------------------------------------------------------*/
6562 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6564 // ugly but optimized by peephole
6567 symbol *nlbl = newiTempLabel (NULL);
6568 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6569 emitcode ("", "!tlabeldef", tlbl->key + 100);
6570 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6571 emitcode ("", "!tlabeldef", nlbl->key + 100);
6575 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6576 emitcode ("", "!tlabeldef", tlbl->key + 100);
6581 // Generate code to perform a bit-wise logic operation
6582 // on two operands in far space (assumed to already have been
6583 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6584 // in far space. This requires pushing the result on the stack
6585 // then popping it into the result.
6587 genFarFarLogicOp(iCode *ic, char *logicOp)
6589 int size, resultSize, compSize;
6593 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6594 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
6595 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6597 _startLazyDPSEvaluation();
6598 for (size = compSize; (size--); offset++)
6600 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6601 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6602 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6604 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6605 emitcode ("push", "acc");
6607 _endLazyDPSEvaluation();
6609 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6610 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6611 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6613 resultSize = AOP_SIZE(IC_RESULT(ic));
6615 ADJUST_PUSHED_RESULT(compSize, resultSize);
6617 _startLazyDPSEvaluation();
6620 emitcode ("pop", "acc");
6621 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6623 _endLazyDPSEvaluation();
6624 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6628 /*-----------------------------------------------------------------*/
6629 /* genAnd - code for and */
6630 /*-----------------------------------------------------------------*/
6632 genAnd (iCode * ic, iCode * ifx)
6634 operand *left, *right, *result;
6635 int size, offset = 0;
6636 unsigned long lit = 0L;
6641 D (emitcode (";", "genAnd "););
6643 AOP_OP_3_NOFATAL (ic, pushResult);
6644 AOP_SET_LOCALS (ic);
6648 genFarFarLogicOp(ic, "anl");
6653 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6655 AOP_TYPE (left), AOP_TYPE (right));
6656 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6658 AOP_SIZE (left), AOP_SIZE (right));
6661 /* if left is a literal & right is not then exchange them */
6662 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6663 #ifdef LOGIC_OPS_BROKEN
6664 || AOP_NEEDSACC (left)
6668 operand *tmp = right;
6673 /* if result = right then exchange left and right */
6674 if (sameRegs (AOP (result), AOP (right)))
6676 operand *tmp = right;
6681 /* if right is bit then exchange them */
6682 if (AOP_TYPE (right) == AOP_CRY &&
6683 AOP_TYPE (left) != AOP_CRY)
6685 operand *tmp = right;
6689 if (AOP_TYPE (right) == AOP_LIT)
6690 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6692 size = AOP_SIZE (result);
6695 // result = bit & yy;
6696 if (AOP_TYPE (left) == AOP_CRY)
6698 // c = bit & literal;
6699 if (AOP_TYPE (right) == AOP_LIT)
6703 if (size && sameRegs (AOP (result), AOP (left)))
6706 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6711 if (size && (AOP_TYPE (result) == AOP_CRY))
6713 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6716 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6721 emitcode ("clr", "c");
6726 if (AOP_TYPE (right) == AOP_CRY)
6729 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6730 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6735 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6737 emitcode ("rrc", "a");
6738 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6746 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6747 genIfxJump (ifx, "c");
6751 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6752 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6753 if ((AOP_TYPE (right) == AOP_LIT) &&
6754 (AOP_TYPE (result) == AOP_CRY) &&
6755 (AOP_TYPE (left) != AOP_CRY))
6757 int posbit = isLiteralBit (lit);
6762 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6765 emitcode ("mov", "c,acc.%d", posbit & 0x07);
6771 SNPRINTF (buff, sizeof(buff),
6772 "acc.%d", posbit & 0x07);
6773 genIfxJump (ifx, buff);
6777 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6784 symbol *tlbl = newiTempLabel (NULL);
6785 int sizel = AOP_SIZE (left);
6787 emitcode ("setb", "c");
6790 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6792 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6794 if ((posbit = isLiteralBit (bytelit)) != 0)
6795 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6798 if (bytelit != 0x0FFL)
6799 emitcode ("anl", "a,%s",
6800 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6801 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6806 // bit = left & literal
6809 emitcode ("clr", "c");
6810 emitcode ("", "!tlabeldef", tlbl->key + 100);
6812 // if(left & literal)
6816 jmpTrueOrFalse (ifx, tlbl);
6818 emitcode ("", "!tlabeldef", tlbl->key + 100);
6826 /* if left is same as result */
6827 if (sameRegs (AOP (result), AOP (left)))
6829 for (; size--; offset++)
6831 if (AOP_TYPE (right) == AOP_LIT)
6833 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6834 if (bytelit == 0x0FF)
6836 /* dummy read of volatile operand */
6837 if (isOperandVolatile (left, FALSE))
6838 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6842 else if (bytelit == 0)
6844 aopPut (AOP (result), zero, offset);
6846 else if (IS_AOP_PREG (result))
6848 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6849 emitcode ("anl", "a,%s",
6850 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6851 aopPut (AOP (result), "a", offset);
6854 emitcode ("anl", "%s,%s",
6855 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6856 aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6860 if (AOP_TYPE (left) == AOP_ACC)
6861 emitcode ("anl", "a,%s",
6862 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6865 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6866 if (IS_AOP_PREG (result))
6868 emitcode ("anl", "a,%s",
6869 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6870 aopPut (AOP (result), "a", offset);
6873 emitcode ("anl", "%s,a",
6874 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6881 // left & result in different registers
6882 if (AOP_TYPE (result) == AOP_CRY)
6885 // if(size), result in bit
6886 // if(!size && ifx), conditional oper: if(left & right)
6887 symbol *tlbl = newiTempLabel (NULL);
6888 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6890 emitcode ("setb", "c");
6893 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6894 emitcode ("anl", "a,%s",
6895 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6897 if (AOP_TYPE(left)==AOP_ACC) {
6898 emitcode("mov", "b,a");
6899 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6900 emitcode("anl", "a,b");
6902 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6903 emitcode ("anl", "a,%s",
6904 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6907 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6913 emitcode ("", "!tlabeldef", tlbl->key + 100);
6917 jmpTrueOrFalse (ifx, tlbl);
6919 emitcode ("", "!tlabeldef", tlbl->key + 100);
6923 for (; (size--); offset++)
6926 // result = left & right
6927 if (AOP_TYPE (right) == AOP_LIT)
6929 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6930 if (bytelit == 0x0FF)
6932 aopPut (AOP (result),
6933 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6937 else if (bytelit == 0)
6939 /* dummy read of volatile operand */
6940 if (isOperandVolatile (left, FALSE))
6941 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6942 aopPut (AOP (result), zero, offset);
6945 D (emitcode (";", "better literal AND."););
6946 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6947 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6948 FALSE, FALSE, DP2_RESULT_REG));
6953 // faster than result <- left, anl result,right
6954 // and better if result is SFR
6955 if (AOP_TYPE (left) == AOP_ACC)
6957 emitcode ("anl", "a,%s",
6958 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6962 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6963 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6965 emitcode("mov", "b,a");
6969 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6970 emitcode ("anl", "a,%s", rOp);
6973 aopPut (AOP (result), "a", offset);
6979 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6980 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6981 freeAsmop (result, NULL, ic, TRUE);
6985 /*-----------------------------------------------------------------*/
6986 /* genOr - code for or */
6987 /*-----------------------------------------------------------------*/
6989 genOr (iCode * ic, iCode * ifx)
6991 operand *left, *right, *result;
6992 int size, offset = 0;
6993 unsigned long lit = 0L;
6997 D (emitcode (";", "genOr "););
6999 AOP_OP_3_NOFATAL (ic, pushResult);
7000 AOP_SET_LOCALS (ic);
7004 genFarFarLogicOp(ic, "orl");
7010 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7012 AOP_TYPE (left), AOP_TYPE (right));
7013 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7015 AOP_SIZE (left), AOP_SIZE (right));
7018 /* if left is a literal & right is not then exchange them */
7019 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7020 #ifdef LOGIC_OPS_BROKEN
7021 || AOP_NEEDSACC (left) // I think this is a net loss now.
7025 operand *tmp = right;
7030 /* if result = right then exchange them */
7031 if (sameRegs (AOP (result), AOP (right)))
7033 operand *tmp = right;
7038 /* if right is bit then exchange them */
7039 if (AOP_TYPE (right) == AOP_CRY &&
7040 AOP_TYPE (left) != AOP_CRY)
7042 operand *tmp = right;
7046 if (AOP_TYPE (right) == AOP_LIT)
7047 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7049 size = AOP_SIZE (result);
7053 if (AOP_TYPE (left) == AOP_CRY)
7055 if (AOP_TYPE (right) == AOP_LIT)
7057 // c = bit & literal;
7060 // lit != 0 => result = 1
7061 if (AOP_TYPE (result) == AOP_CRY)
7064 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7066 continueIfTrue (ifx);
7069 emitcode ("setb", "c");
7073 // lit == 0 => result = left
7074 if (size && sameRegs (AOP (result), AOP (left)))
7076 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7081 if (AOP_TYPE (right) == AOP_CRY)
7084 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7085 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7090 symbol *tlbl = newiTempLabel (NULL);
7091 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7092 emitcode ("setb", "c");
7093 emitcode ("jb", "%s,!tlabel",
7094 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7096 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7097 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7099 jmpTrueOrFalse (ifx, tlbl);
7105 emitcode ("", "!tlabeldef", tlbl->key + 100);
7114 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7115 genIfxJump (ifx, "c");
7119 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7120 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7121 if ((AOP_TYPE (right) == AOP_LIT) &&
7122 (AOP_TYPE (result) == AOP_CRY) &&
7123 (AOP_TYPE (left) != AOP_CRY))
7129 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7131 continueIfTrue (ifx);
7136 // lit = 0, result = boolean(left)
7138 emitcode ("setb", "c");
7142 symbol *tlbl = newiTempLabel (NULL);
7143 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7145 emitcode ("", "!tlabeldef", tlbl->key + 100);
7149 genIfxJump (ifx, "a");
7157 /* if left is same as result */
7158 if (sameRegs (AOP (result), AOP (left)))
7160 for (; size--; offset++)
7162 if (AOP_TYPE (right) == AOP_LIT)
7164 bytelit = (int)((lit >> (offset * 8)) & 0x0FFL);
7165 if (bytelit == 0x00L)
7167 /* dummy read of volatile operand */
7168 if (isOperandVolatile (left, FALSE))
7169 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7173 else if (bytelit == 0x0FF)
7175 aopPut (AOP (result), "#0xFF", offset);
7177 else if (IS_AOP_PREG (left))
7179 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7180 emitcode ("orl", "a,%s",
7181 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7182 aopPut (AOP (result), "a", offset);
7186 emitcode ("orl", "%s,%s",
7187 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7188 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7193 if (AOP_TYPE (left) == AOP_ACC)
7195 emitcode ("orl", "a,%s",
7196 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7200 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7201 if (IS_AOP_PREG (left))
7203 emitcode ("orl", "a,%s",
7204 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7205 aopPut (AOP (result), "a", offset);
7209 emitcode ("orl", "%s,a",
7210 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7218 // left & result in different registers
7219 if (AOP_TYPE (result) == AOP_CRY)
7222 // if(size), result in bit
7223 // if(!size && ifx), conditional oper: if(left | right)
7224 symbol *tlbl = newiTempLabel (NULL);
7225 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7227 emitcode ("setb", "c");
7230 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7231 emitcode ("orl", "a,%s",
7232 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7234 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7235 emitcode ("orl", "a,%s",
7236 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
7238 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7244 emitcode ("", "!tlabeldef", tlbl->key + 100);
7248 jmpTrueOrFalse (ifx, tlbl);
7250 emitcode ("", "!tlabeldef", tlbl->key + 100);
7254 _startLazyDPSEvaluation();
7255 for (; (size--); offset++)
7258 // result = left & right
7259 if (AOP_TYPE (right) == AOP_LIT)
7261 bytelit = (int)((lit >> (offset * 8)) & 0x0FFL);
7262 if (bytelit == 0x00L)
7264 aopPut (AOP (result),
7265 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7269 else if (bytelit == 0x0FF)
7271 /* dummy read of volatile operand */
7272 if (isOperandVolatile (left, FALSE))
7273 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7274 aopPut (AOP (result), "#0xFF", offset);
7277 D (emitcode (";", "better literal OR."););
7278 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7279 emitcode ("orl", "a, %s",
7280 aopGet (AOP (right), offset,
7281 FALSE, FALSE, DP2_RESULT_REG));
7286 // faster than result <- left, anl result,right
7287 // and better if result is SFR
7288 if (AOP_TYPE (left) == AOP_ACC)
7290 emitcode ("orl", "a,%s",
7291 aopGet (AOP (right), offset,
7292 FALSE, FALSE, DP2_RESULT_REG));
7296 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7298 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7300 emitcode("mov", "b,a");
7304 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7305 emitcode ("orl", "a,%s", rOp);
7308 aopPut (AOP (result), "a", offset);
7310 _endLazyDPSEvaluation();
7315 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7316 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7317 freeAsmop (result, NULL, ic, TRUE);
7320 /*-----------------------------------------------------------------*/
7321 /* genXor - code for xclusive or */
7322 /*-----------------------------------------------------------------*/
7324 genXor (iCode * ic, iCode * ifx)
7326 operand *left, *right, *result;
7327 int size, offset = 0;
7328 unsigned long lit = 0L;
7332 D (emitcode (";", "genXor "););
7334 AOP_OP_3_NOFATAL (ic, pushResult);
7335 AOP_SET_LOCALS (ic);
7339 genFarFarLogicOp(ic, "xrl");
7344 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7346 AOP_TYPE (left), AOP_TYPE (right));
7347 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7349 AOP_SIZE (left), AOP_SIZE (right));
7352 /* if left is a literal & right is not ||
7353 if left needs acc & right does not */
7354 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7355 #ifdef LOGIC_OPS_BROKEN
7356 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
7360 operand *tmp = right;
7365 /* if result = right then exchange them */
7366 if (sameRegs (AOP (result), AOP (right)))
7368 operand *tmp = right;
7373 /* if right is bit then exchange them */
7374 if (AOP_TYPE (right) == AOP_CRY &&
7375 AOP_TYPE (left) != AOP_CRY)
7377 operand *tmp = right;
7381 if (AOP_TYPE (right) == AOP_LIT)
7382 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7384 size = AOP_SIZE (result);
7388 if (AOP_TYPE (left) == AOP_CRY)
7390 if (AOP_TYPE (right) == AOP_LIT)
7392 // c = bit & literal;
7395 // lit>>1 != 0 => result = 1
7396 if (AOP_TYPE (result) == AOP_CRY)
7399 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7401 continueIfTrue (ifx);
7404 emitcode ("setb", "c");
7411 // lit == 0, result = left
7412 if (size && sameRegs (AOP (result), AOP (left)))
7414 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7418 // lit == 1, result = not(left)
7419 if (size && sameRegs (AOP (result), AOP (left)))
7421 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7426 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7427 emitcode ("cpl", "c");
7436 symbol *tlbl = newiTempLabel (NULL);
7437 if (AOP_TYPE (right) == AOP_CRY)
7440 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7444 int sizer = AOP_SIZE (right);
7446 // if val>>1 != 0, result = 1
7447 emitcode ("setb", "c");
7450 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
7452 // test the msb of the lsb
7453 emitcode ("anl", "a,#!constbyte",0xfe);
7454 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7458 emitcode ("rrc", "a");
7460 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7461 emitcode ("cpl", "c");
7462 emitcode ("", "!tlabeldef", (tlbl->key + 100));
7469 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7470 genIfxJump (ifx, "c");
7474 /* if left is same as result */
7475 if (sameRegs (AOP (result), AOP (left)))
7477 for (; size--; offset++)
7479 if (AOP_TYPE (right) == AOP_LIT)
7481 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7482 if (bytelit == 0x00L)
7484 /* dummy read of volatile operand */
7485 if (isOperandVolatile (left, FALSE))
7486 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7490 else if (IS_AOP_PREG (left))
7492 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7493 emitcode ("xrl", "a,%s",
7494 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7495 aopPut (AOP (result), "a", offset);
7499 emitcode ("xrl", "%s,%s",
7500 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7501 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7506 if (AOP_TYPE (left) == AOP_ACC)
7507 emitcode ("xrl", "a,%s",
7508 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7511 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7512 if (IS_AOP_PREG (left))
7514 emitcode ("xrl", "a,%s",
7515 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7516 aopPut (AOP (result), "a", offset);
7519 emitcode ("xrl", "%s,a",
7520 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7527 // left & result in different registers
7528 if (AOP_TYPE (result) == AOP_CRY)
7531 // if(size), result in bit
7532 // if(!size && ifx), conditional oper: if(left ^ right)
7533 symbol *tlbl = newiTempLabel (NULL);
7534 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7537 emitcode ("setb", "c");
7540 if ((AOP_TYPE (right) == AOP_LIT) &&
7541 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7543 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7547 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7548 emitcode ("xrl", "a,%s",
7549 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7551 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7552 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7554 emitcode("mov", "b,a");
7558 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7559 emitcode ("xrl", "a,%s", rOp);
7562 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7568 emitcode ("", "!tlabeldef", tlbl->key + 100);
7572 jmpTrueOrFalse (ifx, tlbl);
7576 for (; (size--); offset++)
7579 // result = left & right
7580 if (AOP_TYPE (right) == AOP_LIT)
7582 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7584 aopPut (AOP (result),
7585 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7589 D (emitcode (";", "better literal XOR."););
7590 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7591 emitcode ("xrl", "a, %s",
7592 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7596 // faster than result <- left, anl result,right
7597 // and better if result is SFR
7598 if (AOP_TYPE (left) == AOP_ACC)
7600 emitcode ("xrl", "a,%s",
7601 aopGet (AOP (right), offset,
7602 FALSE, FALSE, DP2_RESULT_REG));
7606 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7607 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7609 emitcode("mov", "b,a");
7613 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7614 emitcode ("xrl", "a,%s", rOp);
7617 aopPut (AOP (result), "a", offset);
7624 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7625 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7626 freeAsmop (result, NULL, ic, TRUE);
7629 /*-----------------------------------------------------------------*/
7630 /* genInline - write the inline code out */
7631 /*-----------------------------------------------------------------*/
7633 genInline (iCode * ic)
7635 char *buffer, *bp, *bp1;
7637 D (emitcode (";", "genInline "); );
7639 _G.inLine += (!options.asmpeep);
7641 buffer = Safe_strdup(IC_INLINE(ic));
7645 /* emit each line as a code */
7670 /* emitcode("",buffer); */
7671 _G.inLine -= (!options.asmpeep);
7674 /*-----------------------------------------------------------------*/
7675 /* genRRC - rotate right with carry */
7676 /*-----------------------------------------------------------------*/
7680 operand *left, *result;
7683 D (emitcode (";", "genRRC "););
7685 /* rotate right with carry */
7686 left = IC_LEFT (ic);
7687 result = IC_RESULT (ic);
7688 aopOp (left, ic, FALSE, FALSE);
7689 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7691 /* move it to the result */
7692 size = AOP_SIZE (result);
7696 _startLazyDPSEvaluation ();
7699 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7700 emitcode ("rrc", "a");
7701 if (AOP_SIZE (result) > 1)
7702 aopPut (AOP (result), "a", offset--);
7704 _endLazyDPSEvaluation ();
7706 /* now we need to put the carry into the
7707 highest order byte of the result */
7708 if (AOP_SIZE (result) > 1)
7710 MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7712 emitcode ("mov", "acc.7,c");
7713 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7714 freeAsmop (left, NULL, ic, TRUE);
7715 freeAsmop (result, NULL, ic, TRUE);
7718 /*-----------------------------------------------------------------*/
7719 /* genRLC - generate code for rotate left with carry */
7720 /*-----------------------------------------------------------------*/
7724 operand *left, *result;
7728 D (emitcode (";", "genRLC "););
7730 /* rotate right with carry */
7731 left = IC_LEFT (ic);
7732 result = IC_RESULT (ic);
7733 aopOp (left, ic, FALSE, FALSE);
7734 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7736 /* move it to the result */
7737 size = AOP_SIZE (result);
7741 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7743 emitcode ("add", "a,acc");
7744 if (AOP_SIZE (result) > 1)
7746 aopPut (AOP (result), "a", offset++);
7749 _startLazyDPSEvaluation ();
7752 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7754 emitcode ("rlc", "a");
7755 if (AOP_SIZE (result) > 1)
7756 aopPut (AOP (result), "a", offset++);
7758 _endLazyDPSEvaluation ();
7760 /* now we need to put the carry into the
7761 highest order byte of the result */
7762 if (AOP_SIZE (result) > 1)
7764 l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7767 emitcode ("mov", "acc.0,c");
7768 aopPut (AOP (result), "a", 0);
7769 freeAsmop (left, NULL, ic, TRUE);
7770 freeAsmop (result, NULL, ic, TRUE);
7773 /*-----------------------------------------------------------------*/
7774 /* genGetHbit - generates code get highest order bit */
7775 /*-----------------------------------------------------------------*/
7777 genGetHbit (iCode * ic)
7779 operand *left, *result;
7780 left = IC_LEFT (ic);
7781 result = IC_RESULT (ic);
7782 aopOp (left, ic, FALSE, FALSE);
7783 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7785 D (emitcode (";", "genGetHbit "););
7787 /* get the highest order byte into a */
7788 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7789 if (AOP_TYPE (result) == AOP_CRY)
7791 emitcode ("rlc", "a");
7796 emitcode ("rl", "a");
7797 emitcode ("anl", "a,#1");
7802 freeAsmop (left, NULL, ic, TRUE);
7803 freeAsmop (result, NULL, ic, TRUE);
7806 /*-----------------------------------------------------------------*/
7807 /* genSwap - generates code to swap nibbles or bytes */
7808 /*-----------------------------------------------------------------*/
7810 genSwap (iCode * ic)
7812 operand *left, *result;
7814 D(emitcode ("; genSwap",""));
7816 left = IC_LEFT (ic);
7817 result = IC_RESULT (ic);
7818 aopOp (left, ic, FALSE, FALSE);
7819 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7821 _startLazyDPSEvaluation ();
7822 switch (AOP_SIZE (left))
7824 case 1: /* swap nibbles in byte */
7825 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7826 emitcode ("swap", "a");
7827 aopPut (AOP (result), "a", 0);
7829 case 2: /* swap bytes in word */
7830 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7832 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7833 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7834 aopPut (AOP (result), "a", 1);
7836 else if (operandsEqu (left, result))
7839 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7840 if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
7842 emitcode ("mov", "b,a");
7846 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7847 aopPut (AOP (result), reg, 1);
7852 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7853 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE, NULL), 1);
7857 wassertl(FALSE, "unsupported SWAP operand size");
7859 _endLazyDPSEvaluation ();
7861 freeAsmop (left, NULL, ic, TRUE);
7862 freeAsmop (result, NULL, ic, TRUE);
7865 /*-----------------------------------------------------------------*/
7866 /* AccRol - rotate left accumulator by known count */
7867 /*-----------------------------------------------------------------*/
7869 AccRol (int shCount)
7871 shCount &= 0x0007; // shCount : 0..7
7878 emitcode ("rl", "a");
7881 emitcode ("rl", "a");
7882 emitcode ("rl", "a");
7885 emitcode ("swap", "a");
7886 emitcode ("rr", "a");
7889 emitcode ("swap", "a");
7892 emitcode ("swap", "a");
7893 emitcode ("rl", "a");
7896 emitcode ("rr", "a");
7897 emitcode ("rr", "a");
7900 emitcode ("rr", "a");
7905 /*-----------------------------------------------------------------*/
7906 /* AccLsh - left shift accumulator by known count */
7907 /*-----------------------------------------------------------------*/
7909 AccLsh (int shCount)
7914 emitcode ("add", "a,acc");
7915 else if (shCount == 2)
7917 emitcode ("add", "a,acc");
7918 emitcode ("add", "a,acc");
7922 /* rotate left accumulator */
7924 /* and kill the lower order bits */
7925 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7930 /*-----------------------------------------------------------------*/
7931 /* AccRsh - right shift accumulator by known count */
7932 /*-----------------------------------------------------------------*/
7934 AccRsh (int shCount)
7941 emitcode ("rrc", "a");
7945 /* rotate right accumulator */
7946 AccRol (8 - shCount);
7947 /* and kill the higher order bits */
7948 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7953 #ifdef BETTER_LITERAL_SHIFT
7954 /*-----------------------------------------------------------------*/
7955 /* AccSRsh - signed right shift accumulator by known count */
7956 /*-----------------------------------------------------------------*/
7958 AccSRsh (int shCount)
7965 emitcode ("mov", "c,acc.7");
7966 emitcode ("rrc", "a");
7968 else if (shCount == 2)
7970 emitcode ("mov", "c,acc.7");
7971 emitcode ("rrc", "a");
7972 emitcode ("mov", "c,acc.7");
7973 emitcode ("rrc", "a");
7977 tlbl = newiTempLabel (NULL);
7978 /* rotate right accumulator */
7979 AccRol (8 - shCount);
7980 /* and kill the higher order bits */
7981 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7982 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7983 emitcode ("orl", "a,#!constbyte",
7984 (unsigned char) ~SRMask[shCount]);
7985 emitcode ("", "!tlabeldef", tlbl->key + 100);
7991 #ifdef BETTER_LITERAL_SHIFT
7992 /*-----------------------------------------------------------------*/
7993 /* shiftR1Left2Result - shift right one byte from left to result */
7994 /*-----------------------------------------------------------------*/
7996 shiftR1Left2Result (operand * left, int offl,
7997 operand * result, int offr,
7998 int shCount, int sign)
8000 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8001 /* shift right accumulator */
8006 aopPut (AOP (result), "a", offr);
8010 #ifdef BETTER_LITERAL_SHIFT
8011 /*-----------------------------------------------------------------*/
8012 /* shiftL1Left2Result - shift left one byte from left to result */
8013 /*-----------------------------------------------------------------*/
8015 shiftL1Left2Result (operand * left, int offl,
8016 operand * result, int offr, int shCount)
8018 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8019 /* shift left accumulator */
8021 aopPut (AOP (result), "a", offr);
8025 #ifdef BETTER_LITERAL_SHIFT
8026 /*-----------------------------------------------------------------*/
8027 /* movLeft2Result - move byte from left to result */
8028 /*-----------------------------------------------------------------*/
8030 movLeft2Result (operand * left, int offl,
8031 operand * result, int offr, int sign)
8034 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8036 l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
8038 if (*l == '@' && (IS_AOP_PREG (result)))
8040 emitcode ("mov", "a,%s", l);
8041 aopPut (AOP (result), "a", offr);
8047 aopPut (AOP (result), l, offr);
8051 /* MSB sign in acc.7 ! */
8052 if (getDataSize (left) == offl + 1)
8054 emitcode ("mov", "a,%s", l);
8055 aopPut (AOP (result), "a", offr);
8063 #ifdef BETTER_LITERAL_SHIFT
8064 /*-----------------------------------------------------------------*/
8065 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8066 /*-----------------------------------------------------------------*/
8070 emitcode ("rrc", "a");
8071 emitcode ("xch", "a,%s", x);
8072 emitcode ("rrc", "a");
8073 emitcode ("xch", "a,%s", x);
8077 #ifdef BETTER_LITERAL_SHIFT
8079 /*-----------------------------------------------------------------*/
8080 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8081 /*-----------------------------------------------------------------*/
8085 emitcode ("xch", "a,%s", x);
8086 emitcode ("rlc", "a");
8087 emitcode ("xch", "a,%s", x);
8088 emitcode ("rlc", "a");
8092 #ifdef BETTER_LITERAL_SHIFT
8093 /*-----------------------------------------------------------------*/
8094 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8095 /*-----------------------------------------------------------------*/
8099 emitcode ("xch", "a,%s", x);
8100 emitcode ("add", "a,acc");
8101 emitcode ("xch", "a,%s", x);
8102 emitcode ("rlc", "a");
8106 #ifdef BETTER_LITERAL_SHIFT
8107 /*-----------------------------------------------------------------*/
8108 /* AccAXLsh - left shift a:x by known count (0..7) */
8109 /*-----------------------------------------------------------------*/
8111 AccAXLsh (char *x, int shCount)
8126 case 5: // AAAAABBB:CCCCCDDD
8128 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8130 emitcode ("anl", "a,#!constbyte",
8131 SLMask[shCount]); // BBB00000:CCCCCDDD
8133 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8135 AccRol (shCount); // DDDCCCCC:BBB00000
8137 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8139 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8141 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8143 emitcode ("anl", "a,#!constbyte",
8144 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8146 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8148 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8151 case 6: // AAAAAABB:CCCCCCDD
8152 emitcode ("anl", "a,#!constbyte",
8153 SRMask[shCount]); // 000000BB:CCCCCCDD
8154 emitcode ("mov", "c,acc.0"); // c = B
8155 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8157 AccAXRrl1 (x); // BCCCCCCD:D000000B
8158 AccAXRrl1 (x); // BBCCCCCC:DD000000
8160 emitcode("rrc","a");
8161 emitcode("xch","a,%s", x);
8162 emitcode("rrc","a");
8163 emitcode("mov","c,acc.0"); //<< get correct bit
8164 emitcode("xch","a,%s", x);
8166 emitcode("rrc","a");
8167 emitcode("xch","a,%s", x);
8168 emitcode("rrc","a");
8169 emitcode("xch","a,%s", x);
8172 case 7: // a:x <<= 7
8174 emitcode ("anl", "a,#!constbyte",
8175 SRMask[shCount]); // 0000000B:CCCCCCCD
8177 emitcode ("mov", "c,acc.0"); // c = B
8179 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8181 AccAXRrl1 (x); // BCCCCCCC:D0000000
8190 #ifdef BETTER_LITERAL_SHIFT
8192 /*-----------------------------------------------------------------*/
8193 /* AccAXRsh - right shift a:x known count (0..7) */
8194 /*-----------------------------------------------------------------*/
8196 AccAXRsh (char *x, int shCount)
8204 AccAXRrl1 (x); // 0->a:x
8209 AccAXRrl1 (x); // 0->a:x
8212 AccAXRrl1 (x); // 0->a:x
8217 case 5: // AAAAABBB:CCCCCDDD = a:x
8219 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8221 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8223 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8225 emitcode ("anl", "a,#!constbyte",
8226 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8228 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8230 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8232 emitcode ("anl", "a,#!constbyte",
8233 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8235 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8237 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8239 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8242 case 6: // AABBBBBB:CCDDDDDD
8244 emitcode ("mov", "c,acc.7");
8245 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8247 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8249 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8251 emitcode ("anl", "a,#!constbyte",
8252 SRMask[shCount]); // 000000AA:BBBBBBCC
8255 case 7: // ABBBBBBB:CDDDDDDD
8257 emitcode ("mov", "c,acc.7"); // c = A
8259 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8261 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8263 emitcode ("anl", "a,#!constbyte",
8264 SRMask[shCount]); // 0000000A:BBBBBBBC
8273 #ifdef BETTER_LITERAL_SHIFT
8274 /*-----------------------------------------------------------------*/
8275 /* AccAXRshS - right shift signed a:x known count (0..7) */
8276 /*-----------------------------------------------------------------*/
8278 AccAXRshS (char *x, int shCount)
8286 emitcode ("mov", "c,acc.7");
8287 AccAXRrl1 (x); // s->a:x
8291 emitcode ("mov", "c,acc.7");
8292 AccAXRrl1 (x); // s->a:x
8294 emitcode ("mov", "c,acc.7");
8295 AccAXRrl1 (x); // s->a:x
8300 case 5: // AAAAABBB:CCCCCDDD = a:x
8302 tlbl = newiTempLabel (NULL);
8303 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8305 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8307 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8309 emitcode ("anl", "a,#!constbyte",
8310 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8312 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8314 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8316 emitcode ("anl", "a,#!constbyte",
8317 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8319 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8321 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8323 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8325 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8326 emitcode ("orl", "a,#!constbyte",
8327 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8329 emitcode ("", "!tlabeldef", tlbl->key + 100);
8330 break; // SSSSAAAA:BBBCCCCC
8332 case 6: // AABBBBBB:CCDDDDDD
8334 tlbl = newiTempLabel (NULL);
8335 emitcode ("mov", "c,acc.7");
8336 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8338 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8340 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8342 emitcode ("anl", "a,#!constbyte",
8343 SRMask[shCount]); // 000000AA:BBBBBBCC
8345 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8346 emitcode ("orl", "a,#!constbyte",
8347 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8349 emitcode ("", "!tlabeldef", tlbl->key + 100);
8351 case 7: // ABBBBBBB:CDDDDDDD
8353 tlbl = newiTempLabel (NULL);
8354 emitcode ("mov", "c,acc.7"); // c = A
8356 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8358 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8360 emitcode ("anl", "a,#!constbyte",
8361 SRMask[shCount]); // 0000000A:BBBBBBBC
8363 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8364 emitcode ("orl", "a,#!constbyte",
8365 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8367 emitcode ("", "!tlabeldef", tlbl->key + 100);
8375 #ifdef BETTER_LITERAL_SHIFT
8377 _loadLeftIntoAx(char **lsb,
8383 // Get the initial value from left into a pair of registers.
8384 // MSB must be in A, LSB can be any register.
8386 // If the result is held in registers, it is an optimization
8387 // if the LSB can be held in the register which will hold the,
8388 // result LSB since this saves us from having to copy it into
8389 // the result following AccAXLsh.
8391 // If the result is addressed indirectly, this is not a gain.
8392 if (AOP_NEEDSACC(result))
8396 _startLazyDPSEvaluation();
8397 if (AOP_TYPE(left) == AOP_DPTR2)
8400 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
8401 // get LSB in DP2_RESULT_REG.
8402 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
8403 assert(!strcmp(leftByte, DP2_RESULT_REG));
8407 // get LSB into DP2_RESULT_REG
8408 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
8409 if (strcmp(leftByte, DP2_RESULT_REG))
8412 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
8415 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
8416 assert(strcmp(leftByte, DP2_RESULT_REG));
8419 _endLazyDPSEvaluation();
8420 *lsb = DP2_RESULT_REG;
8424 if (sameRegs (AOP (result), AOP (left)) &&
8425 ((offl + MSB16) == offr))
8427 /* don't crash result[offr] */
8428 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
8429 emitcode ("xch", "a,%s",
8430 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
8434 movLeft2Result (left, offl, result, offr, 0);
8435 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
8437 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
8438 assert(strcmp(*lsb,"a"));
8443 _storeAxResults(char *lsb,
8447 _startLazyDPSEvaluation();
8448 if (AOP_NEEDSACC(result))
8450 /* We have to explicitly update the result LSB.
8452 emitcode("xch","a,%s", lsb);
8453 aopPut(AOP(result), "a", offr);
8454 emitcode("mov","a,%s", lsb);
8456 if (getDataSize (result) > 1)
8458 aopPut (AOP (result), "a", offr + MSB16);
8460 _endLazyDPSEvaluation();
8463 /*-----------------------------------------------------------------*/
8464 /* shiftL2Left2Result - shift left two bytes from left to result */
8465 /*-----------------------------------------------------------------*/
8467 shiftL2Left2Result (operand * left, int offl,
8468 operand * result, int offr, int shCount)
8472 _loadLeftIntoAx(&lsb, left, result, offl, offr);
8474 AccAXLsh (lsb, shCount);
8476 _storeAxResults(lsb, result, offr);
8480 #ifdef BETTER_LITERAL_SHIFT
8481 /*-----------------------------------------------------------------*/
8482 /* shiftR2Left2Result - shift right two bytes from left to result */
8483 /*-----------------------------------------------------------------*/
8485 shiftR2Left2Result (operand * left, int offl,
8486 operand * result, int offr,
8487 int shCount, int sign)
8491 _loadLeftIntoAx(&lsb, left, result, offl, offr);
8493 /* a:x >> shCount (x = lsb(result)) */
8496 AccAXRshS(lsb, shCount);
8500 AccAXRsh(lsb, shCount);
8503 _storeAxResults(lsb, result, offr);
8507 /*-----------------------------------------------------------------*/
8508 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8509 /*-----------------------------------------------------------------*/
8511 shiftLLeftOrResult (operand * left, int offl,
8512 operand * result, int offr, int shCount)
8514 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8515 /* shift left accumulator */
8517 /* or with result */
8518 emitcode ("orl", "a,%s",
8519 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8520 /* back to result */
8521 aopPut (AOP (result), "a", offr);
8526 /*-----------------------------------------------------------------*/
8527 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8528 /*-----------------------------------------------------------------*/
8530 shiftRLeftOrResult (operand * left, int offl,
8531 operand * result, int offr, int shCount)
8533 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8534 /* shift right accumulator */
8536 /* or with result */
8537 emitcode ("orl", "a,%s",
8538 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8539 /* back to result */
8540 aopPut (AOP (result), "a", offr);
8544 #ifdef BETTER_LITERAL_SHIFT
8545 /*-----------------------------------------------------------------*/
8546 /* genlshOne - left shift a one byte quantity by known count */
8547 /*-----------------------------------------------------------------*/
8549 genlshOne (operand * result, operand * left, int shCount)
8551 D (emitcode (";", "genlshOne "););
8552 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8556 #ifdef BETTER_LITERAL_SHIFT
8557 /*-----------------------------------------------------------------*/
8558 /* genlshTwo - left shift two bytes by known amount != 0 */
8559 /*-----------------------------------------------------------------*/
8561 genlshTwo (operand * result, operand * left, int shCount)
8565 D (emitcode (";", "genlshTwo "););
8567 size = getDataSize (result);
8569 /* if shCount >= 8 */
8574 _startLazyDPSEvaluation();
8580 _endLazyDPSEvaluation();
8581 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8582 aopPut (AOP (result), zero, LSB);
8586 movLeft2Result (left, LSB, result, MSB16, 0);
8587 aopPut (AOP (result), zero, LSB);
8588 _endLazyDPSEvaluation();
8593 aopPut (AOP (result), zero, LSB);
8594 _endLazyDPSEvaluation();
8598 /* 1 <= shCount <= 7 */
8603 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8607 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8615 /*-----------------------------------------------------------------*/
8616 /* shiftLLong - shift left one long from left to result */
8617 /* offl = LSB or MSB16 */
8618 /*-----------------------------------------------------------------*/
8620 shiftLLong (operand * left, operand * result, int offr)
8623 int size = AOP_SIZE (result);
8625 if (size >= LSB + offr)
8627 l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8629 emitcode ("add", "a,acc");
8630 if (sameRegs (AOP (left), AOP (result)) &&
8631 size >= MSB16 + offr && offr != LSB)
8632 emitcode ("xch", "a,%s",
8633 aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8635 aopPut (AOP (result), "a", LSB + offr);
8638 if (size >= MSB16 + offr)
8640 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8642 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8644 emitcode ("rlc", "a");
8645 if (sameRegs (AOP (left), AOP (result)) &&
8646 size >= MSB24 + offr && offr != LSB)
8647 emitcode ("xch", "a,%s",
8648 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8650 aopPut (AOP (result), "a", MSB16 + offr);
8653 if (size >= MSB24 + offr)
8655 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8657 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8659 emitcode ("rlc", "a");
8660 if (sameRegs (AOP (left), AOP (result)) &&
8661 size >= MSB32 + offr && offr != LSB)
8662 emitcode ("xch", "a,%s",
8663 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8665 aopPut (AOP (result), "a", MSB24 + offr);
8668 if (size > MSB32 + offr)
8670 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8672 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8674 emitcode ("rlc", "a");
8675 aopPut (AOP (result), "a", MSB32 + offr);
8678 aopPut (AOP (result), zero, LSB);
8684 /*-----------------------------------------------------------------*/
8685 /* genlshFour - shift four byte by a known amount != 0 */
8686 /*-----------------------------------------------------------------*/
8688 genlshFour (operand * result, operand * left, int shCount)
8692 D (emitcode (";", "genlshFour ");
8695 size = AOP_SIZE (result);
8697 /* if shifting more that 3 bytes */
8702 /* lowest order of left goes to the highest
8703 order of the destination */
8704 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8706 movLeft2Result (left, LSB, result, MSB32, 0);
8707 aopPut (AOP (result), zero, LSB);
8708 aopPut (AOP (result), zero, MSB16);
8709 aopPut (AOP (result), zero, MSB24);
8713 /* more than two bytes */
8714 else if (shCount >= 16)
8716 /* lower order two bytes goes to higher order two bytes */
8718 /* if some more remaining */
8720 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8723 movLeft2Result (left, MSB16, result, MSB32, 0);
8724 movLeft2Result (left, LSB, result, MSB24, 0);
8726 aopPut (AOP (result), zero, MSB16);
8727 aopPut (AOP (result), zero, LSB);
8731 /* if more than 1 byte */
8732 else if (shCount >= 8)
8734 /* lower order three bytes goes to higher order three bytes */
8739 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8741 movLeft2Result (left, LSB, result, MSB16, 0);
8747 movLeft2Result (left, MSB24, result, MSB32, 0);
8748 movLeft2Result (left, MSB16, result, MSB24, 0);
8749 movLeft2Result (left, LSB, result, MSB16, 0);
8750 aopPut (AOP (result), zero, LSB);
8752 else if (shCount == 1)
8753 shiftLLong (left, result, MSB16);
8756 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8757 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8758 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8759 aopPut (AOP (result), zero, LSB);
8764 /* 1 <= shCount <= 7 */
8765 else if (shCount <= 2)
8767 shiftLLong (left, result, LSB);
8769 shiftLLong (result, result, LSB);
8771 /* 3 <= shCount <= 7, optimize */
8774 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8775 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8776 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8781 #ifdef BETTER_LITERAL_SHIFT
8782 /*-----------------------------------------------------------------*/
8783 /* genLeftShiftLiteral - left shifting by known count */
8784 /*-----------------------------------------------------------------*/
8786 genLeftShiftLiteral (operand * left,
8791 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8794 size = getSize (operandType (result));
8796 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8798 /* We only handle certain easy cases so far. */
8800 && (shCount < (size * 8))
8804 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8808 freeAsmop (right, NULL, ic, TRUE);
8810 aopOp(left, ic, FALSE, FALSE);
8811 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8814 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8816 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8817 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8819 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8822 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8824 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8825 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8827 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8833 emitcode ("; shift left ", "result %d, left %d", size,
8837 /* I suppose that the left size >= result size */
8840 _startLazyDPSEvaluation();
8843 movLeft2Result (left, size, result, size, 0);
8845 _endLazyDPSEvaluation();
8847 else if (shCount >= (size * 8))
8849 _startLazyDPSEvaluation();
8852 aopPut (AOP (result), zero, size);
8854 _endLazyDPSEvaluation();
8861 genlshOne (result, left, shCount);
8865 genlshTwo (result, left, shCount);
8869 genlshFour (result, left, shCount);
8873 fprintf(stderr, "*** ack! mystery literal shift!\n");
8877 freeAsmop (left, NULL, ic, TRUE);
8878 freeAsmop (result, NULL, ic, TRUE);
8883 /*-----------------------------------------------------------------*/
8884 /* genLeftShift - generates code for left shifting */
8885 /*-----------------------------------------------------------------*/
8887 genLeftShift (iCode * ic)
8889 operand *left, *right, *result;
8892 symbol *tlbl, *tlbl1;
8894 D (emitcode (";", "genLeftShift "););
8896 right = IC_RIGHT (ic);
8897 left = IC_LEFT (ic);
8898 result = IC_RESULT (ic);
8900 aopOp (right, ic, FALSE, FALSE);
8903 #ifdef BETTER_LITERAL_SHIFT
8904 /* if the shift count is known then do it
8905 as efficiently as possible */
8906 if (AOP_TYPE (right) == AOP_LIT)
8908 if (genLeftShiftLiteral (left, right, result, ic))
8915 /* shift count is unknown then we have to form
8916 a loop get the loop count in B : Note: we take
8917 only the lower order byte since shifting
8918 more that 32 bits make no sense anyway, ( the
8919 largest size of an object can be only 32 bits ) */
8921 if (AOP_TYPE (right) == AOP_LIT)
8923 /* Really should be handled by genLeftShiftLiteral,
8924 * but since I'm too lazy to fix that today, at least we can make
8925 * some small improvement.
8927 emitcode("mov", "b,#!constbyte",
8928 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8932 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8933 emitcode ("inc", "b");
8935 freeAsmop (right, NULL, ic, TRUE);
8936 aopOp (left, ic, FALSE, FALSE);
8937 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8939 /* now move the left to the result if they are not the
8941 if (!sameRegs (AOP (left), AOP (result)) &&
8942 AOP_SIZE (result) > 1)
8945 size = AOP_SIZE (result);
8947 _startLazyDPSEvaluation ();
8950 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8951 if (*l == '@' && (IS_AOP_PREG (result)))
8954 emitcode ("mov", "a,%s", l);
8955 aopPut (AOP (result), "a", offset);
8958 aopPut (AOP (result), l, offset);
8961 _endLazyDPSEvaluation ();
8964 tlbl = newiTempLabel (NULL);
8965 size = AOP_SIZE (result);
8967 tlbl1 = newiTempLabel (NULL);
8969 /* if it is only one byte then */
8972 symbol *tlbl1 = newiTempLabel (NULL);
8974 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8975 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8976 emitcode ("", "!tlabeldef", tlbl->key + 100);
8977 emitcode ("add", "a,acc");
8978 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8979 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8980 aopPut (AOP (result), "a", 0);
8984 reAdjustPreg (AOP (result));
8986 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8987 emitcode ("", "!tlabeldef", tlbl->key + 100);
8988 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8989 emitcode ("add", "a,acc");
8990 aopPut (AOP (result), "a", offset++);
8991 _startLazyDPSEvaluation ();
8994 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8995 emitcode ("rlc", "a");
8996 aopPut (AOP (result), "a", offset++);
8998 _endLazyDPSEvaluation ();
8999 reAdjustPreg (AOP (result));
9001 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9002 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9004 freeAsmop (left, NULL, ic, TRUE);
9005 freeAsmop (result, NULL, ic, TRUE);
9008 #ifdef BETTER_LITERAL_SHIFT
9009 /*-----------------------------------------------------------------*/
9010 /* genrshOne - right shift a one byte quantity by known count */
9011 /*-----------------------------------------------------------------*/
9013 genrshOne (operand * result, operand * left,
9014 int shCount, int sign)
9016 D (emitcode (";", "genrshOne"););
9017 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9021 #ifdef BETTER_LITERAL_SHIFT
9022 /*-----------------------------------------------------------------*/
9023 /* genrshTwo - right shift two bytes by known amount != 0 */
9024 /*-----------------------------------------------------------------*/
9026 genrshTwo (operand * result, operand * left,
9027 int shCount, int sign)
9029 D (emitcode (";", "genrshTwo"););
9031 /* if shCount >= 8 */
9035 _startLazyDPSEvaluation();
9038 shiftR1Left2Result (left, MSB16, result, LSB,
9043 movLeft2Result (left, MSB16, result, LSB, sign);
9045 addSign (result, MSB16, sign);
9046 _endLazyDPSEvaluation();
9049 /* 1 <= shCount <= 7 */
9052 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9057 /*-----------------------------------------------------------------*/
9058 /* shiftRLong - shift right one long from left to result */
9059 /* offl = LSB or MSB16 */
9060 /*-----------------------------------------------------------------*/
9062 shiftRLong (operand * left, int offl,
9063 operand * result, int sign)
9065 int isSameRegs=sameRegs(AOP(left),AOP(result));
9067 if (isSameRegs && offl>1) {
9068 // we are in big trouble, but this shouldn't happen
9069 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9072 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
9077 emitcode ("rlc", "a");
9078 emitcode ("subb", "a,acc");
9079 emitcode ("xch", "a,%s",
9080 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
9082 aopPut (AOP(result), zero, MSB32);
9087 emitcode ("clr", "c");
9089 emitcode ("mov", "c,acc.7");
9092 emitcode ("rrc", "a");
9094 if (isSameRegs && offl==MSB16) {
9096 "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
9098 aopPut (AOP (result), "a", MSB32);
9099 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
9102 emitcode ("rrc", "a");
9103 if (isSameRegs && offl==1) {
9104 emitcode ("xch", "a,%s",
9105 aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
9107 aopPut (AOP (result), "a", MSB24);
9108 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
9110 emitcode ("rrc", "a");
9111 aopPut (AOP (result), "a", MSB16 - offl);
9115 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
9116 emitcode ("rrc", "a");
9117 aopPut (AOP (result), "a", LSB);
9121 /*-----------------------------------------------------------------*/
9122 /* genrshFour - shift four byte by a known amount != 0 */
9123 /*-----------------------------------------------------------------*/
9125 genrshFour (operand * result, operand * left,
9126 int shCount, int sign)
9128 D (emitcode (";", "genrshFour"););
9130 /* if shifting more that 3 bytes */
9134 _startLazyDPSEvaluation();
9136 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9138 movLeft2Result (left, MSB32, result, LSB, sign);
9139 addSign (result, MSB16, sign);
9140 _endLazyDPSEvaluation();
9142 else if (shCount >= 16)
9145 _startLazyDPSEvaluation();
9147 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9150 movLeft2Result (left, MSB24, result, LSB, 0);
9151 movLeft2Result (left, MSB32, result, MSB16, sign);
9153 addSign (result, MSB24, sign);
9154 _endLazyDPSEvaluation();
9156 else if (shCount >= 8)
9159 _startLazyDPSEvaluation();
9162 shiftRLong (left, MSB16, result, sign);
9164 else if (shCount == 0)
9166 movLeft2Result (left, MSB16, result, LSB, 0);
9167 movLeft2Result (left, MSB24, result, MSB16, 0);
9168 movLeft2Result (left, MSB32, result, MSB24, sign);
9169 addSign (result, MSB32, sign);
9173 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9174 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9175 /* the last shift is signed */
9176 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9177 addSign (result, MSB32, sign);
9179 _endLazyDPSEvaluation();
9183 /* 1 <= shCount <= 7 */
9186 shiftRLong (left, LSB, result, sign);
9188 shiftRLong (result, LSB, result, sign);
9192 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9193 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9194 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9199 #ifdef BETTER_LITERAL_SHIFT
9200 /*-----------------------------------------------------------------*/
9201 /* genRightShiftLiteral - right shifting by known count */
9202 /*-----------------------------------------------------------------*/
9204 genRightShiftLiteral (operand * left,
9210 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9213 size = getSize (operandType (result));
9215 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
9217 /* We only handle certain easy cases so far. */
9219 && (shCount < (size * 8))
9224 D(emitcode (";", "genRightShiftLiteral wimping out"););
9228 freeAsmop (right, NULL, ic, TRUE);
9230 aopOp (left, ic, FALSE, FALSE);
9231 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9234 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9238 /* test the LEFT size !!! */
9240 /* I suppose that the left size >= result size */
9243 size = getDataSize (result);
9244 _startLazyDPSEvaluation();
9247 movLeft2Result (left, size, result, size, 0);
9249 _endLazyDPSEvaluation();
9251 else if (shCount >= (size * 8))
9255 /* get sign in acc.7 */
9256 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
9258 addSign (result, LSB, sign);
9265 genrshOne (result, left, shCount, sign);
9269 genrshTwo (result, left, shCount, sign);
9273 genrshFour (result, left, shCount, sign);
9280 freeAsmop (left, NULL, ic, TRUE);
9281 freeAsmop (result, NULL, ic, TRUE);
9287 /*-----------------------------------------------------------------*/
9288 /* genSignedRightShift - right shift of signed number */
9289 /*-----------------------------------------------------------------*/
9291 genSignedRightShift (iCode * ic)
9293 operand *right, *left, *result;
9296 symbol *tlbl, *tlbl1;
9298 D (emitcode (";", "genSignedRightShift "););
9300 /* we do it the hard way put the shift count in b
9301 and loop thru preserving the sign */
9303 right = IC_RIGHT (ic);
9304 left = IC_LEFT (ic);
9305 result = IC_RESULT (ic);
9307 aopOp (right, ic, FALSE, FALSE);
9309 #ifdef BETTER_LITERAL_SHIFT
9310 if (AOP_TYPE (right) == AOP_LIT)
9312 if (genRightShiftLiteral (left, right, result, ic, 1))
9318 /* shift count is unknown then we have to form
9319 a loop get the loop count in B : Note: we take
9320 only the lower order byte since shifting
9321 more that 32 bits make no sense anyway, ( the
9322 largest size of an object can be only 32 bits ) */
9324 if (AOP_TYPE (right) == AOP_LIT)
9326 /* Really should be handled by genRightShiftLiteral,
9327 * but since I'm too lazy to fix that today, at least we can make
9328 * some small improvement.
9330 emitcode("mov", "b,#!constbyte",
9331 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9335 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9336 emitcode ("inc", "b");
9338 freeAsmop (right, NULL, ic, TRUE);
9339 aopOp (left, ic, FALSE, FALSE);
9340 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9342 /* now move the left to the result if they are not the
9344 if (!sameRegs (AOP (left), AOP (result)) &&
9345 AOP_SIZE (result) > 1)
9348 size = AOP_SIZE (result);
9350 _startLazyDPSEvaluation ();
9353 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9354 if (*l == '@' && IS_AOP_PREG (result))
9357 emitcode ("mov", "a,%s", l);
9358 aopPut (AOP (result), "a", offset);
9361 aopPut (AOP (result), l, offset);
9364 _endLazyDPSEvaluation ();
9367 /* mov the highest order bit to OVR */
9368 tlbl = newiTempLabel (NULL);
9369 tlbl1 = newiTempLabel (NULL);
9371 size = AOP_SIZE (result);
9373 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
9374 emitcode ("rlc", "a");
9375 emitcode ("mov", "ov,c");
9376 /* if it is only one byte then */
9379 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9380 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9381 emitcode ("", "!tlabeldef", tlbl->key + 100);
9382 emitcode ("mov", "c,ov");
9383 emitcode ("rrc", "a");
9384 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9385 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9386 aopPut (AOP (result), "a", 0);
9390 reAdjustPreg (AOP (result));
9391 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9392 emitcode ("", "!tlabeldef", tlbl->key + 100);
9393 emitcode ("mov", "c,ov");
9394 _startLazyDPSEvaluation ();
9397 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9398 emitcode ("rrc", "a");
9399 aopPut (AOP (result), "a", offset--);
9401 _endLazyDPSEvaluation ();
9402 reAdjustPreg (AOP (result));
9403 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9404 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9407 freeAsmop (left, NULL, ic, TRUE);
9408 freeAsmop (result, NULL, ic, TRUE);
9411 /*-----------------------------------------------------------------*/
9412 /* genRightShift - generate code for right shifting */
9413 /*-----------------------------------------------------------------*/
9415 genRightShift (iCode * ic)
9417 operand *right, *left, *result;
9421 symbol *tlbl, *tlbl1;
9423 D (emitcode (";", "genRightShift "););
9425 /* if signed then we do it the hard way preserve the
9426 sign bit moving it inwards */
9427 letype = getSpec (operandType (IC_LEFT (ic)));
9429 if (!SPEC_USIGN (letype))
9431 genSignedRightShift (ic);
9435 /* signed & unsigned types are treated the same : i.e. the
9436 signed is NOT propagated inwards : quoting from the
9437 ANSI - standard : "for E1 >> E2, is equivalent to division
9438 by 2**E2 if unsigned or if it has a non-negative value,
9439 otherwise the result is implementation defined ", MY definition
9440 is that the sign does not get propagated */
9442 right = IC_RIGHT (ic);
9443 left = IC_LEFT (ic);
9444 result = IC_RESULT (ic);
9446 aopOp (right, ic, FALSE, FALSE);
9448 #ifdef BETTER_LITERAL_SHIFT
9449 /* if the shift count is known then do it
9450 as efficiently as possible */
9451 if (AOP_TYPE (right) == AOP_LIT)
9453 if (genRightShiftLiteral (left, right, result, ic, 0))
9460 /* shift count is unknown then we have to form
9461 a loop get the loop count in B : Note: we take
9462 only the lower order byte since shifting
9463 more that 32 bits make no sense anyway, ( the
9464 largest size of an object can be only 32 bits ) */
9466 if (AOP_TYPE (right) == AOP_LIT)
9468 /* Really should be handled by genRightShiftLiteral,
9469 * but since I'm too lazy to fix that today, at least we can make
9470 * some small improvement.
9472 emitcode("mov", "b,#!constbyte",
9473 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9477 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9478 emitcode ("inc", "b");
9480 freeAsmop (right, NULL, ic, TRUE);
9481 aopOp (left, ic, FALSE, FALSE);
9482 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9484 /* now move the left to the result if they are not the
9486 if (!sameRegs (AOP (left), AOP (result)) &&
9487 AOP_SIZE (result) > 1)
9490 size = AOP_SIZE (result);
9492 _startLazyDPSEvaluation ();
9495 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9496 if (*l == '@' && IS_AOP_PREG (result))
9499 emitcode ("mov", "a,%s", l);
9500 aopPut (AOP (result), "a", offset);
9503 aopPut (AOP (result), l, offset);
9506 _endLazyDPSEvaluation ();
9509 tlbl = newiTempLabel (NULL);
9510 tlbl1 = newiTempLabel (NULL);
9511 size = AOP_SIZE (result);
9514 /* if it is only one byte then */
9517 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9518 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9519 emitcode ("", "!tlabeldef", tlbl->key + 100);
9521 emitcode ("rrc", "a");
9522 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9523 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9524 aopPut (AOP (result), "a", 0);
9528 reAdjustPreg (AOP (result));
9529 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9530 emitcode ("", "!tlabeldef", tlbl->key + 100);
9532 _startLazyDPSEvaluation ();
9535 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9536 emitcode ("rrc", "a");
9537 aopPut (AOP (result), "a", offset--);
9539 _endLazyDPSEvaluation ();
9540 reAdjustPreg (AOP (result));
9542 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9543 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9546 freeAsmop (left, NULL, ic, TRUE);
9547 freeAsmop (result, NULL, ic, TRUE);
9551 /*-----------------------------------------------------------------*/
9552 /* emitPtrByteGet - emits code to get a byte into A through a */
9553 /* pointer register (R0, R1, or DPTR). The */
9554 /* original value of A can be preserved in B. */
9555 /*-----------------------------------------------------------------*/
9557 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9564 emitcode ("mov", "b,a");
9565 emitcode ("mov", "a,@%s", rname);
9570 emitcode ("mov", "b,a");
9571 emitcode ("movx", "a,@%s", rname);
9576 emitcode ("mov", "b,a");
9577 emitcode ("movx", "a,@dptr");
9582 emitcode ("mov", "b,a");
9583 emitcode ("clr", "a");
9584 emitcode ("movc", "a,@a+dptr");
9590 emitcode ("push", "b");
9591 emitcode ("push", "acc");
9593 emitcode ("lcall", "__gptrget");
9595 emitcode ("pop", "b");
9600 /*-----------------------------------------------------------------*/
9601 /* emitPtrByteSet - emits code to set a byte from src through a */
9602 /* pointer register (R0, R1, or DPTR). */
9603 /*-----------------------------------------------------------------*/
9605 emitPtrByteSet (char *rname, int p_type, char *src)
9614 emitcode ("mov", "@%s,a", rname);
9617 emitcode ("mov", "@%s,%s", rname, src);
9622 emitcode ("movx", "@%s,a", rname);
9627 emitcode ("movx", "@dptr,a");
9632 emitcode ("lcall", "__gptrput");
9637 /*-----------------------------------------------------------------*/
9638 /* genUnpackBits - generates code for unpacking bits */
9639 /*-----------------------------------------------------------------*/
9641 genUnpackBits (operand * result, char *rname, int ptype)
9643 int offset = 0; /* result byte offset */
9644 int rsize; /* result size */
9645 int rlen = 0; /* remaining bitfield length */
9646 sym_link *etype; /* bitfield type information */
9647 int blen; /* bitfield length */
9648 int bstr; /* bitfield starting bit within byte */
9650 D(emitcode ("; genUnpackBits",""));
9652 etype = getSpec (operandType (result));
9653 rsize = getSize (operandType (result));
9654 blen = SPEC_BLEN (etype);
9655 bstr = SPEC_BSTR (etype);
9657 /* If the bitfield length is less than a byte */
9660 emitPtrByteGet (rname, ptype, FALSE);
9662 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9663 aopPut (AOP (result), "a", offset++);
9667 /* Bit field did not fit in a byte. Copy all
9668 but the partial byte at the end. */
9669 for (rlen=blen;rlen>=8;rlen-=8)
9671 emitPtrByteGet (rname, ptype, FALSE);
9672 aopPut (AOP (result), "a", offset++);
9674 emitcode ("inc", "%s", rname);
9677 /* Handle the partial byte at the end */
9680 emitPtrByteGet (rname, ptype, FALSE);
9681 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9682 aopPut (AOP (result), "a", offset++);
9690 aopPut (AOP (result), zero, offset++);
9695 /*-----------------------------------------------------------------*/
9696 /* genDataPointerGet - generates code when ptr offset is known */
9697 /*-----------------------------------------------------------------*/
9699 genDataPointerGet (operand * left,
9705 int size, offset = 0;
9706 aopOp (result, ic, TRUE, FALSE);
9708 /* get the string representation of the name */
9709 l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9710 size = AOP_SIZE (result);
9711 _startLazyDPSEvaluation ();
9716 SNPRINTF (buff, sizeof(buff),
9717 "(%s + %d)", l + 1, offset);
9721 SNPRINTF (buff, sizeof(buff),
9724 aopPut (AOP (result), buff, offset++);
9726 _endLazyDPSEvaluation ();
9728 freeAsmop (left, NULL, ic, TRUE);
9729 freeAsmop (result, NULL, ic, TRUE);
9732 /*-----------------------------------------------------------------*/
9733 /* genNearPointerGet - emitcode for near pointer fetch */
9734 /*-----------------------------------------------------------------*/
9736 genNearPointerGet (operand * left,
9744 sym_link *rtype, *retype, *letype;
9745 sym_link *ltype = operandType (left);
9748 rtype = operandType (result);
9749 retype = getSpec (rtype);
9750 letype = getSpec (ltype);
9752 aopOp (left, ic, FALSE, FALSE);
9754 /* if left is rematerialisable and
9755 result is not bitfield variable type and
9756 the left is pointer to data space i.e
9757 lower 128 bytes of space */
9758 if (AOP_TYPE (left) == AOP_IMMD &&
9759 !IS_BITFIELD (retype) &&
9760 !IS_BITFIELD (letype) &&
9761 DCL_TYPE (ltype) == POINTER)
9763 genDataPointerGet (left, result, ic);
9767 /* if the value is already in a pointer register
9768 then don't need anything more */
9769 if (!AOP_INPREG (AOP (left)))
9771 /* otherwise get a free pointer register */
9773 preg = getFreePtr (ic, &aop, FALSE);
9774 emitcode ("mov", "%s,%s",
9776 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9780 rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9782 freeAsmop (left, NULL, ic, TRUE);
9783 aopOp (result, ic, FALSE, FALSE);
9785 /* if bitfield then unpack the bits */
9786 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9787 genUnpackBits (result, rname, POINTER);
9790 /* we have can just get the values */
9791 int size = AOP_SIZE (result);
9796 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9799 emitcode ("mov", "a,@%s", rname);
9800 aopPut (AOP (result), "a", offset);
9804 SNPRINTF (buff, sizeof(buff), "@%s", rname);
9805 aopPut (AOP (result), buff, offset);
9810 emitcode ("inc", "%s", rname);
9815 /* now some housekeeping stuff */
9818 /* we had to allocate for this iCode */
9819 if (pi) { /* post increment present */
9820 aopPut(AOP ( left ),rname,0);
9822 freeAsmop (NULL, aop, ic, TRUE);
9826 /* we did not allocate which means left
9827 already in a pointer register, then
9828 if size > 0 && this could be used again
9829 we have to point it back to where it
9831 if (AOP_SIZE (result) > 1 &&
9832 !OP_SYMBOL (left)->remat &&
9833 (OP_SYMBOL (left)->liveTo > ic->seq ||
9837 int size = AOP_SIZE (result) - 1;
9839 emitcode ("dec", "%s", rname);
9844 freeAsmop (result, NULL, ic, TRUE);
9845 if (pi) pi->generated = 1;
9848 /*-----------------------------------------------------------------*/
9849 /* genPagedPointerGet - emitcode for paged pointer fetch */
9850 /*-----------------------------------------------------------------*/
9852 genPagedPointerGet (operand * left,
9860 sym_link *rtype, *retype, *letype;
9862 rtype = operandType (result);
9863 retype = getSpec (rtype);
9864 letype = getSpec (operandType (left));
9865 aopOp (left, ic, FALSE, FALSE);
9867 /* if the value is already in a pointer register
9868 then don't need anything more */
9869 if (!AOP_INPREG (AOP (left)))
9871 /* otherwise get a free pointer register */
9873 preg = getFreePtr (ic, &aop, FALSE);
9874 emitcode ("mov", "%s,%s",
9876 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9880 rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9882 freeAsmop (left, NULL, ic, TRUE);
9883 aopOp (result, ic, FALSE, FALSE);
9885 /* if bitfield then unpack the bits */
9886 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9887 genUnpackBits (result, rname, PPOINTER);
9890 /* we have can just get the values */
9891 int size = AOP_SIZE (result);
9897 emitcode ("movx", "a,@%s", rname);
9898 aopPut (AOP (result), "a", offset);
9903 emitcode ("inc", "%s", rname);
9907 /* now some housekeeping stuff */
9910 /* we had to allocate for this iCode */
9911 if (pi) aopPut ( AOP (left), rname, 0);
9912 freeAsmop (NULL, aop, ic, TRUE);
9916 /* we did not allocate which means left
9917 already in a pointer register, then
9918 if size > 0 && this could be used again
9919 we have to point it back to where it
9921 if (AOP_SIZE (result) > 1 &&
9922 !OP_SYMBOL (left)->remat &&
9923 (OP_SYMBOL (left)->liveTo > ic->seq ||
9927 int size = AOP_SIZE (result) - 1;
9929 emitcode ("dec", "%s", rname);
9934 freeAsmop (result, NULL, ic, TRUE);
9935 if (pi) pi->generated = 1;
9938 /*-----------------------------------------------------------------*/
9939 /* genFarPointerGet - gget value from far space */
9940 /*-----------------------------------------------------------------*/
9942 genFarPointerGet (operand * left,
9943 operand * result, iCode * ic, iCode *pi)
9945 int size, offset, dopi=1;
9946 sym_link *retype = getSpec (operandType (result));
9947 sym_link *letype = getSpec (operandType (left));
9948 D (emitcode (";", "genFarPointerGet"););
9950 aopOp (left, ic, FALSE, FALSE);
9952 /* if the operand is already in dptr
9953 then we do nothing else we move the value to dptr */
9954 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9956 /* if this is remateriazable */
9957 if (AOP_TYPE (left) == AOP_IMMD)
9959 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9963 /* we need to get it byte by byte */
9964 _startLazyDPSEvaluation ();
9965 if (AOP_TYPE (left) != AOP_DPTR)
9967 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9968 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9969 if (options.model == MODEL_FLAT24)
9970 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9974 /* We need to generate a load to DPTR indirect through DPTR. */
9975 D (emitcode (";", "genFarPointerGet -- indirection special case."););
9976 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9977 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9978 if (options.model == MODEL_FLAT24)
9979 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9980 emitcode ("pop", "dph");
9981 emitcode ("pop", "dpl");
9984 _endLazyDPSEvaluation ();
9987 /* so dptr know contains the address */
9988 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9990 /* if bit then unpack */
9991 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9992 if (AOP_INDPTRn(left)) {
9993 genSetDPTR(AOP(left)->aopu.dptr);
9995 genUnpackBits (result, "dptr", FPOINTER);
9996 if (AOP_INDPTRn(left)) {
10001 size = AOP_SIZE (result);
10004 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10006 genSetDPTR(AOP(left)->aopu.dptr);
10007 emitcode ("movx", "a,@dptr");
10008 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10009 emitcode ("inc", "dptr");
10011 aopPut (AOP (result), "a", offset++);
10014 _startLazyDPSEvaluation ();
10016 if (AOP_INDPTRn(left)) {
10017 genSetDPTR(AOP(left)->aopu.dptr);
10023 emitcode ("movx", "a,@dptr");
10024 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10025 emitcode ("inc", "dptr");
10027 aopPut (AOP (result), "a", offset++);
10029 _endLazyDPSEvaluation ();
10032 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10033 if (!AOP_INDPTRn(left)) {
10034 _startLazyDPSEvaluation ();
10035 aopPut ( AOP (left), "dpl", 0);
10036 aopPut ( AOP (left), "dph", 1);
10037 if (options.model == MODEL_FLAT24)
10038 aopPut ( AOP (left), "dpx", 2);
10039 _endLazyDPSEvaluation ();
10042 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
10043 AOP_SIZE(result) > 1 &&
10045 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
10047 size = AOP_SIZE (result) - 1;
10048 if (AOP_INDPTRn(left)) {
10049 genSetDPTR(AOP(left)->aopu.dptr);
10051 while (size--) emitcode ("lcall","__decdptr");
10052 if (AOP_INDPTRn(left)) {
10057 freeAsmop (left, NULL, ic, TRUE);
10058 freeAsmop (result, NULL, ic, TRUE);
10061 /*-----------------------------------------------------------------*/
10062 /* genCodePointerGet - get value from code space */
10063 /*-----------------------------------------------------------------*/
10065 genCodePointerGet (operand * left,
10066 operand * result, iCode * ic, iCode *pi)
10068 int size, offset, dopi=1;
10069 sym_link *retype = getSpec (operandType (result));
10071 aopOp (left, ic, FALSE, FALSE);
10073 /* if the operand is already in dptr
10074 then we do nothing else we move the value to dptr */
10075 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
10077 /* if this is remateriazable */
10078 if (AOP_TYPE (left) == AOP_IMMD)
10080 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10083 { /* we need to get it byte by byte */
10084 _startLazyDPSEvaluation ();
10085 if (AOP_TYPE (left) != AOP_DPTR)
10087 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10088 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10089 if (options.model == MODEL_FLAT24)
10090 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10094 /* We need to generate a load to DPTR indirect through DPTR. */
10095 D (emitcode (";", "gencodePointerGet -- indirection special case."););
10096 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
10097 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
10098 if (options.model == MODEL_FLAT24)
10099 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10100 emitcode ("pop", "dph");
10101 emitcode ("pop", "dpl");
10104 _endLazyDPSEvaluation ();
10107 /* so dptr know contains the address */
10108 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10110 /* if bit then unpack */
10111 if (IS_BITFIELD (retype)) {
10112 if (AOP_INDPTRn(left)) {
10113 genSetDPTR(AOP(left)->aopu.dptr);
10115 genUnpackBits (result, "dptr", CPOINTER);
10116 if (AOP_INDPTRn(left)) {
10121 size = AOP_SIZE (result);
10123 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10125 genSetDPTR(AOP(left)->aopu.dptr);
10126 emitcode ("clr", "a");
10127 emitcode ("movc", "a,@a+dptr");
10128 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10129 emitcode ("inc", "dptr");
10131 aopPut (AOP (result), "a", offset++);
10134 _startLazyDPSEvaluation ();
10137 if (AOP_INDPTRn(left)) {
10138 genSetDPTR(AOP(left)->aopu.dptr);
10144 emitcode ("clr", "a");
10145 emitcode ("movc", "a,@a+dptr");
10146 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10147 emitcode ("inc", "dptr");
10148 aopPut (AOP (result), "a", offset++);
10150 _endLazyDPSEvaluation ();
10153 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10154 if (!AOP_INDPTRn(left)) {
10155 _startLazyDPSEvaluation ();
10157 aopPut ( AOP (left), "dpl", 0);
10158 aopPut ( AOP (left), "dph", 1);
10159 if (options.model == MODEL_FLAT24)
10160 aopPut ( AOP (left), "dpx", 2);
10162 _endLazyDPSEvaluation ();
10165 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
10166 AOP_SIZE(result) > 1 &&
10167 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10169 size = AOP_SIZE (result) - 1;
10170 if (AOP_INDPTRn(left)) {
10171 genSetDPTR(AOP(left)->aopu.dptr);
10173 while (size--) emitcode ("lcall","__decdptr");
10174 if (AOP_INDPTRn(left)) {
10179 freeAsmop (left, NULL, ic, TRUE);
10180 freeAsmop (result, NULL, ic, TRUE);
10183 /*-----------------------------------------------------------------*/
10184 /* genGenPointerGet - gget value from generic pointer space */
10185 /*-----------------------------------------------------------------*/
10187 genGenPointerGet (operand * left,
10188 operand * result, iCode * ic, iCode * pi)
10191 sym_link *retype = getSpec (operandType (result));
10192 sym_link *letype = getSpec (operandType (left));
10194 D (emitcode (";", "genGenPointerGet "); );
10196 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
10198 /* if the operand is already in dptr
10199 then we do nothing else we move the value to dptr */
10200 if (AOP_TYPE (left) != AOP_STR)
10202 /* if this is rematerializable */
10203 if (AOP_TYPE (left) == AOP_IMMD)
10205 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10206 if (AOP(left)->aopu.aop_immd.from_cast_remat)
10208 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
10212 emitcode ("mov", "b,#%d", pointerCode (retype));
10216 { /* we need to get it byte by byte */
10217 _startLazyDPSEvaluation ();
10218 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
10219 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
10220 if (options.model == MODEL_FLAT24) {
10221 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10222 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
10224 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10226 _endLazyDPSEvaluation ();
10230 /* so dptr-b now contains the address */
10232 aopOp (result, ic, FALSE, TRUE);
10235 /* if bit then unpack */
10236 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10238 genUnpackBits (result, "dptr", GPOINTER);
10242 size = AOP_SIZE (result);
10249 // Get two bytes at a time, results in _AP & A.
10250 // dptr will be incremented ONCE by __gptrgetWord.
10252 // Note: any change here must be coordinated
10253 // with the implementation of __gptrgetWord
10254 // in device/lib/_gptrget.c
10255 emitcode ("lcall", "__gptrgetWord");
10256 aopPut (AOP (result), DP2_RESULT_REG, offset++);
10257 aopPut (AOP (result), "a", offset++);
10262 // Only one byte to get.
10263 emitcode ("lcall", "__gptrget");
10264 aopPut (AOP (result), "a", offset++);
10267 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
10269 emitcode ("inc", "dptr");
10274 if (pi && AOP_TYPE (left) != AOP_IMMD) {
10275 _startLazyDPSEvaluation ();
10277 aopPut ( AOP (left), "dpl", 0);
10278 aopPut ( AOP (left), "dph", 1);
10279 if (options.model == MODEL_FLAT24) {
10280 aopPut ( AOP (left), "dpx", 2);
10281 aopPut ( AOP (left), "b", 3);
10282 } else aopPut ( AOP (left), "b", 2);
10284 _endLazyDPSEvaluation ();
10287 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
10288 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10290 size = AOP_SIZE (result) - 1;
10291 while (size--) emitcode ("lcall","__decdptr");
10294 freeAsmop (left, NULL, ic, TRUE);
10295 freeAsmop (result, NULL, ic, TRUE);
10298 /*-----------------------------------------------------------------*/
10299 /* genPointerGet - generate code for pointer get */
10300 /*-----------------------------------------------------------------*/
10302 genPointerGet (iCode * ic, iCode *pi)
10304 operand *left, *result;
10305 sym_link *type, *etype;
10308 D (emitcode (";", "genPointerGet ");
10311 left = IC_LEFT (ic);
10312 result = IC_RESULT (ic);
10314 /* depending on the type of pointer we need to
10315 move it to the correct pointer register */
10316 type = operandType (left);
10317 etype = getSpec (type);
10318 /* if left is of type of pointer then it is simple */
10319 if (IS_PTR (type) && !IS_FUNC (type->next))
10320 p_type = DCL_TYPE (type);
10323 /* we have to go by the storage class */
10324 p_type = PTR_TYPE (SPEC_OCLS (etype));
10326 /* special case when cast remat */
10327 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10328 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10330 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10331 type = operandType (left);
10332 p_type = DCL_TYPE (type);
10334 /* now that we have the pointer type we assign
10335 the pointer values */
10341 genNearPointerGet (left, result, ic, pi);
10345 genPagedPointerGet (left, result, ic, pi);
10349 genFarPointerGet (left, result, ic, pi);
10353 genCodePointerGet (left, result, ic, pi);
10357 genGenPointerGet (left, result, ic, pi);
10363 /*-----------------------------------------------------------------*/
10364 /* genPackBits - generates code for packed bit storage */
10365 /*-----------------------------------------------------------------*/
10367 genPackBits (sym_link * etype,
10369 char *rname, int p_type)
10371 int offset = 0; /* source byte offset */
10372 int rlen = 0; /* remaining bitfield length */
10373 int blen; /* bitfield length */
10374 int bstr; /* bitfield starting bit within byte */
10375 int litval; /* source literal value (if AOP_LIT) */
10376 unsigned char mask; /* bitmask within current byte */
10378 D(emitcode ("; genPackBits",""));
10380 blen = SPEC_BLEN (etype);
10381 bstr = SPEC_BSTR (etype);
10383 /* If the bitfield length is less than a byte */
10386 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10387 (unsigned char) (0xFF >> (8 - bstr)));
10389 if (AOP_TYPE (right) == AOP_LIT)
10391 /* Case with a bitfield length <8 and literal source
10393 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10395 litval &= (~mask) & 0xff;
10396 emitPtrByteGet (rname, p_type, FALSE);
10397 if ((mask|litval)!=0xff)
10398 emitcode ("anl","a,#!constbyte", mask);
10400 emitcode ("orl","a,#!constbyte", litval);
10404 if ((blen==1) && (p_type!=GPOINTER))
10406 /* Case with a bitfield length == 1 and no generic pointer
10408 if (AOP_TYPE (right) == AOP_CRY)
10409 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10412 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10413 emitcode ("rrc","a");
10415 emitPtrByteGet (rname, p_type, FALSE);
10416 emitcode ("mov","acc.%d,c",bstr);
10420 /* Case with a bitfield length < 8 and arbitrary source
10422 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10423 /* shift and mask source value */
10425 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10427 /* transfer A to B and get next byte */
10428 emitPtrByteGet (rname, p_type, TRUE);
10430 emitcode ("anl", "a,#!constbyte", mask);
10431 emitcode ("orl", "a,b");
10432 if (p_type == GPOINTER)
10433 emitcode ("pop", "b");
10437 emitPtrByteSet (rname, p_type, "a");
10441 /* Bit length is greater than 7 bits. In this case, copy */
10442 /* all except the partial byte at the end */
10443 for (rlen=blen;rlen>=8;rlen-=8)
10445 emitPtrByteSet (rname, p_type,
10446 aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
10448 emitcode ("inc", "%s", rname);
10451 /* If there was a partial byte at the end */
10454 mask = (((unsigned char) -1 << rlen) & 0xff);
10456 if (AOP_TYPE (right) == AOP_LIT)
10458 /* Case with partial byte and literal source
10460 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10461 litval >>= (blen-rlen);
10462 litval &= (~mask) & 0xff;
10463 emitPtrByteGet (rname, p_type, FALSE);
10464 if ((mask|litval)!=0xff)
10465 emitcode ("anl","a,#!constbyte", mask);
10467 emitcode ("orl","a,#!constbyte", litval);
10471 /* Case with partial byte and arbitrary source
10473 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10474 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10476 /* transfer A to B and get next byte */
10477 emitPtrByteGet (rname, p_type, TRUE);
10479 emitcode ("anl", "a,#!constbyte", mask);
10480 emitcode ("orl", "a,b");
10481 if (p_type == GPOINTER)
10482 emitcode ("pop", "b");
10484 emitPtrByteSet (rname, p_type, "a");
10490 /*-----------------------------------------------------------------*/
10491 /* genDataPointerSet - remat pointer to data space */
10492 /*-----------------------------------------------------------------*/
10494 genDataPointerSet (operand * right,
10498 int size, offset = 0;
10499 char *l, buff[256];
10501 aopOp (right, ic, FALSE, FALSE);
10503 l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
10504 size = AOP_SIZE (right);
10509 SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
10513 SNPRINTF (buff, sizeof(buff), "%s", l + 1);
10516 emitcode ("mov", "%s,%s", buff,
10517 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10520 freeAsmop (right, NULL, ic, TRUE);
10521 freeAsmop (result, NULL, ic, TRUE);
10524 /*-----------------------------------------------------------------*/
10525 /* genNearPointerSet - emitcode for near pointer put */
10526 /*-----------------------------------------------------------------*/
10528 genNearPointerSet (operand * right,
10535 sym_link *retype, *letype;
10536 sym_link *ptype = operandType (result);
10538 retype = getSpec (operandType (right));
10539 letype = getSpec (ptype);
10541 aopOp (result, ic, FALSE, FALSE);
10543 /* if the result is rematerializable &
10544 in data space & not a bit variable */
10545 if (AOP_TYPE (result) == AOP_IMMD &&
10546 DCL_TYPE (ptype) == POINTER &&
10547 !IS_BITVAR (retype) &&
10548 !IS_BITVAR (letype))
10550 genDataPointerSet (right, result, ic);
10554 /* if the value is already in a pointer register
10555 then don't need anything more */
10556 if (!AOP_INPREG (AOP (result)))
10558 /* otherwise get a free pointer register */
10561 aop = newAsmop (0);
10562 preg = getFreePtr (ic, &aop, FALSE);
10563 emitcode ("mov", "%s,%s",
10565 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10566 rname = preg->name;
10569 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10571 aopOp (right, ic, FALSE, FALSE);
10573 /* if bitfield then unpack the bits */
10574 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10575 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10578 /* we have can just get the values */
10579 int size = AOP_SIZE (right);
10584 l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10588 emitcode ("mov", "@%s,a", rname);
10591 emitcode ("mov", "@%s,%s", rname, l);
10593 emitcode ("inc", "%s", rname);
10598 /* now some housekeeping stuff */
10601 /* we had to allocate for this iCode */
10602 if (pi) aopPut (AOP (result),rname,0);
10603 freeAsmop (NULL, aop, ic, TRUE);
10607 /* we did not allocate which means left
10608 already in a pointer register, then
10609 if size > 0 && this could be used again
10610 we have to point it back to where it
10612 if (AOP_SIZE (right) > 1 &&
10613 !OP_SYMBOL (result)->remat &&
10614 (OP_SYMBOL (result)->liveTo > ic->seq ||
10618 int size = AOP_SIZE (right) - 1;
10620 emitcode ("dec", "%s", rname);
10625 if (pi) pi->generated = 1;
10626 freeAsmop (result, NULL, ic, TRUE);
10627 freeAsmop (right, NULL, ic, TRUE);
10632 /*-----------------------------------------------------------------*/
10633 /* genPagedPointerSet - emitcode for Paged pointer put */
10634 /*-----------------------------------------------------------------*/
10636 genPagedPointerSet (operand * right,
10643 sym_link *retype, *letype;
10645 retype = getSpec (operandType (right));
10646 letype = getSpec (operandType (result));
10648 aopOp (result, ic, FALSE, FALSE);
10650 /* if the value is already in a pointer register
10651 then don't need anything more */
10652 if (!AOP_INPREG (AOP (result)))
10654 /* otherwise get a free pointer register */
10657 aop = newAsmop (0);
10658 preg = getFreePtr (ic, &aop, FALSE);
10659 emitcode ("mov", "%s,%s",
10661 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10662 rname = preg->name;
10665 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10667 aopOp (right, ic, FALSE, FALSE);
10669 /* if bitfield then unpack the bits */
10670 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10671 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10674 /* we have can just get the values */
10675 int size = AOP_SIZE (right);
10680 MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10682 emitcode ("movx", "@%s,a", rname);
10685 emitcode ("inc", "%s", rname);
10691 /* now some housekeeping stuff */
10694 if (pi) aopPut (AOP (result),rname,0);
10695 /* we had to allocate for this iCode */
10696 freeAsmop (NULL, aop, ic, TRUE);
10700 /* we did not allocate which means left
10701 already in a pointer register, then
10702 if size > 0 && this could be used again
10703 we have to point it back to where it
10705 if (AOP_SIZE (right) > 1 &&
10706 !OP_SYMBOL (result)->remat &&
10707 (OP_SYMBOL (result)->liveTo > ic->seq ||
10711 int size = AOP_SIZE (right) - 1;
10713 emitcode ("dec", "%s", rname);
10718 if (pi) pi->generated = 1;
10719 freeAsmop (result, NULL, ic, TRUE);
10720 freeAsmop (right, NULL, ic, TRUE);
10725 /*-----------------------------------------------------------------*/
10726 /* genFarPointerSet - set value from far space */
10727 /*-----------------------------------------------------------------*/
10729 genFarPointerSet (operand * right,
10730 operand * result, iCode * ic, iCode *pi)
10732 int size, offset, dopi=1;
10733 sym_link *retype = getSpec (operandType (right));
10734 sym_link *letype = getSpec (operandType (result));
10736 aopOp (result, ic, FALSE, FALSE);
10738 /* if the operand is already in dptr
10739 then we do nothing else we move the value to dptr */
10740 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10742 /* if this is remateriazable */
10743 if (AOP_TYPE (result) == AOP_IMMD)
10744 emitcode ("mov", "dptr,%s",
10745 aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10748 /* we need to get it byte by byte */
10749 _startLazyDPSEvaluation ();
10750 if (AOP_TYPE (result) != AOP_DPTR)
10752 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10753 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10754 if (options.model == MODEL_FLAT24)
10755 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10759 /* We need to generate a load to DPTR indirect through DPTR. */
10760 D (emitcode (";", "genFarPointerSet -- indirection special case."););
10762 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10763 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10764 if (options.model == MODEL_FLAT24)
10765 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10766 emitcode ("pop", "dph");
10767 emitcode ("pop", "dpl");
10770 _endLazyDPSEvaluation ();
10773 /* so dptr know contains the address */
10774 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10776 /* if bit then unpack */
10777 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10778 if (AOP_INDPTRn(result)) {
10779 genSetDPTR(AOP(result)->aopu.dptr);
10781 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10782 if (AOP_INDPTRn(result)) {
10786 size = AOP_SIZE (right);
10788 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10790 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10792 genSetDPTR(AOP(result)->aopu.dptr);
10793 emitcode ("movx", "@dptr,a");
10794 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10795 emitcode ("inc", "dptr");
10799 _startLazyDPSEvaluation ();
10801 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10803 if (AOP_INDPTRn(result)) {
10804 genSetDPTR(AOP(result)->aopu.dptr);
10810 emitcode ("movx", "@dptr,a");
10811 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10812 emitcode ("inc", "dptr");
10814 _endLazyDPSEvaluation ();
10818 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10819 if (!AOP_INDPTRn(result)) {
10820 _startLazyDPSEvaluation ();
10822 aopPut (AOP(result),"dpl",0);
10823 aopPut (AOP(result),"dph",1);
10824 if (options.model == MODEL_FLAT24)
10825 aopPut (AOP(result),"dpx",2);
10827 _endLazyDPSEvaluation ();
10830 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10831 AOP_SIZE(right) > 1 &&
10832 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10834 size = AOP_SIZE (right) - 1;
10835 if (AOP_INDPTRn(result)) {
10836 genSetDPTR(AOP(result)->aopu.dptr);
10838 while (size--) emitcode ("lcall","__decdptr");
10839 if (AOP_INDPTRn(result)) {
10843 freeAsmop (result, NULL, ic, TRUE);
10844 freeAsmop (right, NULL, ic, TRUE);
10847 /*-----------------------------------------------------------------*/
10848 /* genGenPointerSet - set value from generic pointer space */
10849 /*-----------------------------------------------------------------*/
10851 genGenPointerSet (operand * right,
10852 operand * result, iCode * ic, iCode *pi)
10855 sym_link *retype = getSpec (operandType (right));
10856 sym_link *letype = getSpec (operandType (result));
10858 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10860 /* if the operand is already in dptr
10861 then we do nothing else we move the value to dptr */
10862 if (AOP_TYPE (result) != AOP_STR)
10864 _startLazyDPSEvaluation ();
10865 /* if this is remateriazable */
10866 if (AOP_TYPE (result) == AOP_IMMD)
10868 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10869 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10871 MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10876 "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10880 { /* we need to get it byte by byte */
10881 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10882 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10883 if (options.model == MODEL_FLAT24) {
10884 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10885 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10887 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10890 _endLazyDPSEvaluation ();
10892 /* so dptr + b now contains the address */
10894 aopOp (right, ic, FALSE, TRUE);
10898 /* if bit then unpack */
10899 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10901 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10905 size = AOP_SIZE (right);
10908 _startLazyDPSEvaluation ();
10913 // Set two bytes at a time, passed in _AP & A.
10914 // dptr will be incremented ONCE by __gptrputWord.
10916 // Note: any change here must be coordinated
10917 // with the implementation of __gptrputWord
10918 // in device/lib/_gptrput.c
10919 emitcode("mov", "_ap, %s",
10920 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10921 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10925 emitcode ("lcall", "__gptrputWord");
10930 // Only one byte to put.
10931 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10935 emitcode ("lcall", "__gptrput");
10938 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10940 emitcode ("inc", "dptr");
10943 _endLazyDPSEvaluation ();
10946 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10947 _startLazyDPSEvaluation ();
10949 aopPut (AOP(result),"dpl",0);
10950 aopPut (AOP(result),"dph",1);
10951 if (options.model == MODEL_FLAT24) {
10952 aopPut (AOP(result),"dpx",2);
10953 aopPut (AOP(result),"b",3);
10955 aopPut (AOP(result),"b",2);
10957 _endLazyDPSEvaluation ();
10960 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10961 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10963 size = AOP_SIZE (right) - 1;
10964 while (size--) emitcode ("lcall","__decdptr");
10966 freeAsmop (result, NULL, ic, TRUE);
10967 freeAsmop (right, NULL, ic, TRUE);
10970 /*-----------------------------------------------------------------*/
10971 /* genPointerSet - stores the value into a pointer location */
10972 /*-----------------------------------------------------------------*/
10974 genPointerSet (iCode * ic, iCode *pi)
10976 operand *right, *result;
10977 sym_link *type, *etype;
10980 D (emitcode (";", "genPointerSet "););
10982 right = IC_RIGHT (ic);
10983 result = IC_RESULT (ic);
10985 /* depending on the type of pointer we need to
10986 move it to the correct pointer register */
10987 type = operandType (result);
10988 etype = getSpec (type);
10989 /* if left is of type of pointer then it is simple */
10990 if (IS_PTR (type) && !IS_FUNC (type->next))
10992 p_type = DCL_TYPE (type);
10996 /* we have to go by the storage class */
10997 p_type = PTR_TYPE (SPEC_OCLS (etype));
10999 /* special case when cast remat */
11000 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
11001 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
11002 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
11003 type = operandType (result);
11004 p_type = DCL_TYPE (type);
11007 /* now that we have the pointer type we assign
11008 the pointer values */
11014 genNearPointerSet (right, result, ic, pi);
11018 genPagedPointerSet (right, result, ic, pi);
11022 genFarPointerSet (right, result, ic, pi);
11026 genGenPointerSet (right, result, ic, pi);
11030 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11031 "genPointerSet: illegal pointer type");
11036 /*-----------------------------------------------------------------*/
11037 /* genIfx - generate code for Ifx statement */
11038 /*-----------------------------------------------------------------*/
11040 genIfx (iCode * ic, iCode * popIc)
11042 operand *cond = IC_COND (ic);
11045 D (emitcode (";", "genIfx "););
11047 aopOp (cond, ic, FALSE, FALSE);
11049 /* get the value into acc */
11050 if (AOP_TYPE (cond) != AOP_CRY)
11059 /* the result is now in the accumulator */
11060 freeAsmop (cond, NULL, ic, TRUE);
11062 /* if there was something to be popped then do it */
11066 /* if the condition is a bit variable */
11067 if (isbit && IS_ITEMP (cond) &&
11070 genIfxJump (ic, SPIL_LOC (cond)->rname);
11072 else if (isbit && !IS_ITEMP (cond))
11074 genIfxJump (ic, OP_SYMBOL (cond)->rname);
11078 genIfxJump (ic, "a");
11084 /*-----------------------------------------------------------------*/
11085 /* genAddrOf - generates code for address of */
11086 /*-----------------------------------------------------------------*/
11088 genAddrOf (iCode * ic)
11090 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11093 D (emitcode (";", "genAddrOf ");
11096 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11098 /* if the operand is on the stack then we
11099 need to get the stack offset of this
11101 if (sym->onStack) {
11103 /* if 10 bit stack */
11104 if (options.stack10bit) {
11108 tsprintf(buff, sizeof(buff),
11109 "#!constbyte",(options.stack_loc >> 16) & 0xff);
11110 /* if it has an offset then we need to compute it */
11111 /* emitcode ("subb", "a,#!constbyte", */
11112 /* -((sym->stack < 0) ? */
11113 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11114 /* ((short) sym->stack)) & 0xff); */
11115 /* emitcode ("mov","b,a"); */
11116 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
11117 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11118 /* ((short) sym->stack)) >> 8) & 0xff); */
11120 emitcode ("mov", "a,_bpx");
11121 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
11122 ((char) (sym->stack - _G.nRegsSaved)) :
11123 ((char) sym->stack )) & 0xff);
11124 emitcode ("mov", "b,a");
11125 emitcode ("mov", "a,_bpx+1");
11127 offset = (((sym->stack < 0) ?
11128 ((short) (sym->stack - _G.nRegsSaved)) :
11129 ((short) sym->stack )) >> 8) & 0xff;
11131 emitcode ("addc","a,#!constbyte", offset);
11133 aopPut (AOP (IC_RESULT (ic)), "b", 0);
11134 aopPut (AOP (IC_RESULT (ic)), "a", 1);
11135 aopPut (AOP (IC_RESULT (ic)), buff, 2);
11137 /* we can just move _bp */
11138 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
11139 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
11140 aopPut (AOP (IC_RESULT (ic)), buff, 2);
11143 /* if it has an offset then we need to compute it */
11145 emitcode ("mov", "a,_bp");
11146 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
11147 aopPut (AOP (IC_RESULT (ic)), "a", 0);
11149 /* we can just move _bp */
11150 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
11152 /* fill the result with zero */
11153 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11156 if (options.stack10bit && size < (FPTRSIZE - 1)) {
11158 "*** warning: pointer to stack var truncated.\n");
11163 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
11169 /* object not on stack then we need the name */
11170 size = AOP_SIZE (IC_RESULT (ic));
11175 char s[SDCC_NAME_MAX];
11179 tsprintf(s, sizeof(s), "#!his",sym->rname);
11182 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
11185 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
11187 default: /* should not need this (just in case) */
11188 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
11195 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11198 aopPut (AOP (IC_RESULT (ic)), s, offset++);
11202 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11206 #if 0 // obsolete, and buggy for != xdata
11207 /*-----------------------------------------------------------------*/
11208 /* genArrayInit - generates code for address of */
11209 /*-----------------------------------------------------------------*/
11211 genArrayInit (iCode * ic)
11213 literalList *iLoop;
11215 int elementSize = 0, eIndex;
11216 unsigned val, lastVal;
11218 operand *left=IC_LEFT(ic);
11220 D (emitcode (";", "genArrayInit "););
11222 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
11224 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
11226 // Load immediate value into DPTR.
11227 emitcode("mov", "dptr, %s",
11228 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
11230 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
11233 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11234 "Unexpected operand to genArrayInit.\n");
11237 // a regression because of SDCCcse.c:1.52
11238 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
11239 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
11240 if (options.model == MODEL_FLAT24)
11241 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
11245 type = operandType(IC_LEFT(ic));
11247 if (type && type->next)
11249 elementSize = getSize(type->next);
11253 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11254 "can't determine element size in genArrayInit.\n");
11258 iLoop = IC_ARRAYILIST(ic);
11263 bool firstpass = TRUE;
11265 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
11266 iLoop->count, (int)iLoop->literalValue, elementSize);
11272 symbol *tlbl = NULL;
11274 count = ix > 256 ? 256 : ix;
11278 tlbl = newiTempLabel (NULL);
11279 if (firstpass || (count & 0xff))
11281 emitcode("mov", "b, #!constbyte", count & 0xff);
11284 emitcode ("", "!tlabeldef", tlbl->key + 100);
11289 for (eIndex = 0; eIndex < elementSize; eIndex++)
11291 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
11292 if (val != lastVal)
11294 emitcode("mov", "a, #!constbyte", val);
11298 emitcode("movx", "@dptr, a");
11299 emitcode("inc", "dptr");
11304 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
11310 iLoop = iLoop->next;
11313 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
11317 /*-----------------------------------------------------------------*/
11318 /* genFarFarAssign - assignment when both are in far space */
11319 /*-----------------------------------------------------------------*/
11321 genFarFarAssign (operand * result, operand * right, iCode * ic)
11323 int size = AOP_SIZE (right);
11325 symbol *rSym = NULL;
11329 /* quick & easy case. */
11330 D(emitcode(";","genFarFarAssign (1 byte case)"););
11331 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
11332 freeAsmop (right, NULL, ic, FALSE);
11333 /* now assign DPTR to result */
11335 aopOp(result, ic, FALSE, FALSE);
11337 aopPut(AOP(result), "a", 0);
11338 freeAsmop(result, NULL, ic, FALSE);
11342 /* See if we've got an underlying symbol to abuse. */
11343 if (IS_SYMOP(result) && OP_SYMBOL(result))
11345 if (IS_TRUE_SYMOP(result))
11347 rSym = OP_SYMBOL(result);
11349 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
11351 rSym = OP_SYMBOL(result)->usl.spillLoc;
11355 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
11357 /* We can use the '390 auto-toggle feature to good effect here. */
11359 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
11360 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11361 emitcode ("mov", "dptr,#%s", rSym->rname);
11362 /* DP2 = result, DP1 = right, DP1 is current. */
11365 emitcode("movx", "a,@dptr");
11366 emitcode("movx", "@dptr,a");
11369 emitcode("inc", "dptr");
11370 emitcode("inc", "dptr");
11373 emitcode("mov", "dps,#0");
11374 freeAsmop (right, NULL, ic, FALSE);
11376 some alternative code for processors without auto-toggle
11377 no time to test now, so later well put in...kpb
11378 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
11379 emitcode("mov", "dps,#1"); /* Select DPTR2. */
11380 emitcode ("mov", "dptr,#%s", rSym->rname);
11381 /* DP2 = result, DP1 = right, DP1 is current. */
11385 emitcode("movx", "a,@dptr");
11387 emitcode("inc", "dptr");
11388 emitcode("inc", "dps");
11389 emitcode("movx", "@dptr,a");
11391 emitcode("inc", "dptr");
11392 emitcode("inc", "dps");
11394 emitcode("mov", "dps,#0");
11395 freeAsmop (right, NULL, ic, FALSE);
11400 D (emitcode (";", "genFarFarAssign"););
11401 aopOp (result, ic, TRUE, TRUE);
11403 _startLazyDPSEvaluation ();
11407 aopPut (AOP (result),
11408 aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
11411 _endLazyDPSEvaluation ();
11412 freeAsmop (result, NULL, ic, FALSE);
11413 freeAsmop (right, NULL, ic, FALSE);
11417 /*-----------------------------------------------------------------*/
11418 /* genAssign - generate code for assignment */
11419 /*-----------------------------------------------------------------*/
11421 genAssign (iCode * ic)
11423 operand *result, *right;
11425 unsigned long lit = 0L;
11427 D (emitcode (";", "genAssign ");
11430 result = IC_RESULT (ic);
11431 right = IC_RIGHT (ic);
11433 /* if they are the same */
11434 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11437 aopOp (right, ic, FALSE, FALSE);
11439 emitcode (";", "genAssign: resultIsFar = %s",
11440 isOperandInFarSpace (result) ?
11443 /* special case both in far space */
11444 if ((AOP_TYPE (right) == AOP_DPTR ||
11445 AOP_TYPE (right) == AOP_DPTR2) &&
11446 /* IS_TRUE_SYMOP(result) && */
11447 isOperandInFarSpace (result))
11449 genFarFarAssign (result, right, ic);
11453 aopOp (result, ic, TRUE, FALSE);
11455 /* if they are the same registers */
11456 if (sameRegs (AOP (right), AOP (result)))
11459 /* if the result is a bit */
11460 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
11462 /* if the right size is a literal then
11463 we know what the value is */
11464 if (AOP_TYPE (right) == AOP_LIT)
11466 if (((int) operandLitValue (right)))
11467 aopPut (AOP (result), one, 0);
11469 aopPut (AOP (result), zero, 0);
11473 /* the right is also a bit variable */
11474 if (AOP_TYPE (right) == AOP_CRY)
11476 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11477 aopPut (AOP (result), "c", 0);
11481 /* we need to or */
11483 aopPut (AOP (result), "a", 0);
11487 /* bit variables done */
11489 size = AOP_SIZE (result);
11491 if (AOP_TYPE (right) == AOP_LIT)
11492 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11495 (AOP_TYPE (result) != AOP_REG) &&
11496 (AOP_TYPE (right) == AOP_LIT) &&
11497 !IS_FLOAT (operandType (right)))
11499 _startLazyDPSEvaluation ();
11500 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
11502 aopPut (AOP (result),
11503 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11508 /* And now fill the rest with zeros. */
11511 emitcode ("clr", "a");
11515 aopPut (AOP (result), "a", offset++);
11517 _endLazyDPSEvaluation ();
11521 _startLazyDPSEvaluation ();
11524 aopPut (AOP (result),
11525 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11529 _endLazyDPSEvaluation ();
11533 freeAsmop (right, NULL, ic, FALSE);
11534 freeAsmop (result, NULL, ic, TRUE);
11537 /*-----------------------------------------------------------------*/
11538 /* genJumpTab - generates code for jump table */
11539 /*-----------------------------------------------------------------*/
11541 genJumpTab (iCode * ic)
11546 D (emitcode (";", "genJumpTab ");
11549 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11550 /* get the condition into accumulator */
11551 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11553 /* multiply by four! */
11554 emitcode ("add", "a,acc");
11555 emitcode ("add", "a,acc");
11556 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11558 jtab = newiTempLabel (NULL);
11559 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11560 emitcode ("jmp", "@a+dptr");
11561 emitcode ("", "!tlabeldef", jtab->key + 100);
11562 /* now generate the jump labels */
11563 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11564 jtab = setNextItem (IC_JTLABELS (ic)))
11565 emitcode ("ljmp", "!tlabel", jtab->key + 100);
11569 /*-----------------------------------------------------------------*/
11570 /* genCast - gen code for casting */
11571 /*-----------------------------------------------------------------*/
11573 genCast (iCode * ic)
11575 operand *result = IC_RESULT (ic);
11576 sym_link *ctype = operandType (IC_LEFT (ic));
11577 sym_link *rtype = operandType (IC_RIGHT (ic));
11578 operand *right = IC_RIGHT (ic);
11581 D (emitcode (";", "genCast "););
11583 /* if they are equivalent then do nothing */
11584 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11587 aopOp (right, ic, FALSE, AOP_IS_STR (result));
11588 aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
11590 /* if the result is a bit */
11591 if (IS_BITVAR (OP_SYMBOL (result)->type)
11592 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11594 /* if the right size is a literal then
11595 we know what the value is */
11596 if (AOP_TYPE (right) == AOP_LIT)
11598 if (((int) operandLitValue (right)))
11599 aopPut (AOP (result), one, 0);
11601 aopPut (AOP (result), zero, 0);
11606 /* the right is also a bit variable */
11607 if (AOP_TYPE (right) == AOP_CRY)
11609 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11610 aopPut (AOP (result), "c", 0);
11614 /* we need to or */
11616 aopPut (AOP (result), "a", 0);
11620 /* if they are the same size : or less */
11621 if (AOP_SIZE (result) <= AOP_SIZE (right))
11624 /* if they are in the same place */
11625 if (sameRegs (AOP (right), AOP (result)))
11628 /* if they in different places then copy */
11629 size = AOP_SIZE (result);
11631 _startLazyDPSEvaluation ();
11634 aopPut (AOP (result),
11635 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11639 _endLazyDPSEvaluation ();
11644 /* if the result is of type pointer */
11645 if (IS_PTR (ctype))
11649 sym_link *type = operandType (right);
11651 /* pointer to generic pointer */
11652 if (IS_GENPTR (ctype))
11656 p_type = DCL_TYPE (type);
11660 #if OLD_CAST_BEHAVIOR
11661 /* KV: we are converting a non-pointer type to
11662 * a generic pointer. This (ifdef'd out) code
11663 * says that the resulting generic pointer
11664 * should have the same class as the storage
11665 * location of the non-pointer variable.
11667 * For example, converting an int (which happens
11668 * to be stored in DATA space) to a pointer results
11669 * in a DATA generic pointer; if the original int
11670 * in XDATA space, so will be the resulting pointer.
11672 * I don't like that behavior, and thus this change:
11673 * all such conversions will be forced to XDATA and
11674 * throw a warning. If you want some non-XDATA
11675 * type, or you want to suppress the warning, you
11676 * must go through an intermediate cast, like so:
11678 * char _generic *gp = (char _xdata *)(intVar);
11680 sym_link *etype = getSpec (type);
11682 /* we have to go by the storage class */
11683 if (SPEC_OCLS (etype) != generic)
11685 p_type = PTR_TYPE (SPEC_OCLS (etype));
11690 /* Converting unknown class (i.e. register variable)
11691 * to generic pointer. This is not good, but
11692 * we'll make a guess (and throw a warning).
11695 werror (W_INT_TO_GEN_PTR_CAST);
11699 /* the first two bytes are known */
11700 size = GPTRSIZE - 1;
11702 _startLazyDPSEvaluation ();
11705 aopPut (AOP (result),
11706 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11710 _endLazyDPSEvaluation ();
11712 /* the last byte depending on type */
11714 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11719 // pointerTypeToGPByte will have bitched.
11723 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%x", gpVal);
11724 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11729 /* just copy the pointers */
11730 size = AOP_SIZE (result);
11732 _startLazyDPSEvaluation ();
11735 aopPut (AOP (result),
11736 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11740 _endLazyDPSEvaluation ();
11744 /* so we now know that the size of destination is greater
11745 than the size of the source */
11746 /* we move to result for the size of source */
11747 size = AOP_SIZE (right);
11749 _startLazyDPSEvaluation ();
11752 aopPut (AOP (result),
11753 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11757 _endLazyDPSEvaluation ();
11759 /* now depending on the sign of the source && destination */
11760 size = AOP_SIZE (result) - AOP_SIZE (right);
11761 /* if unsigned or not an integral type */
11762 /* also, if the source is a bit, we don't need to sign extend, because
11763 * it can't possibly have set the sign bit.
11765 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11769 aopPut (AOP (result), zero, offset++);
11774 /* we need to extend the sign :{ */
11775 MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11776 FALSE, FALSE, NULL));
11777 emitcode ("rlc", "a");
11778 emitcode ("subb", "a,acc");
11780 aopPut (AOP (result), "a", offset++);
11783 /* we are done hurray !!!! */
11786 freeAsmop (right, NULL, ic, TRUE);
11787 freeAsmop (result, NULL, ic, TRUE);
11791 /*-----------------------------------------------------------------*/
11792 /* genDjnz - generate decrement & jump if not zero instrucion */
11793 /*-----------------------------------------------------------------*/
11795 genDjnz (iCode * ic, iCode * ifx)
11797 symbol *lbl, *lbl1;
11801 /* if the if condition has a false label
11802 then we cannot save */
11803 if (IC_FALSE (ifx))
11806 /* if the minus is not of the form
11808 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11809 !IS_OP_LITERAL (IC_RIGHT (ic)))
11812 if (operandLitValue (IC_RIGHT (ic)) != 1)
11815 /* if the size of this greater than one then no
11817 if (getSize (operandType (IC_RESULT (ic))) > 1)
11820 /* otherwise we can save BIG */
11821 D(emitcode(";", "genDjnz"););
11823 lbl = newiTempLabel (NULL);
11824 lbl1 = newiTempLabel (NULL);
11826 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11828 if (AOP_NEEDSACC(IC_RESULT(ic)))
11830 /* If the result is accessed indirectly via
11831 * the accumulator, we must explicitly write
11832 * it back after the decrement.
11834 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11836 if (strcmp(rByte, "a"))
11838 /* Something is hopelessly wrong */
11839 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11840 __FILE__, __LINE__);
11841 /* We can just give up; the generated code will be inefficient,
11842 * but what the hey.
11844 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11847 emitcode ("dec", "%s", rByte);
11848 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11849 emitcode ("jnz", "!tlabel", lbl->key + 100);
11851 else if (IS_AOP_PREG (IC_RESULT (ic)))
11853 emitcode ("dec", "%s",
11854 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11855 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11856 emitcode ("jnz", "!tlabel", lbl->key + 100);
11860 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11863 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11864 emitcode ("", "!tlabeldef", lbl->key + 100);
11865 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11866 emitcode ("", "!tlabeldef", lbl1->key + 100);
11868 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11869 ifx->generated = 1;
11873 /*-----------------------------------------------------------------*/
11874 /* genReceive - generate code for a receive iCode */
11875 /*-----------------------------------------------------------------*/
11877 genReceive (iCode * ic)
11879 int size = getSize (operandType (IC_RESULT (ic)));
11883 D (emitcode (";", "genReceive "););
11885 if (ic->argreg == 1)
11887 /* first parameter */
11888 if (AOP_IS_STR(IC_RESULT(ic)))
11890 /* Nothing to do: it's already in the proper place. */
11897 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11898 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11899 IS_TRUE_SYMOP (IC_RESULT (ic)));
11902 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11905 /* Sanity checking... */
11906 if (AOP_USESDPTR(IC_RESULT(ic)))
11908 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11909 "genReceive got unexpected DPTR.");
11911 assignResultValue (IC_RESULT (ic));
11916 /* second receive onwards */
11917 /* this gets a little tricky since unused recevies will be
11918 eliminated, we have saved the reg in the type field . and
11919 we use that to figure out which register to use */
11920 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11921 rb1off = ic->argreg;
11924 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11927 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11930 /*-----------------------------------------------------------------*/
11931 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11932 /*-----------------------------------------------------------------*/
11933 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11935 operand *from , *to , *count;
11940 /* we know it has to be 3 parameters */
11941 assert (nparms == 3);
11943 rsave = newBitVect(16);
11944 /* save DPTR if it needs to be saved */
11945 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11946 if (bitVectBitValue(ic->rMask,i))
11947 rsave = bitVectSetBit(rsave,i);
11949 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11950 ds390_rUmaskForOp (IC_RESULT(ic))));
11957 aopOp (from, ic->next, FALSE, FALSE);
11959 /* get from into DPTR1 */
11960 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11961 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11962 if (options.model == MODEL_FLAT24) {
11963 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11966 freeAsmop (from, NULL, ic, FALSE);
11967 aopOp (to, ic, FALSE, FALSE);
11968 /* get "to" into DPTR */
11969 /* if the operand is already in dptr
11970 then we do nothing else we move the value to dptr */
11971 if (AOP_TYPE (to) != AOP_STR) {
11972 /* if already in DPTR then we need to push */
11973 if (AOP_TYPE(to) == AOP_DPTR) {
11974 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11975 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11976 if (options.model == MODEL_FLAT24)
11977 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11978 emitcode ("pop", "dph");
11979 emitcode ("pop", "dpl");
11981 _startLazyDPSEvaluation ();
11982 /* if this is remateriazable */
11983 if (AOP_TYPE (to) == AOP_IMMD) {
11984 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11985 } else { /* we need to get it byte by byte */
11986 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11987 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11988 if (options.model == MODEL_FLAT24) {
11989 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11992 _endLazyDPSEvaluation ();
11995 freeAsmop (to, NULL, ic, FALSE);
11996 _G.dptrInUse = _G.dptr1InUse = 1;
11997 aopOp (count, ic->next->next, FALSE,FALSE);
11998 lbl =newiTempLabel(NULL);
12000 /* now for the actual copy */
12001 if (AOP_TYPE(count) == AOP_LIT &&
12002 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12003 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12005 emitcode ("lcall","__bi_memcpyc2x_s");
12007 emitcode ("lcall","__bi_memcpyx2x_s");
12009 freeAsmop (count, NULL, ic, FALSE);
12011 symbol *lbl1 = newiTempLabel(NULL);
12013 emitcode (";"," Auto increment but no djnz");
12014 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12015 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12016 freeAsmop (count, NULL, ic, FALSE);
12017 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12018 emitcode ("","!tlabeldef",lbl->key+100);
12020 emitcode ("clr","a");
12021 emitcode ("movc", "a,@a+dptr");
12023 emitcode ("movx", "a,@dptr");
12024 emitcode ("movx", "@dptr,a");
12025 emitcode ("inc", "dptr");
12026 emitcode ("inc", "dptr");
12027 emitcode ("mov","a,b");
12028 emitcode ("orl","a,_ap");
12029 emitcode ("jz","!tlabel",lbl1->key+100);
12030 emitcode ("mov","a,_ap");
12031 emitcode ("add","a,#!constbyte",0xFF);
12032 emitcode ("mov","_ap,a");
12033 emitcode ("mov","a,b");
12034 emitcode ("addc","a,#!constbyte",0xFF);
12035 emitcode ("mov","b,a");
12036 emitcode ("sjmp","!tlabel",lbl->key+100);
12037 emitcode ("","!tlabeldef",lbl1->key+100);
12039 emitcode ("mov", "dps,#0");
12040 _G.dptrInUse = _G.dptr1InUse = 0;
12041 unsavermask(rsave);
12045 /*-----------------------------------------------------------------*/
12046 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
12047 /*-----------------------------------------------------------------*/
12048 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
12050 operand *from , *to , *count;
12055 /* we know it has to be 3 parameters */
12056 assert (nparms == 3);
12058 rsave = newBitVect(16);
12059 /* save DPTR if it needs to be saved */
12060 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12061 if (bitVectBitValue(ic->rMask,i))
12062 rsave = bitVectSetBit(rsave,i);
12064 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12065 ds390_rUmaskForOp (IC_RESULT(ic))));
12072 aopOp (from, ic->next, FALSE, FALSE);
12074 /* get from into DPTR1 */
12075 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12076 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12077 if (options.model == MODEL_FLAT24) {
12078 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12081 freeAsmop (from, NULL, ic, FALSE);
12082 aopOp (to, ic, FALSE, FALSE);
12083 /* get "to" into DPTR */
12084 /* if the operand is already in dptr
12085 then we do nothing else we move the value to dptr */
12086 if (AOP_TYPE (to) != AOP_STR) {
12087 /* if already in DPTR then we need to push */
12088 if (AOP_TYPE(to) == AOP_DPTR) {
12089 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12090 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12091 if (options.model == MODEL_FLAT24)
12092 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12093 emitcode ("pop", "dph");
12094 emitcode ("pop", "dpl");
12096 _startLazyDPSEvaluation ();
12097 /* if this is remateriazable */
12098 if (AOP_TYPE (to) == AOP_IMMD) {
12099 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12100 } else { /* we need to get it byte by byte */
12101 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12102 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12103 if (options.model == MODEL_FLAT24) {
12104 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12107 _endLazyDPSEvaluation ();
12110 freeAsmop (to, NULL, ic, FALSE);
12111 _G.dptrInUse = _G.dptr1InUse = 1;
12112 aopOp (count, ic->next->next, FALSE,FALSE);
12113 lbl =newiTempLabel(NULL);
12114 lbl2 =newiTempLabel(NULL);
12116 /* now for the actual compare */
12117 if (AOP_TYPE(count) == AOP_LIT &&
12118 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12119 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12121 emitcode("lcall","__bi_memcmpc2x_s");
12123 emitcode("lcall","__bi_memcmpx2x_s");
12124 freeAsmop (count, NULL, ic, FALSE);
12125 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12126 aopPut(AOP(IC_RESULT(ic)),"a",0);
12127 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12129 symbol *lbl1 = newiTempLabel(NULL);
12131 emitcode("push","ar0");
12132 emitcode (";"," Auto increment but no djnz");
12133 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12134 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12135 freeAsmop (count, NULL, ic, FALSE);
12136 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12137 emitcode ("","!tlabeldef",lbl->key+100);
12139 emitcode ("clr","a");
12140 emitcode ("movc", "a,@a+dptr");
12142 emitcode ("movx", "a,@dptr");
12143 emitcode ("mov","r0,a");
12144 emitcode ("movx", "a,@dptr");
12145 emitcode ("clr","c");
12146 emitcode ("subb","a,r0");
12147 emitcode ("jnz","!tlabel",lbl2->key+100);
12148 emitcode ("inc", "dptr");
12149 emitcode ("inc", "dptr");
12150 emitcode ("mov","a,b");
12151 emitcode ("orl","a,_ap");
12152 emitcode ("jz","!tlabel",lbl1->key+100);
12153 emitcode ("mov","a,_ap");
12154 emitcode ("add","a,#!constbyte",0xFF);
12155 emitcode ("mov","_ap,a");
12156 emitcode ("mov","a,b");
12157 emitcode ("addc","a,#!constbyte",0xFF);
12158 emitcode ("mov","b,a");
12159 emitcode ("sjmp","!tlabel",lbl->key+100);
12160 emitcode ("","!tlabeldef",lbl1->key+100);
12161 emitcode ("clr","a");
12162 emitcode ("","!tlabeldef",lbl2->key+100);
12163 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12164 aopPut(AOP(IC_RESULT(ic)),"a",0);
12165 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12166 emitcode("pop","ar0");
12167 emitcode ("mov", "dps,#0");
12169 _G.dptrInUse = _G.dptr1InUse = 0;
12170 unsavermask(rsave);
12174 /*-----------------------------------------------------------------*/
12175 /* genInp - gen code for __builtin_inp read data from a mem mapped */
12176 /* port, first parameter output area second parameter pointer to */
12177 /* port third parameter count */
12178 /*-----------------------------------------------------------------*/
12179 static void genInp( iCode *ic, int nparms, operand **parms)
12181 operand *from , *to , *count;
12186 /* we know it has to be 3 parameters */
12187 assert (nparms == 3);
12189 rsave = newBitVect(16);
12190 /* save DPTR if it needs to be saved */
12191 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12192 if (bitVectBitValue(ic->rMask,i))
12193 rsave = bitVectSetBit(rsave,i);
12195 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12196 ds390_rUmaskForOp (IC_RESULT(ic))));
12203 aopOp (from, ic->next, FALSE, FALSE);
12205 /* get from into DPTR1 */
12206 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12207 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12208 if (options.model == MODEL_FLAT24) {
12209 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12212 freeAsmop (from, NULL, ic, FALSE);
12213 aopOp (to, ic, FALSE, FALSE);
12214 /* get "to" into DPTR */
12215 /* if the operand is already in dptr
12216 then we do nothing else we move the value to dptr */
12217 if (AOP_TYPE (to) != AOP_STR) {
12218 /* if already in DPTR then we need to push */
12219 if (AOP_TYPE(to) == AOP_DPTR) {
12220 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12221 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12222 if (options.model == MODEL_FLAT24)
12223 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12224 emitcode ("pop", "dph");
12225 emitcode ("pop", "dpl");
12227 _startLazyDPSEvaluation ();
12228 /* if this is remateriazable */
12229 if (AOP_TYPE (to) == AOP_IMMD) {
12230 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12231 } else { /* we need to get it byte by byte */
12232 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12233 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12234 if (options.model == MODEL_FLAT24) {
12235 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12238 _endLazyDPSEvaluation ();
12241 freeAsmop (to, NULL, ic, FALSE);
12243 _G.dptrInUse = _G.dptr1InUse = 1;
12244 aopOp (count, ic->next->next, FALSE,FALSE);
12245 lbl =newiTempLabel(NULL);
12247 /* now for the actual copy */
12248 if (AOP_TYPE(count) == AOP_LIT &&
12249 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12250 emitcode (";","OH JOY auto increment with djnz (very fast)");
12251 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12252 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12253 freeAsmop (count, NULL, ic, FALSE);
12254 emitcode ("","!tlabeldef",lbl->key+100);
12255 emitcode ("movx", "a,@dptr"); /* read data from port */
12256 emitcode ("dec","dps"); /* switch to DPTR */
12257 emitcode ("movx", "@dptr,a"); /* save into location */
12258 emitcode ("inc", "dptr"); /* point to next area */
12259 emitcode ("inc","dps"); /* switch to DPTR2 */
12260 emitcode ("djnz","b,!tlabel",lbl->key+100);
12262 symbol *lbl1 = newiTempLabel(NULL);
12264 emitcode (";"," Auto increment but no djnz");
12265 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12266 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12267 freeAsmop (count, NULL, ic, FALSE);
12268 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12269 emitcode ("","!tlabeldef",lbl->key+100);
12270 emitcode ("movx", "a,@dptr");
12271 emitcode ("dec","dps"); /* switch to DPTR */
12272 emitcode ("movx", "@dptr,a");
12273 emitcode ("inc", "dptr");
12274 emitcode ("inc","dps"); /* switch to DPTR2 */
12275 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
12276 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
12277 emitcode ("mov","a,b");
12278 emitcode ("orl","a,_ap");
12279 emitcode ("jz","!tlabel",lbl1->key+100);
12280 emitcode ("mov","a,_ap");
12281 emitcode ("add","a,#!constbyte",0xFF);
12282 emitcode ("mov","_ap,a");
12283 emitcode ("mov","a,b");
12284 emitcode ("addc","a,#!constbyte",0xFF);
12285 emitcode ("mov","b,a");
12286 emitcode ("sjmp","!tlabel",lbl->key+100);
12287 emitcode ("","!tlabeldef",lbl1->key+100);
12289 emitcode ("mov", "dps,#0");
12290 _G.dptrInUse = _G.dptr1InUse = 0;
12291 unsavermask(rsave);
12295 /*-----------------------------------------------------------------*/
12296 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
12297 /* port, first parameter output area second parameter pointer to */
12298 /* port third parameter count */
12299 /*-----------------------------------------------------------------*/
12300 static void genOutp( iCode *ic, int nparms, operand **parms)
12302 operand *from , *to , *count;
12307 /* we know it has to be 3 parameters */
12308 assert (nparms == 3);
12310 rsave = newBitVect(16);
12311 /* save DPTR if it needs to be saved */
12312 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12313 if (bitVectBitValue(ic->rMask,i))
12314 rsave = bitVectSetBit(rsave,i);
12316 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12317 ds390_rUmaskForOp (IC_RESULT(ic))));
12324 aopOp (from, ic->next, FALSE, FALSE);
12326 /* get from into DPTR1 */
12327 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12328 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12329 if (options.model == MODEL_FLAT24) {
12330 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12333 freeAsmop (from, NULL, ic, FALSE);
12334 aopOp (to, ic, FALSE, FALSE);
12335 /* get "to" into DPTR */
12336 /* if the operand is already in dptr
12337 then we do nothing else we move the value to dptr */
12338 if (AOP_TYPE (to) != AOP_STR) {
12339 /* if already in DPTR then we need to push */
12340 if (AOP_TYPE(to) == AOP_DPTR) {
12341 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12342 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12343 if (options.model == MODEL_FLAT24)
12344 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12345 emitcode ("pop", "dph");
12346 emitcode ("pop", "dpl");
12348 _startLazyDPSEvaluation ();
12349 /* if this is remateriazable */
12350 if (AOP_TYPE (to) == AOP_IMMD) {
12351 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12352 } else { /* we need to get it byte by byte */
12353 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12354 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12355 if (options.model == MODEL_FLAT24) {
12356 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12359 _endLazyDPSEvaluation ();
12362 freeAsmop (to, NULL, ic, FALSE);
12364 _G.dptrInUse = _G.dptr1InUse = 1;
12365 aopOp (count, ic->next->next, FALSE,FALSE);
12366 lbl =newiTempLabel(NULL);
12368 /* now for the actual copy */
12369 if (AOP_TYPE(count) == AOP_LIT &&
12370 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12371 emitcode (";","OH JOY auto increment with djnz (very fast)");
12372 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12373 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12374 emitcode ("","!tlabeldef",lbl->key+100);
12375 emitcode ("movx", "a,@dptr"); /* read data from port */
12376 emitcode ("inc","dps"); /* switch to DPTR2 */
12377 emitcode ("movx", "@dptr,a"); /* save into location */
12378 emitcode ("inc", "dptr"); /* point to next area */
12379 emitcode ("dec","dps"); /* switch to DPTR */
12380 emitcode ("djnz","b,!tlabel",lbl->key+100);
12381 freeAsmop (count, NULL, ic, FALSE);
12383 symbol *lbl1 = newiTempLabel(NULL);
12385 emitcode (";"," Auto increment but no djnz");
12386 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12387 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12388 freeAsmop (count, NULL, ic, FALSE);
12389 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12390 emitcode ("","!tlabeldef",lbl->key+100);
12391 emitcode ("movx", "a,@dptr");
12392 emitcode ("inc", "dptr");
12393 emitcode ("inc","dps"); /* switch to DPTR2 */
12394 emitcode ("movx", "@dptr,a");
12395 emitcode ("dec","dps"); /* switch to DPTR */
12396 emitcode ("mov","a,b");
12397 emitcode ("orl","a,_ap");
12398 emitcode ("jz","!tlabel",lbl1->key+100);
12399 emitcode ("mov","a,_ap");
12400 emitcode ("add","a,#!constbyte",0xFF);
12401 emitcode ("mov","_ap,a");
12402 emitcode ("mov","a,b");
12403 emitcode ("addc","a,#!constbyte",0xFF);
12404 emitcode ("mov","b,a");
12405 emitcode ("sjmp","!tlabel",lbl->key+100);
12406 emitcode ("","!tlabeldef",lbl1->key+100);
12408 emitcode ("mov", "dps,#0");
12409 _G.dptrInUse = _G.dptr1InUse = 0;
12410 unsavermask(rsave);
12414 /*-----------------------------------------------------------------*/
12415 /* genSwapW - swap lower & high order bytes */
12416 /*-----------------------------------------------------------------*/
12417 static void genSwapW(iCode *ic, int nparms, operand **parms)
12421 assert (nparms==1);
12424 dest=IC_RESULT(ic);
12426 assert(getSize(operandType(src))==2);
12428 aopOp (src, ic, FALSE, FALSE);
12429 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
12431 MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
12433 freeAsmop (src, NULL, ic, FALSE);
12435 aopOp (dest,ic, FALSE, FALSE);
12436 aopPut(AOP(dest),"b",0);
12437 aopPut(AOP(dest),"a",1);
12438 freeAsmop (dest, NULL, ic, FALSE);
12441 /*-----------------------------------------------------------------*/
12442 /* genMemsetX - gencode for memSetX data */
12443 /*-----------------------------------------------------------------*/
12444 static void genMemsetX(iCode *ic, int nparms, operand **parms)
12446 operand *to , *val , *count;
12452 /* we know it has to be 3 parameters */
12453 assert (nparms == 3);
12459 /* save DPTR if it needs to be saved */
12460 rsave = newBitVect(16);
12461 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12462 if (bitVectBitValue(ic->rMask,i))
12463 rsave = bitVectSetBit(rsave,i);
12465 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12466 ds390_rUmaskForOp (IC_RESULT(ic))));
12469 aopOp (to, ic, FALSE, FALSE);
12470 /* get "to" into DPTR */
12471 /* if the operand is already in dptr
12472 then we do nothing else we move the value to dptr */
12473 if (AOP_TYPE (to) != AOP_STR) {
12474 /* if already in DPTR then we need to push */
12475 if (AOP_TYPE(to) == AOP_DPTR) {
12476 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12477 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12478 if (options.model == MODEL_FLAT24)
12479 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12480 emitcode ("pop", "dph");
12481 emitcode ("pop", "dpl");
12483 _startLazyDPSEvaluation ();
12484 /* if this is remateriazable */
12485 if (AOP_TYPE (to) == AOP_IMMD) {
12486 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12487 } else { /* we need to get it byte by byte */
12488 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12489 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12490 if (options.model == MODEL_FLAT24) {
12491 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12494 _endLazyDPSEvaluation ();
12497 freeAsmop (to, NULL, ic, FALSE);
12499 aopOp (val, ic->next->next, FALSE,FALSE);
12500 aopOp (count, ic->next->next, FALSE,FALSE);
12501 lbl =newiTempLabel(NULL);
12502 /* now for the actual copy */
12503 if (AOP_TYPE(count) == AOP_LIT &&
12504 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12505 l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
12506 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12508 emitcode ("","!tlabeldef",lbl->key+100);
12509 emitcode ("movx", "@dptr,a");
12510 emitcode ("inc", "dptr");
12511 emitcode ("djnz","b,!tlabel",lbl->key+100);
12513 symbol *lbl1 = newiTempLabel(NULL);
12515 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12516 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12517 emitcode ("","!tlabeldef",lbl->key+100);
12518 MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
12519 emitcode ("movx", "@dptr,a");
12520 emitcode ("inc", "dptr");
12521 emitcode ("mov","a,b");
12522 emitcode ("orl","a,_ap");
12523 emitcode ("jz","!tlabel",lbl1->key+100);
12524 emitcode ("mov","a,_ap");
12525 emitcode ("add","a,#!constbyte",0xFF);
12526 emitcode ("mov","_ap,a");
12527 emitcode ("mov","a,b");
12528 emitcode ("addc","a,#!constbyte",0xFF);
12529 emitcode ("mov","b,a");
12530 emitcode ("sjmp","!tlabel",lbl->key+100);
12531 emitcode ("","!tlabeldef",lbl1->key+100);
12533 freeAsmop (count, NULL, ic, FALSE);
12534 unsavermask(rsave);
12537 /*-----------------------------------------------------------------*/
12538 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12539 /*-----------------------------------------------------------------*/
12540 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12543 operand *pnum, *result;
12546 assert (nparms==1);
12547 /* save registers that need to be saved */
12548 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12549 ds390_rUmaskForOp (IC_RESULT(ic))));
12552 aopOp (pnum, ic, FALSE, FALSE);
12553 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12554 freeAsmop (pnum, NULL, ic, FALSE);
12555 emitcode ("lcall","NatLib_LoadPrimitive");
12556 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12557 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
12558 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12559 for (i = (size-1) ; i >= 0 ; i-- ) {
12560 emitcode ("push","a%s",javaRet[i]);
12562 for (i=0; i < size ; i++ ) {
12563 emitcode ("pop","a%s",
12564 aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12567 for (i = 0 ; i < size ; i++ ) {
12568 aopPut(AOP(result),javaRet[i],i);
12571 freeAsmop (result, NULL, ic, FALSE);
12572 unsavermask(rsave);
12575 /*-----------------------------------------------------------------*/
12576 /* genNatLibLoadPointer - calls TINI api function to load pointer */
12577 /*-----------------------------------------------------------------*/
12578 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12581 operand *pnum, *result;
12585 assert (nparms==1);
12586 /* save registers that need to be saved */
12587 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12588 ds390_rUmaskForOp (IC_RESULT(ic))));
12591 aopOp (pnum, ic, FALSE, FALSE);
12592 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12593 freeAsmop (pnum, NULL, ic, FALSE);
12594 emitcode ("lcall","NatLib_LoadPointer");
12595 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12596 if (AOP_TYPE(result)!=AOP_STR) {
12597 for (i = 0 ; i < size ; i++ ) {
12598 aopPut(AOP(result),fReturn[i],i);
12601 freeAsmop (result, NULL, ic, FALSE);
12602 unsavermask(rsave);
12605 /*-----------------------------------------------------------------*/
12606 /* genNatLibInstallStateBlock - */
12607 /*-----------------------------------------------------------------*/
12608 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
12609 operand **parms, const char *name)
12612 operand *psb, *handle;
12613 assert (nparms==2);
12615 /* save registers that need to be saved */
12616 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12617 ds390_rUmaskForOp (IC_RESULT(ic))));
12621 /* put pointer to state block into DPTR1 */
12622 aopOp (psb, ic, FALSE, FALSE);
12623 if (AOP_TYPE (psb) == AOP_IMMD) {
12624 emitcode ("mov","dps,#1");
12625 emitcode ("mov", "dptr,%s",
12626 aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12627 emitcode ("mov","dps,#0");
12629 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12630 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12631 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12633 freeAsmop (psb, NULL, ic, FALSE);
12635 /* put libraryID into DPTR */
12636 emitcode ("mov","dptr,#LibraryID");
12638 /* put handle into r3:r2 */
12639 aopOp (handle, ic, FALSE, FALSE);
12640 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12641 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12642 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12643 emitcode ("pop","ar3");
12644 emitcode ("pop","ar2");
12646 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12647 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12649 freeAsmop (psb, NULL, ic, FALSE);
12651 /* make the call */
12652 emitcode ("lcall","NatLib_Install%sStateBlock",name);
12654 /* put return value into place*/
12656 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12658 aopPut(AOP(IC_RESULT(ic)),"a",0);
12659 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12660 unsavermask(rsave);
12663 /*-----------------------------------------------------------------*/
12664 /* genNatLibRemoveStateBlock - */
12665 /*-----------------------------------------------------------------*/
12666 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12672 /* save registers that need to be saved */
12673 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12674 ds390_rUmaskForOp (IC_RESULT(ic))));
12676 /* put libraryID into DPTR */
12677 emitcode ("mov","dptr,#LibraryID");
12678 /* make the call */
12679 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12680 unsavermask(rsave);
12683 /*-----------------------------------------------------------------*/
12684 /* genNatLibGetStateBlock - */
12685 /*-----------------------------------------------------------------*/
12686 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12687 operand **parms,const char *name)
12690 symbol *lbl = newiTempLabel(NULL);
12693 /* save registers that need to be saved */
12694 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12695 ds390_rUmaskForOp (IC_RESULT(ic))));
12697 /* put libraryID into DPTR */
12698 emitcode ("mov","dptr,#LibraryID");
12699 /* make the call */
12700 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12701 emitcode ("jnz","!tlabel",lbl->key+100);
12703 /* put return value into place */
12704 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12705 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12706 emitcode ("push","ar3");
12707 emitcode ("push","ar2");
12708 emitcode ("pop","%s",
12709 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12710 emitcode ("pop","%s",
12711 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12713 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12714 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12716 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12717 emitcode ("","!tlabeldef",lbl->key+100);
12718 unsavermask(rsave);
12721 /*-----------------------------------------------------------------*/
12722 /* genMMMalloc - */
12723 /*-----------------------------------------------------------------*/
12724 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12725 int size, const char *name)
12730 symbol *lbl = newiTempLabel(NULL);
12732 assert (nparms == 1);
12733 /* save registers that need to be saved */
12734 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12735 ds390_rUmaskForOp (IC_RESULT(ic))));
12738 aopOp (bsize,ic,FALSE,FALSE);
12740 /* put the size in R4-R2 */
12741 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12742 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12743 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12745 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12746 emitcode("pop","ar4");
12748 emitcode("pop","ar3");
12749 emitcode("pop","ar2");
12751 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12752 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12754 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12757 freeAsmop (bsize, NULL, ic, FALSE);
12759 /* make the call */
12760 emitcode ("lcall","MM_%s",name);
12761 emitcode ("jz","!tlabel",lbl->key+100);
12762 emitcode ("mov","r2,#!constbyte",0xff);
12763 emitcode ("mov","r3,#!constbyte",0xff);
12764 emitcode ("","!tlabeldef",lbl->key+100);
12765 /* we don't care about the pointer : we just save the handle */
12766 rsym = OP_SYMBOL(IC_RESULT(ic));
12767 if (rsym->liveFrom != rsym->liveTo) {
12768 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12769 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12770 emitcode ("push","ar3");
12771 emitcode ("push","ar2");
12772 emitcode ("pop","%s",
12773 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12774 emitcode ("pop","%s",
12775 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12777 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12778 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12780 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12782 unsavermask(rsave);
12785 /*-----------------------------------------------------------------*/
12787 /*-----------------------------------------------------------------*/
12788 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12793 assert (nparms == 1);
12794 /* save registers that need to be saved */
12795 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12796 ds390_rUmaskForOp (IC_RESULT(ic))));
12799 aopOp (handle,ic,FALSE,FALSE);
12801 /* put the size in R4-R2 */
12802 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12803 emitcode("push","%s",
12804 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12805 emitcode("push","%s",
12806 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12807 emitcode("pop","ar3");
12808 emitcode("pop","ar2");
12810 emitcode ("mov","r2,%s",
12811 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12812 emitcode ("mov","r3,%s",
12813 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12815 freeAsmop (handle, NULL, ic, FALSE);
12817 /* make the call */
12818 emitcode ("lcall","MM_Deref");
12821 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12822 if (rsym->liveFrom != rsym->liveTo) {
12823 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12824 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12825 _startLazyDPSEvaluation ();
12827 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12828 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12829 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12831 _endLazyDPSEvaluation ();
12836 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12837 unsavermask(rsave);
12840 /*-----------------------------------------------------------------*/
12841 /* genMMUnrestrictedPersist - */
12842 /*-----------------------------------------------------------------*/
12843 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12848 assert (nparms == 1);
12849 /* save registers that need to be saved */
12850 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12851 ds390_rUmaskForOp (IC_RESULT(ic))));
12854 aopOp (handle,ic,FALSE,FALSE);
12856 /* put the size in R3-R2 */
12857 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12858 emitcode("push","%s",
12859 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12860 emitcode("push","%s",
12861 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12862 emitcode("pop","ar3");
12863 emitcode("pop","ar2");
12865 emitcode ("mov","r2,%s",
12866 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12867 emitcode ("mov","r3,%s",
12868 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12870 freeAsmop (handle, NULL, ic, FALSE);
12872 /* make the call */
12873 emitcode ("lcall","MM_UnrestrictedPersist");
12876 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12877 if (rsym->liveFrom != rsym->liveTo) {
12878 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12879 aopPut(AOP(IC_RESULT(ic)),"a",0);
12880 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12883 unsavermask(rsave);
12886 /*-----------------------------------------------------------------*/
12887 /* genSystemExecJavaProcess - */
12888 /*-----------------------------------------------------------------*/
12889 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12892 operand *handle, *pp;
12894 assert (nparms==2);
12895 /* save registers that need to be saved */
12896 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12897 ds390_rUmaskForOp (IC_RESULT(ic))));
12902 /* put the handle in R3-R2 */
12903 aopOp (handle,ic,FALSE,FALSE);
12904 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12905 emitcode("push","%s",
12906 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12907 emitcode("push","%s",
12908 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12909 emitcode("pop","ar3");
12910 emitcode("pop","ar2");
12912 emitcode ("mov","r2,%s",
12913 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12914 emitcode ("mov","r3,%s",
12915 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12917 freeAsmop (handle, NULL, ic, FALSE);
12919 /* put pointer in DPTR */
12920 aopOp (pp,ic,FALSE,FALSE);
12921 if (AOP_TYPE(pp) == AOP_IMMD) {
12922 emitcode ("mov", "dptr,%s",
12923 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12924 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12925 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12926 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12927 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12929 freeAsmop (handle, NULL, ic, FALSE);
12931 /* make the call */
12932 emitcode ("lcall","System_ExecJavaProcess");
12934 /* put result in place */
12936 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12937 if (rsym->liveFrom != rsym->liveTo) {
12938 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12939 aopPut(AOP(IC_RESULT(ic)),"a",0);
12940 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12944 unsavermask(rsave);
12947 /*-----------------------------------------------------------------*/
12948 /* genSystemRTCRegisters - */
12949 /*-----------------------------------------------------------------*/
12950 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12956 assert (nparms==1);
12957 /* save registers that need to be saved */
12958 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12959 ds390_rUmaskForOp (IC_RESULT(ic))));
12962 /* put pointer in DPTR */
12963 aopOp (pp,ic,FALSE,FALSE);
12964 if (AOP_TYPE (pp) == AOP_IMMD) {
12965 emitcode ("mov","dps,#1");
12966 emitcode ("mov", "dptr,%s",
12967 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12968 emitcode ("mov","dps,#0");
12970 emitcode ("mov","dpl1,%s",
12971 aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12972 emitcode ("mov","dph1,%s",
12973 aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12974 emitcode ("mov","dpx1,%s",
12975 aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12977 freeAsmop (pp, NULL, ic, FALSE);
12979 /* make the call */
12980 emitcode ("lcall","System_%sRTCRegisters",name);
12982 unsavermask(rsave);
12985 /*-----------------------------------------------------------------*/
12986 /* genSystemThreadSleep - */
12987 /*-----------------------------------------------------------------*/
12988 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12993 assert (nparms==1);
12994 /* save registers that need to be saved */
12995 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12996 ds390_rUmaskForOp (IC_RESULT(ic))));
12999 aopOp(to,ic,FALSE,FALSE);
13000 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
13001 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
13002 emitcode ("push","%s",
13003 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
13004 emitcode ("push","%s",
13005 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
13006 emitcode ("push","%s",
13007 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
13008 emitcode ("push","%s",
13009 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
13010 emitcode ("pop","ar3");
13011 emitcode ("pop","ar2");
13012 emitcode ("pop","ar1");
13013 emitcode ("pop","ar0");
13015 emitcode ("mov","r0,%s",
13016 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
13017 emitcode ("mov","r1,%s",
13018 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
13019 emitcode ("mov","r2,%s",
13020 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
13021 emitcode ("mov","r3,%s",
13022 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
13024 freeAsmop (to, NULL, ic, FALSE);
13026 /* suspend in acc */
13028 aopOp(s,ic,FALSE,FALSE);
13029 emitcode ("mov","a,%s",
13030 aopGet(AOP(s),0,FALSE,TRUE,NULL));
13031 freeAsmop (s, NULL, ic, FALSE);
13033 /* make the call */
13034 emitcode ("lcall","System_%s",name);
13036 unsavermask(rsave);
13039 /*-----------------------------------------------------------------*/
13040 /* genSystemThreadResume - */
13041 /*-----------------------------------------------------------------*/
13042 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
13047 assert (nparms==2);
13048 /* save registers that need to be saved */
13049 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13050 ds390_rUmaskForOp (IC_RESULT(ic))));
13056 aopOp(pid,ic,FALSE,FALSE);
13057 emitcode ("mov","r0,%s",
13058 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13059 freeAsmop (pid, NULL, ic, FALSE);
13062 aopOp(tid,ic,FALSE,FALSE);
13063 emitcode ("mov","a,%s",
13064 aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
13065 freeAsmop (tid, NULL, ic, FALSE);
13067 emitcode ("lcall","System_ThreadResume");
13069 /* put result into place */
13071 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13072 if (rsym->liveFrom != rsym->liveTo) {
13073 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13074 aopPut(AOP(IC_RESULT(ic)),"a",0);
13075 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13078 unsavermask(rsave);
13081 /*-----------------------------------------------------------------*/
13082 /* genSystemProcessResume - */
13083 /*-----------------------------------------------------------------*/
13084 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
13089 assert (nparms==1);
13090 /* save registers that need to be saved */
13091 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13092 ds390_rUmaskForOp (IC_RESULT(ic))));
13097 aopOp(pid,ic,FALSE,FALSE);
13098 emitcode ("mov","a,%s",
13099 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13100 freeAsmop (pid, NULL, ic, FALSE);
13102 emitcode ("lcall","System_ProcessResume");
13104 unsavermask(rsave);
13107 /*-----------------------------------------------------------------*/
13109 /*-----------------------------------------------------------------*/
13110 static void genSystem (iCode *ic,int nparms,char *name)
13112 assert(nparms == 0);
13114 emitcode ("lcall","System_%s",name);
13117 /*-----------------------------------------------------------------*/
13118 /* genSystemPoll - */
13119 /*-----------------------------------------------------------------*/
13120 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
13125 assert (nparms==1);
13126 /* save registers that need to be saved */
13127 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13128 ds390_rUmaskForOp (IC_RESULT(ic))));
13131 aopOp (fp,ic,FALSE,FALSE);
13132 if (AOP_TYPE (fp) == AOP_IMMD) {
13133 emitcode ("mov", "dptr,%s",
13134 aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
13135 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
13136 emitcode ("mov","dpl,%s",
13137 aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
13138 emitcode ("mov","dph,%s",
13139 aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
13140 emitcode ("mov","dpx,%s",
13141 aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
13143 freeAsmop (fp, NULL, ic, FALSE);
13145 emitcode ("lcall","System_%sPoll",name);
13147 /* put result into place */
13149 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13150 if (rsym->liveFrom != rsym->liveTo) {
13151 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13152 aopPut(AOP(IC_RESULT(ic)),"a",0);
13153 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13156 unsavermask(rsave);
13159 /*-----------------------------------------------------------------*/
13160 /* genSystemGetCurrentID - */
13161 /*-----------------------------------------------------------------*/
13162 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
13164 assert (nparms==0);
13166 emitcode ("lcall","System_GetCurrent%sId",name);
13167 /* put result into place */
13169 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13170 if (rsym->liveFrom != rsym->liveTo) {
13171 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13172 aopPut(AOP(IC_RESULT(ic)),"a",0);
13173 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13178 /*-----------------------------------------------------------------*/
13179 /* genDummyRead - generate code for dummy read of volatiles */
13180 /*-----------------------------------------------------------------*/
13182 genDummyRead (iCode * ic)
13187 D(emitcode("; genDummyRead",""));
13189 op = IC_RIGHT (ic);
13190 if (op && IS_SYMOP (op))
13192 aopOp (op, ic, FALSE, FALSE);
13194 /* if the result is a bit */
13195 if (AOP_TYPE (op) == AOP_CRY)
13196 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13199 /* bit variables done */
13201 size = AOP_SIZE (op);
13205 MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13210 freeAsmop (op, NULL, ic, TRUE);
13214 if (op && IS_SYMOP (op))
13216 aopOp (op, ic, FALSE, FALSE);
13218 /* if the result is a bit */
13219 if (AOP_TYPE (op) == AOP_CRY)
13220 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13223 /* bit variables done */
13225 size = AOP_SIZE (op);
13229 MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13234 freeAsmop (op, NULL, ic, TRUE);
13239 /*-----------------------------------------------------------------*/
13240 /* genCritical - generate code for start of a critical sequence */
13241 /*-----------------------------------------------------------------*/
13243 genCritical (iCode *ic)
13245 symbol *tlbl = newiTempLabel (NULL);
13247 D(emitcode("; genCritical",""));
13249 if (IC_RESULT (ic))
13250 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
13252 emitcode ("setb", "c");
13253 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
13254 emitcode ("clr", "c");
13255 emitcode ("", "%05d$:", (tlbl->key + 100));
13257 if (IC_RESULT (ic))
13258 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
13260 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
13262 if (IC_RESULT (ic))
13263 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13266 /*-----------------------------------------------------------------*/
13267 /* genEndCritical - generate code for end of a critical sequence */
13268 /*-----------------------------------------------------------------*/
13270 genEndCritical (iCode *ic)
13272 D(emitcode("; genEndCritical",""));
13276 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
13277 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
13279 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
13280 emitcode ("mov", "ea,c");
13284 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE));
13285 emitcode ("rrc", "a");
13286 emitcode ("mov", "ea,c");
13288 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
13292 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
13293 emitcode ("mov", "ea,c");
13299 /*-----------------------------------------------------------------*/
13300 /* genBuiltIn - calls the appropriate function to generating code */
13301 /* for a built in function */
13302 /*-----------------------------------------------------------------*/
13303 static void genBuiltIn (iCode *ic)
13305 operand *bi_parms[MAX_BUILTIN_ARGS];
13310 /* get all the arguments for a built in function */
13311 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
13313 /* which function is it */
13314 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
13315 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
13316 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
13317 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
13318 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
13319 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
13320 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
13321 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
13322 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
13323 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
13324 genMemsetX(bi_iCode,nbi_parms,bi_parms);
13325 } else if (strcmp(bif->name,"__builtin_inp")==0) {
13326 genInp(bi_iCode,nbi_parms,bi_parms);
13327 } else if (strcmp(bif->name,"__builtin_outp")==0) {
13328 genOutp(bi_iCode,nbi_parms,bi_parms);
13329 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
13330 genSwapW(bi_iCode,nbi_parms,bi_parms);
13331 /* JavaNative builtIns */
13332 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
13333 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
13334 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
13335 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
13336 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
13337 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
13338 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
13339 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
13340 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
13341 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13342 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
13343 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13344 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
13345 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
13346 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
13347 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
13348 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
13349 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13350 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
13351 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13352 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
13353 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
13354 } else if (strcmp(bif->name,"MM_Malloc")==0) {
13355 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
13356 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
13357 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
13358 } else if (strcmp(bif->name,"MM_Free")==0) {
13359 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
13360 } else if (strcmp(bif->name,"MM_Deref")==0) {
13361 genMMDeref(bi_iCode,nbi_parms,bi_parms);
13362 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
13363 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
13364 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
13365 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
13366 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
13367 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
13368 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
13369 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
13370 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
13371 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
13372 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
13373 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
13374 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
13375 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
13376 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
13377 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
13378 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13379 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13380 } else if (strcmp(bif->name,"System_SaveThread")==0) {
13381 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13382 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13383 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13384 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
13385 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
13386 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
13387 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
13388 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
13389 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
13390 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
13391 genSystem(bi_iCode,nbi_parms,"ProcessYield");
13392 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
13393 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
13394 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
13395 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
13396 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
13397 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
13398 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
13399 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
13400 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
13401 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
13403 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
13409 /*-----------------------------------------------------------------*/
13410 /* gen390Code - generate code for Dallas 390 based controllers */
13411 /*-----------------------------------------------------------------*/
13413 gen390Code (iCode * lic)
13418 lineHead = lineCurr = NULL;
13419 dptrn[1][0] = "dpl1";
13420 dptrn[1][1] = "dph1";
13421 dptrn[1][2] = "dpx1";
13423 if (options.model == MODEL_FLAT24) {
13424 fReturnSizeDS390 = 5;
13425 fReturn = fReturn24;
13427 fReturnSizeDS390 = 4;
13428 fReturn = fReturn16;
13429 options.stack10bit=0;
13432 /* print the allocation information */
13433 if (allocInfo && currFunc)
13434 printAllocInfo (currFunc, codeOutFile);
13436 /* if debug information required */
13437 if (options.debug && currFunc)
13439 debugFile->writeFunction (currFunc, lic);
13441 /* stack pointer name */
13442 if (options.useXstack)
13448 for (ic = lic; ic; ic = ic->next)
13450 _G.current_iCode = ic;
13452 if (ic->lineno && cln != ic->lineno)
13456 debugFile->writeCLine (ic);
13458 if (!options.noCcodeInAsm) {
13459 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
13460 printCLine(ic->filename, ic->lineno));
13464 if (options.iCodeInAsm) {
13465 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
13467 /* if the result is marked as
13468 spilt and rematerializable or code for
13469 this has already been generated then
13471 if (resultRemat (ic) || ic->generated)
13474 /* depending on the operation */
13494 /* IPOP happens only when trying to restore a
13495 spilt live range, if there is an ifx statement
13496 following this pop then the if statement might
13497 be using some of the registers being popped which
13498 would destory the contents of the register so
13499 we need to check for this condition and handle it */
13501 ic->next->op == IFX &&
13502 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
13503 genIfx (ic->next, ic);
13521 genEndFunction (ic);
13541 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
13558 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
13562 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
13569 /* note these two are xlated by algebraic equivalence
13570 during parsing SDCC.y */
13571 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13572 "got '>=' or '<=' shouldn't have come here");
13576 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
13588 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
13592 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
13596 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
13620 genRightShift (ic);
13623 case GET_VALUE_AT_ADDRESS:
13624 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13628 if (POINTER_SET (ic))
13629 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13655 if (ic->builtinSEND) genBuiltIn(ic);
13656 else addSet (&_G.sendSet, ic);
13659 case DUMMY_READ_VOLATILE:
13668 genEndCritical (ic);
13675 #if 0 // obsolete, and buggy for != xdata
13687 /* now we are ready to call the
13688 peep hole optimizer */
13689 if (!options.nopeep)
13690 peepHole (&lineHead);
13692 /* now do the actual printing */
13693 printLine (lineHead, codeOutFile);