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 if (!SPEC_USIGN (etype))
9665 /* signed bitfield */
9666 symbol *tlbl = newiTempLabel (NULL);
9668 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9669 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9670 emitcode ("", "%05d$:", tlbl->key + 100);
9672 aopPut (AOP (result), "a", offset++);
9676 /* Bit field did not fit in a byte. Copy all
9677 but the partial byte at the end. */
9678 for (rlen=blen;rlen>=8;rlen-=8)
9680 emitPtrByteGet (rname, ptype, FALSE);
9681 aopPut (AOP (result), "a", offset++);
9683 emitcode ("inc", "%s", rname);
9686 /* Handle the partial byte at the end */
9689 emitPtrByteGet (rname, ptype, FALSE);
9690 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9691 if (!SPEC_USIGN (etype))
9693 /* signed bitfield */
9694 symbol *tlbl = newiTempLabel (NULL);
9696 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9697 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9698 emitcode ("", "%05d$:", tlbl->key + 100);
9700 aopPut (AOP (result), "a", offset++);
9708 if (SPEC_USIGN (etype))
9712 /* signed bitfield: sign extension with 0x00 or 0xff */
9713 emitcode ("rlc", "a");
9714 emitcode ("subb", "a,acc");
9720 aopPut (AOP (result), source, offset++);
9725 /*-----------------------------------------------------------------*/
9726 /* genDataPointerGet - generates code when ptr offset is known */
9727 /*-----------------------------------------------------------------*/
9729 genDataPointerGet (operand * left,
9735 int size, offset = 0;
9736 aopOp (result, ic, TRUE, FALSE);
9738 /* get the string representation of the name */
9739 l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9740 size = AOP_SIZE (result);
9741 _startLazyDPSEvaluation ();
9746 SNPRINTF (buff, sizeof(buff),
9747 "(%s + %d)", l + 1, offset);
9751 SNPRINTF (buff, sizeof(buff),
9754 aopPut (AOP (result), buff, offset++);
9756 _endLazyDPSEvaluation ();
9758 freeAsmop (left, NULL, ic, TRUE);
9759 freeAsmop (result, NULL, ic, TRUE);
9762 /*-----------------------------------------------------------------*/
9763 /* genNearPointerGet - emitcode for near pointer fetch */
9764 /*-----------------------------------------------------------------*/
9766 genNearPointerGet (operand * left,
9774 sym_link *rtype, *retype, *letype;
9775 sym_link *ltype = operandType (left);
9778 rtype = operandType (result);
9779 retype = getSpec (rtype);
9780 letype = getSpec (ltype);
9782 aopOp (left, ic, FALSE, FALSE);
9784 /* if left is rematerialisable and
9785 result is not bitfield variable type and
9786 the left is pointer to data space i.e
9787 lower 128 bytes of space */
9788 if (AOP_TYPE (left) == AOP_IMMD &&
9789 !IS_BITFIELD (retype) &&
9790 !IS_BITFIELD (letype) &&
9791 DCL_TYPE (ltype) == POINTER)
9793 genDataPointerGet (left, result, ic);
9797 /* if the value is already in a pointer register
9798 then don't need anything more */
9799 if (!AOP_INPREG (AOP (left)))
9801 /* otherwise get a free pointer register */
9803 preg = getFreePtr (ic, &aop, FALSE);
9804 emitcode ("mov", "%s,%s",
9806 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9810 rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9812 freeAsmop (left, NULL, ic, TRUE);
9813 aopOp (result, ic, FALSE, FALSE);
9815 /* if bitfield then unpack the bits */
9816 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9817 genUnpackBits (result, rname, POINTER);
9820 /* we have can just get the values */
9821 int size = AOP_SIZE (result);
9826 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9829 emitcode ("mov", "a,@%s", rname);
9830 aopPut (AOP (result), "a", offset);
9834 SNPRINTF (buff, sizeof(buff), "@%s", rname);
9835 aopPut (AOP (result), buff, offset);
9840 emitcode ("inc", "%s", rname);
9845 /* now some housekeeping stuff */
9848 /* we had to allocate for this iCode */
9849 if (pi) { /* post increment present */
9850 aopPut(AOP ( left ),rname,0);
9852 freeAsmop (NULL, aop, ic, TRUE);
9856 /* we did not allocate which means left
9857 already in a pointer register, then
9858 if size > 0 && this could be used again
9859 we have to point it back to where it
9861 if (AOP_SIZE (result) > 1 &&
9862 !OP_SYMBOL (left)->remat &&
9863 (OP_SYMBOL (left)->liveTo > ic->seq ||
9867 int size = AOP_SIZE (result) - 1;
9869 emitcode ("dec", "%s", rname);
9874 freeAsmop (result, NULL, ic, TRUE);
9875 if (pi) pi->generated = 1;
9878 /*-----------------------------------------------------------------*/
9879 /* genPagedPointerGet - emitcode for paged pointer fetch */
9880 /*-----------------------------------------------------------------*/
9882 genPagedPointerGet (operand * left,
9890 sym_link *rtype, *retype, *letype;
9892 rtype = operandType (result);
9893 retype = getSpec (rtype);
9894 letype = getSpec (operandType (left));
9895 aopOp (left, ic, FALSE, FALSE);
9897 /* if the value is already in a pointer register
9898 then don't need anything more */
9899 if (!AOP_INPREG (AOP (left)))
9901 /* otherwise get a free pointer register */
9903 preg = getFreePtr (ic, &aop, FALSE);
9904 emitcode ("mov", "%s,%s",
9906 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9910 rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9912 freeAsmop (left, NULL, ic, TRUE);
9913 aopOp (result, ic, FALSE, FALSE);
9915 /* if bitfield then unpack the bits */
9916 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9917 genUnpackBits (result, rname, PPOINTER);
9920 /* we have can just get the values */
9921 int size = AOP_SIZE (result);
9927 emitcode ("movx", "a,@%s", rname);
9928 aopPut (AOP (result), "a", offset);
9933 emitcode ("inc", "%s", rname);
9937 /* now some housekeeping stuff */
9940 /* we had to allocate for this iCode */
9941 if (pi) aopPut ( AOP (left), rname, 0);
9942 freeAsmop (NULL, aop, ic, TRUE);
9946 /* we did not allocate which means left
9947 already in a pointer register, then
9948 if size > 0 && this could be used again
9949 we have to point it back to where it
9951 if (AOP_SIZE (result) > 1 &&
9952 !OP_SYMBOL (left)->remat &&
9953 (OP_SYMBOL (left)->liveTo > ic->seq ||
9957 int size = AOP_SIZE (result) - 1;
9959 emitcode ("dec", "%s", rname);
9964 freeAsmop (result, NULL, ic, TRUE);
9965 if (pi) pi->generated = 1;
9968 /*-----------------------------------------------------------------*/
9969 /* genFarPointerGet - gget value from far space */
9970 /*-----------------------------------------------------------------*/
9972 genFarPointerGet (operand * left,
9973 operand * result, iCode * ic, iCode *pi)
9975 int size, offset, dopi=1;
9976 sym_link *retype = getSpec (operandType (result));
9977 sym_link *letype = getSpec (operandType (left));
9978 D (emitcode (";", "genFarPointerGet"););
9980 aopOp (left, ic, FALSE, FALSE);
9982 /* if the operand is already in dptr
9983 then we do nothing else we move the value to dptr */
9984 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9986 /* if this is remateriazable */
9987 if (AOP_TYPE (left) == AOP_IMMD)
9989 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9993 /* we need to get it byte by byte */
9994 _startLazyDPSEvaluation ();
9995 if (AOP_TYPE (left) != AOP_DPTR)
9997 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9998 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9999 if (options.model == MODEL_FLAT24)
10000 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10004 /* We need to generate a load to DPTR indirect through DPTR. */
10005 D (emitcode (";", "genFarPointerGet -- indirection special case."););
10006 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
10007 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
10008 if (options.model == MODEL_FLAT24)
10009 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10010 emitcode ("pop", "dph");
10011 emitcode ("pop", "dpl");
10014 _endLazyDPSEvaluation ();
10017 /* so dptr know contains the address */
10018 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10020 /* if bit then unpack */
10021 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10022 if (AOP_INDPTRn(left)) {
10023 genSetDPTR(AOP(left)->aopu.dptr);
10025 genUnpackBits (result, "dptr", FPOINTER);
10026 if (AOP_INDPTRn(left)) {
10031 size = AOP_SIZE (result);
10034 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10036 genSetDPTR(AOP(left)->aopu.dptr);
10037 emitcode ("movx", "a,@dptr");
10038 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10039 emitcode ("inc", "dptr");
10041 aopPut (AOP (result), "a", offset++);
10044 _startLazyDPSEvaluation ();
10046 if (AOP_INDPTRn(left)) {
10047 genSetDPTR(AOP(left)->aopu.dptr);
10053 emitcode ("movx", "a,@dptr");
10054 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10055 emitcode ("inc", "dptr");
10057 aopPut (AOP (result), "a", offset++);
10059 _endLazyDPSEvaluation ();
10062 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10063 if (!AOP_INDPTRn(left)) {
10064 _startLazyDPSEvaluation ();
10065 aopPut ( AOP (left), "dpl", 0);
10066 aopPut ( AOP (left), "dph", 1);
10067 if (options.model == MODEL_FLAT24)
10068 aopPut ( AOP (left), "dpx", 2);
10069 _endLazyDPSEvaluation ();
10072 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
10073 AOP_SIZE(result) > 1 &&
10075 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
10077 size = AOP_SIZE (result) - 1;
10078 if (AOP_INDPTRn(left)) {
10079 genSetDPTR(AOP(left)->aopu.dptr);
10081 while (size--) emitcode ("lcall","__decdptr");
10082 if (AOP_INDPTRn(left)) {
10087 freeAsmop (left, NULL, ic, TRUE);
10088 freeAsmop (result, NULL, ic, TRUE);
10091 /*-----------------------------------------------------------------*/
10092 /* genCodePointerGet - get value from code space */
10093 /*-----------------------------------------------------------------*/
10095 genCodePointerGet (operand * left,
10096 operand * result, iCode * ic, iCode *pi)
10098 int size, offset, dopi=1;
10099 sym_link *retype = getSpec (operandType (result));
10101 aopOp (left, ic, FALSE, FALSE);
10103 /* if the operand is already in dptr
10104 then we do nothing else we move the value to dptr */
10105 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
10107 /* if this is remateriazable */
10108 if (AOP_TYPE (left) == AOP_IMMD)
10110 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10113 { /* we need to get it byte by byte */
10114 _startLazyDPSEvaluation ();
10115 if (AOP_TYPE (left) != AOP_DPTR)
10117 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10118 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10119 if (options.model == MODEL_FLAT24)
10120 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10124 /* We need to generate a load to DPTR indirect through DPTR. */
10125 D (emitcode (";", "gencodePointerGet -- indirection special case."););
10126 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
10127 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
10128 if (options.model == MODEL_FLAT24)
10129 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10130 emitcode ("pop", "dph");
10131 emitcode ("pop", "dpl");
10134 _endLazyDPSEvaluation ();
10137 /* so dptr know contains the address */
10138 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10140 /* if bit then unpack */
10141 if (IS_BITFIELD (retype)) {
10142 if (AOP_INDPTRn(left)) {
10143 genSetDPTR(AOP(left)->aopu.dptr);
10145 genUnpackBits (result, "dptr", CPOINTER);
10146 if (AOP_INDPTRn(left)) {
10151 size = AOP_SIZE (result);
10153 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10155 genSetDPTR(AOP(left)->aopu.dptr);
10156 emitcode ("clr", "a");
10157 emitcode ("movc", "a,@a+dptr");
10158 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10159 emitcode ("inc", "dptr");
10161 aopPut (AOP (result), "a", offset++);
10164 _startLazyDPSEvaluation ();
10167 if (AOP_INDPTRn(left)) {
10168 genSetDPTR(AOP(left)->aopu.dptr);
10174 emitcode ("clr", "a");
10175 emitcode ("movc", "a,@a+dptr");
10176 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10177 emitcode ("inc", "dptr");
10178 aopPut (AOP (result), "a", offset++);
10180 _endLazyDPSEvaluation ();
10183 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10184 if (!AOP_INDPTRn(left)) {
10185 _startLazyDPSEvaluation ();
10187 aopPut ( AOP (left), "dpl", 0);
10188 aopPut ( AOP (left), "dph", 1);
10189 if (options.model == MODEL_FLAT24)
10190 aopPut ( AOP (left), "dpx", 2);
10192 _endLazyDPSEvaluation ();
10195 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
10196 AOP_SIZE(result) > 1 &&
10197 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10199 size = AOP_SIZE (result) - 1;
10200 if (AOP_INDPTRn(left)) {
10201 genSetDPTR(AOP(left)->aopu.dptr);
10203 while (size--) emitcode ("lcall","__decdptr");
10204 if (AOP_INDPTRn(left)) {
10209 freeAsmop (left, NULL, ic, TRUE);
10210 freeAsmop (result, NULL, ic, TRUE);
10213 /*-----------------------------------------------------------------*/
10214 /* genGenPointerGet - gget value from generic pointer space */
10215 /*-----------------------------------------------------------------*/
10217 genGenPointerGet (operand * left,
10218 operand * result, iCode * ic, iCode * pi)
10221 sym_link *retype = getSpec (operandType (result));
10222 sym_link *letype = getSpec (operandType (left));
10224 D (emitcode (";", "genGenPointerGet "); );
10226 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
10228 /* if the operand is already in dptr
10229 then we do nothing else we move the value to dptr */
10230 if (AOP_TYPE (left) != AOP_STR)
10232 /* if this is rematerializable */
10233 if (AOP_TYPE (left) == AOP_IMMD)
10235 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10236 if (AOP(left)->aopu.aop_immd.from_cast_remat)
10238 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
10242 emitcode ("mov", "b,#%d", pointerCode (retype));
10246 { /* we need to get it byte by byte */
10247 _startLazyDPSEvaluation ();
10248 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
10249 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
10250 if (options.model == MODEL_FLAT24) {
10251 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10252 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
10254 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10256 _endLazyDPSEvaluation ();
10260 /* so dptr-b now contains the address */
10262 aopOp (result, ic, FALSE, TRUE);
10265 /* if bit then unpack */
10266 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10268 genUnpackBits (result, "dptr", GPOINTER);
10272 size = AOP_SIZE (result);
10279 // Get two bytes at a time, results in _AP & A.
10280 // dptr will be incremented ONCE by __gptrgetWord.
10282 // Note: any change here must be coordinated
10283 // with the implementation of __gptrgetWord
10284 // in device/lib/_gptrget.c
10285 emitcode ("lcall", "__gptrgetWord");
10286 aopPut (AOP (result), DP2_RESULT_REG, offset++);
10287 aopPut (AOP (result), "a", offset++);
10292 // Only one byte to get.
10293 emitcode ("lcall", "__gptrget");
10294 aopPut (AOP (result), "a", offset++);
10297 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
10299 emitcode ("inc", "dptr");
10304 if (pi && AOP_TYPE (left) != AOP_IMMD) {
10305 _startLazyDPSEvaluation ();
10307 aopPut ( AOP (left), "dpl", 0);
10308 aopPut ( AOP (left), "dph", 1);
10309 if (options.model == MODEL_FLAT24) {
10310 aopPut ( AOP (left), "dpx", 2);
10311 aopPut ( AOP (left), "b", 3);
10312 } else aopPut ( AOP (left), "b", 2);
10314 _endLazyDPSEvaluation ();
10317 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
10318 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10320 size = AOP_SIZE (result) - 1;
10321 while (size--) emitcode ("lcall","__decdptr");
10324 freeAsmop (left, NULL, ic, TRUE);
10325 freeAsmop (result, NULL, ic, TRUE);
10328 /*-----------------------------------------------------------------*/
10329 /* genPointerGet - generate code for pointer get */
10330 /*-----------------------------------------------------------------*/
10332 genPointerGet (iCode * ic, iCode *pi)
10334 operand *left, *result;
10335 sym_link *type, *etype;
10338 D (emitcode (";", "genPointerGet ");
10341 left = IC_LEFT (ic);
10342 result = IC_RESULT (ic);
10344 /* depending on the type of pointer we need to
10345 move it to the correct pointer register */
10346 type = operandType (left);
10347 etype = getSpec (type);
10348 /* if left is of type of pointer then it is simple */
10349 if (IS_PTR (type) && !IS_FUNC (type->next))
10350 p_type = DCL_TYPE (type);
10353 /* we have to go by the storage class */
10354 p_type = PTR_TYPE (SPEC_OCLS (etype));
10356 /* special case when cast remat */
10357 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10358 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10360 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10361 type = operandType (left);
10362 p_type = DCL_TYPE (type);
10364 /* now that we have the pointer type we assign
10365 the pointer values */
10371 genNearPointerGet (left, result, ic, pi);
10375 genPagedPointerGet (left, result, ic, pi);
10379 genFarPointerGet (left, result, ic, pi);
10383 genCodePointerGet (left, result, ic, pi);
10387 genGenPointerGet (left, result, ic, pi);
10393 /*-----------------------------------------------------------------*/
10394 /* genPackBits - generates code for packed bit storage */
10395 /*-----------------------------------------------------------------*/
10397 genPackBits (sym_link * etype,
10399 char *rname, int p_type)
10401 int offset = 0; /* source byte offset */
10402 int rlen = 0; /* remaining bitfield length */
10403 int blen; /* bitfield length */
10404 int bstr; /* bitfield starting bit within byte */
10405 int litval; /* source literal value (if AOP_LIT) */
10406 unsigned char mask; /* bitmask within current byte */
10408 D(emitcode ("; genPackBits",""));
10410 blen = SPEC_BLEN (etype);
10411 bstr = SPEC_BSTR (etype);
10413 /* If the bitfield length is less than a byte */
10416 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10417 (unsigned char) (0xFF >> (8 - bstr)));
10419 if (AOP_TYPE (right) == AOP_LIT)
10421 /* Case with a bitfield length <8 and literal source
10423 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10425 litval &= (~mask) & 0xff;
10426 emitPtrByteGet (rname, p_type, FALSE);
10427 if ((mask|litval)!=0xff)
10428 emitcode ("anl","a,#!constbyte", mask);
10430 emitcode ("orl","a,#!constbyte", litval);
10434 if ((blen==1) && (p_type!=GPOINTER))
10436 /* Case with a bitfield length == 1 and no generic pointer
10438 if (AOP_TYPE (right) == AOP_CRY)
10439 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10442 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10443 emitcode ("rrc","a");
10445 emitPtrByteGet (rname, p_type, FALSE);
10446 emitcode ("mov","acc.%d,c",bstr);
10450 /* Case with a bitfield length < 8 and arbitrary source
10452 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10453 /* shift and mask source value */
10455 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10457 /* transfer A to B and get next byte */
10458 emitPtrByteGet (rname, p_type, TRUE);
10460 emitcode ("anl", "a,#!constbyte", mask);
10461 emitcode ("orl", "a,b");
10462 if (p_type == GPOINTER)
10463 emitcode ("pop", "b");
10467 emitPtrByteSet (rname, p_type, "a");
10471 /* Bit length is greater than 7 bits. In this case, copy */
10472 /* all except the partial byte at the end */
10473 for (rlen=blen;rlen>=8;rlen-=8)
10475 emitPtrByteSet (rname, p_type,
10476 aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
10478 emitcode ("inc", "%s", rname);
10481 /* If there was a partial byte at the end */
10484 mask = (((unsigned char) -1 << rlen) & 0xff);
10486 if (AOP_TYPE (right) == AOP_LIT)
10488 /* Case with partial byte and literal source
10490 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10491 litval >>= (blen-rlen);
10492 litval &= (~mask) & 0xff;
10493 emitPtrByteGet (rname, p_type, FALSE);
10494 if ((mask|litval)!=0xff)
10495 emitcode ("anl","a,#!constbyte", mask);
10497 emitcode ("orl","a,#!constbyte", litval);
10501 /* Case with partial byte and arbitrary source
10503 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10504 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10506 /* transfer A to B and get next byte */
10507 emitPtrByteGet (rname, p_type, TRUE);
10509 emitcode ("anl", "a,#!constbyte", mask);
10510 emitcode ("orl", "a,b");
10511 if (p_type == GPOINTER)
10512 emitcode ("pop", "b");
10514 emitPtrByteSet (rname, p_type, "a");
10520 /*-----------------------------------------------------------------*/
10521 /* genDataPointerSet - remat pointer to data space */
10522 /*-----------------------------------------------------------------*/
10524 genDataPointerSet (operand * right,
10528 int size, offset = 0;
10529 char *l, buff[256];
10531 aopOp (right, ic, FALSE, FALSE);
10533 l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
10534 size = AOP_SIZE (right);
10539 SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
10543 SNPRINTF (buff, sizeof(buff), "%s", l + 1);
10546 emitcode ("mov", "%s,%s", buff,
10547 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10550 freeAsmop (right, NULL, ic, TRUE);
10551 freeAsmop (result, NULL, ic, TRUE);
10554 /*-----------------------------------------------------------------*/
10555 /* genNearPointerSet - emitcode for near pointer put */
10556 /*-----------------------------------------------------------------*/
10558 genNearPointerSet (operand * right,
10565 sym_link *retype, *letype;
10566 sym_link *ptype = operandType (result);
10568 retype = getSpec (operandType (right));
10569 letype = getSpec (ptype);
10571 aopOp (result, ic, FALSE, FALSE);
10573 /* if the result is rematerializable &
10574 in data space & not a bit variable */
10575 if (AOP_TYPE (result) == AOP_IMMD &&
10576 DCL_TYPE (ptype) == POINTER &&
10577 !IS_BITVAR (retype) &&
10578 !IS_BITVAR (letype))
10580 genDataPointerSet (right, result, ic);
10584 /* if the value is already in a pointer register
10585 then don't need anything more */
10586 if (!AOP_INPREG (AOP (result)))
10588 /* otherwise get a free pointer register */
10591 aop = newAsmop (0);
10592 preg = getFreePtr (ic, &aop, FALSE);
10593 emitcode ("mov", "%s,%s",
10595 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10596 rname = preg->name;
10599 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10601 aopOp (right, ic, FALSE, FALSE);
10603 /* if bitfield then unpack the bits */
10604 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10605 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10608 /* we have can just get the values */
10609 int size = AOP_SIZE (right);
10614 l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10618 emitcode ("mov", "@%s,a", rname);
10621 emitcode ("mov", "@%s,%s", rname, l);
10623 emitcode ("inc", "%s", rname);
10628 /* now some housekeeping stuff */
10631 /* we had to allocate for this iCode */
10632 if (pi) aopPut (AOP (result),rname,0);
10633 freeAsmop (NULL, aop, ic, TRUE);
10637 /* we did not allocate which means left
10638 already in a pointer register, then
10639 if size > 0 && this could be used again
10640 we have to point it back to where it
10642 if (AOP_SIZE (right) > 1 &&
10643 !OP_SYMBOL (result)->remat &&
10644 (OP_SYMBOL (result)->liveTo > ic->seq ||
10648 int size = AOP_SIZE (right) - 1;
10650 emitcode ("dec", "%s", rname);
10655 if (pi) pi->generated = 1;
10656 freeAsmop (result, NULL, ic, TRUE);
10657 freeAsmop (right, NULL, ic, TRUE);
10662 /*-----------------------------------------------------------------*/
10663 /* genPagedPointerSet - emitcode for Paged pointer put */
10664 /*-----------------------------------------------------------------*/
10666 genPagedPointerSet (operand * right,
10673 sym_link *retype, *letype;
10675 retype = getSpec (operandType (right));
10676 letype = getSpec (operandType (result));
10678 aopOp (result, ic, FALSE, FALSE);
10680 /* if the value is already in a pointer register
10681 then don't need anything more */
10682 if (!AOP_INPREG (AOP (result)))
10684 /* otherwise get a free pointer register */
10687 aop = newAsmop (0);
10688 preg = getFreePtr (ic, &aop, FALSE);
10689 emitcode ("mov", "%s,%s",
10691 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10692 rname = preg->name;
10695 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10697 aopOp (right, ic, FALSE, FALSE);
10699 /* if bitfield then unpack the bits */
10700 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10701 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10704 /* we have can just get the values */
10705 int size = AOP_SIZE (right);
10710 MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10712 emitcode ("movx", "@%s,a", rname);
10715 emitcode ("inc", "%s", rname);
10721 /* now some housekeeping stuff */
10724 if (pi) aopPut (AOP (result),rname,0);
10725 /* we had to allocate for this iCode */
10726 freeAsmop (NULL, aop, ic, TRUE);
10730 /* we did not allocate which means left
10731 already in a pointer register, then
10732 if size > 0 && this could be used again
10733 we have to point it back to where it
10735 if (AOP_SIZE (right) > 1 &&
10736 !OP_SYMBOL (result)->remat &&
10737 (OP_SYMBOL (result)->liveTo > ic->seq ||
10741 int size = AOP_SIZE (right) - 1;
10743 emitcode ("dec", "%s", rname);
10748 if (pi) pi->generated = 1;
10749 freeAsmop (result, NULL, ic, TRUE);
10750 freeAsmop (right, NULL, ic, TRUE);
10755 /*-----------------------------------------------------------------*/
10756 /* genFarPointerSet - set value from far space */
10757 /*-----------------------------------------------------------------*/
10759 genFarPointerSet (operand * right,
10760 operand * result, iCode * ic, iCode *pi)
10762 int size, offset, dopi=1;
10763 sym_link *retype = getSpec (operandType (right));
10764 sym_link *letype = getSpec (operandType (result));
10766 aopOp (result, ic, FALSE, FALSE);
10768 /* if the operand is already in dptr
10769 then we do nothing else we move the value to dptr */
10770 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10772 /* if this is remateriazable */
10773 if (AOP_TYPE (result) == AOP_IMMD)
10774 emitcode ("mov", "dptr,%s",
10775 aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10778 /* we need to get it byte by byte */
10779 _startLazyDPSEvaluation ();
10780 if (AOP_TYPE (result) != AOP_DPTR)
10782 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10783 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10784 if (options.model == MODEL_FLAT24)
10785 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10789 /* We need to generate a load to DPTR indirect through DPTR. */
10790 D (emitcode (";", "genFarPointerSet -- indirection special case."););
10792 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10793 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10794 if (options.model == MODEL_FLAT24)
10795 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10796 emitcode ("pop", "dph");
10797 emitcode ("pop", "dpl");
10800 _endLazyDPSEvaluation ();
10803 /* so dptr know contains the address */
10804 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10806 /* if bit then unpack */
10807 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10808 if (AOP_INDPTRn(result)) {
10809 genSetDPTR(AOP(result)->aopu.dptr);
10811 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10812 if (AOP_INDPTRn(result)) {
10816 size = AOP_SIZE (right);
10818 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10820 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10822 genSetDPTR(AOP(result)->aopu.dptr);
10823 emitcode ("movx", "@dptr,a");
10824 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10825 emitcode ("inc", "dptr");
10829 _startLazyDPSEvaluation ();
10831 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10833 if (AOP_INDPTRn(result)) {
10834 genSetDPTR(AOP(result)->aopu.dptr);
10840 emitcode ("movx", "@dptr,a");
10841 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10842 emitcode ("inc", "dptr");
10844 _endLazyDPSEvaluation ();
10848 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10849 if (!AOP_INDPTRn(result)) {
10850 _startLazyDPSEvaluation ();
10852 aopPut (AOP(result),"dpl",0);
10853 aopPut (AOP(result),"dph",1);
10854 if (options.model == MODEL_FLAT24)
10855 aopPut (AOP(result),"dpx",2);
10857 _endLazyDPSEvaluation ();
10860 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10861 AOP_SIZE(right) > 1 &&
10862 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10864 size = AOP_SIZE (right) - 1;
10865 if (AOP_INDPTRn(result)) {
10866 genSetDPTR(AOP(result)->aopu.dptr);
10868 while (size--) emitcode ("lcall","__decdptr");
10869 if (AOP_INDPTRn(result)) {
10873 freeAsmop (result, NULL, ic, TRUE);
10874 freeAsmop (right, NULL, ic, TRUE);
10877 /*-----------------------------------------------------------------*/
10878 /* genGenPointerSet - set value from generic pointer space */
10879 /*-----------------------------------------------------------------*/
10881 genGenPointerSet (operand * right,
10882 operand * result, iCode * ic, iCode *pi)
10885 sym_link *retype = getSpec (operandType (right));
10886 sym_link *letype = getSpec (operandType (result));
10888 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10890 /* if the operand is already in dptr
10891 then we do nothing else we move the value to dptr */
10892 if (AOP_TYPE (result) != AOP_STR)
10894 _startLazyDPSEvaluation ();
10895 /* if this is remateriazable */
10896 if (AOP_TYPE (result) == AOP_IMMD)
10898 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10899 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10901 MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10906 "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10910 { /* we need to get it byte by byte */
10911 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10912 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10913 if (options.model == MODEL_FLAT24) {
10914 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10915 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10917 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10920 _endLazyDPSEvaluation ();
10922 /* so dptr + b now contains the address */
10924 aopOp (right, ic, FALSE, TRUE);
10928 /* if bit then unpack */
10929 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10931 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10935 size = AOP_SIZE (right);
10938 _startLazyDPSEvaluation ();
10943 // Set two bytes at a time, passed in _AP & A.
10944 // dptr will be incremented ONCE by __gptrputWord.
10946 // Note: any change here must be coordinated
10947 // with the implementation of __gptrputWord
10948 // in device/lib/_gptrput.c
10949 emitcode("mov", "_ap, %s",
10950 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10951 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10955 emitcode ("lcall", "__gptrputWord");
10960 // Only one byte to put.
10961 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10965 emitcode ("lcall", "__gptrput");
10968 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10970 emitcode ("inc", "dptr");
10973 _endLazyDPSEvaluation ();
10976 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10977 _startLazyDPSEvaluation ();
10979 aopPut (AOP(result),"dpl",0);
10980 aopPut (AOP(result),"dph",1);
10981 if (options.model == MODEL_FLAT24) {
10982 aopPut (AOP(result),"dpx",2);
10983 aopPut (AOP(result),"b",3);
10985 aopPut (AOP(result),"b",2);
10987 _endLazyDPSEvaluation ();
10990 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10991 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10993 size = AOP_SIZE (right) - 1;
10994 while (size--) emitcode ("lcall","__decdptr");
10996 freeAsmop (result, NULL, ic, TRUE);
10997 freeAsmop (right, NULL, ic, TRUE);
11000 /*-----------------------------------------------------------------*/
11001 /* genPointerSet - stores the value into a pointer location */
11002 /*-----------------------------------------------------------------*/
11004 genPointerSet (iCode * ic, iCode *pi)
11006 operand *right, *result;
11007 sym_link *type, *etype;
11010 D (emitcode (";", "genPointerSet "););
11012 right = IC_RIGHT (ic);
11013 result = IC_RESULT (ic);
11015 /* depending on the type of pointer we need to
11016 move it to the correct pointer register */
11017 type = operandType (result);
11018 etype = getSpec (type);
11019 /* if left is of type of pointer then it is simple */
11020 if (IS_PTR (type) && !IS_FUNC (type->next))
11022 p_type = DCL_TYPE (type);
11026 /* we have to go by the storage class */
11027 p_type = PTR_TYPE (SPEC_OCLS (etype));
11029 /* special case when cast remat */
11030 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
11031 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
11032 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
11033 type = operandType (result);
11034 p_type = DCL_TYPE (type);
11037 /* now that we have the pointer type we assign
11038 the pointer values */
11044 genNearPointerSet (right, result, ic, pi);
11048 genPagedPointerSet (right, result, ic, pi);
11052 genFarPointerSet (right, result, ic, pi);
11056 genGenPointerSet (right, result, ic, pi);
11060 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11061 "genPointerSet: illegal pointer type");
11066 /*-----------------------------------------------------------------*/
11067 /* genIfx - generate code for Ifx statement */
11068 /*-----------------------------------------------------------------*/
11070 genIfx (iCode * ic, iCode * popIc)
11072 operand *cond = IC_COND (ic);
11075 D (emitcode (";", "genIfx "););
11077 aopOp (cond, ic, FALSE, FALSE);
11079 /* get the value into acc */
11080 if (AOP_TYPE (cond) != AOP_CRY)
11089 /* the result is now in the accumulator */
11090 freeAsmop (cond, NULL, ic, TRUE);
11092 /* if there was something to be popped then do it */
11096 /* if the condition is a bit variable */
11097 if (isbit && IS_ITEMP (cond) &&
11100 genIfxJump (ic, SPIL_LOC (cond)->rname);
11102 else if (isbit && !IS_ITEMP (cond))
11104 genIfxJump (ic, OP_SYMBOL (cond)->rname);
11108 genIfxJump (ic, "a");
11114 /*-----------------------------------------------------------------*/
11115 /* genAddrOf - generates code for address of */
11116 /*-----------------------------------------------------------------*/
11118 genAddrOf (iCode * ic)
11120 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11123 D (emitcode (";", "genAddrOf ");
11126 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11128 /* if the operand is on the stack then we
11129 need to get the stack offset of this
11131 if (sym->onStack) {
11133 /* if 10 bit stack */
11134 if (options.stack10bit) {
11138 tsprintf(buff, sizeof(buff),
11139 "#!constbyte",(options.stack_loc >> 16) & 0xff);
11140 /* if it has an offset then we need to compute it */
11141 /* emitcode ("subb", "a,#!constbyte", */
11142 /* -((sym->stack < 0) ? */
11143 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11144 /* ((short) sym->stack)) & 0xff); */
11145 /* emitcode ("mov","b,a"); */
11146 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
11147 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11148 /* ((short) sym->stack)) >> 8) & 0xff); */
11150 emitcode ("mov", "a,_bpx");
11151 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
11152 ((char) (sym->stack - _G.nRegsSaved)) :
11153 ((char) sym->stack )) & 0xff);
11154 emitcode ("mov", "b,a");
11155 emitcode ("mov", "a,_bpx+1");
11157 offset = (((sym->stack < 0) ?
11158 ((short) (sym->stack - _G.nRegsSaved)) :
11159 ((short) sym->stack )) >> 8) & 0xff;
11161 emitcode ("addc","a,#!constbyte", offset);
11163 aopPut (AOP (IC_RESULT (ic)), "b", 0);
11164 aopPut (AOP (IC_RESULT (ic)), "a", 1);
11165 aopPut (AOP (IC_RESULT (ic)), buff, 2);
11167 /* we can just move _bp */
11168 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
11169 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
11170 aopPut (AOP (IC_RESULT (ic)), buff, 2);
11173 /* if it has an offset then we need to compute it */
11175 emitcode ("mov", "a,_bp");
11176 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
11177 aopPut (AOP (IC_RESULT (ic)), "a", 0);
11179 /* we can just move _bp */
11180 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
11182 /* fill the result with zero */
11183 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11186 if (options.stack10bit && size < (FPTRSIZE - 1)) {
11188 "*** warning: pointer to stack var truncated.\n");
11193 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
11199 /* object not on stack then we need the name */
11200 size = AOP_SIZE (IC_RESULT (ic));
11205 char s[SDCC_NAME_MAX];
11209 tsprintf(s, sizeof(s), "#!his",sym->rname);
11212 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
11215 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
11217 default: /* should not need this (just in case) */
11218 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
11225 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11228 aopPut (AOP (IC_RESULT (ic)), s, offset++);
11232 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11236 #if 0 // obsolete, and buggy for != xdata
11237 /*-----------------------------------------------------------------*/
11238 /* genArrayInit - generates code for address of */
11239 /*-----------------------------------------------------------------*/
11241 genArrayInit (iCode * ic)
11243 literalList *iLoop;
11245 int elementSize = 0, eIndex;
11246 unsigned val, lastVal;
11248 operand *left=IC_LEFT(ic);
11250 D (emitcode (";", "genArrayInit "););
11252 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
11254 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
11256 // Load immediate value into DPTR.
11257 emitcode("mov", "dptr, %s",
11258 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
11260 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
11263 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11264 "Unexpected operand to genArrayInit.\n");
11267 // a regression because of SDCCcse.c:1.52
11268 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
11269 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
11270 if (options.model == MODEL_FLAT24)
11271 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
11275 type = operandType(IC_LEFT(ic));
11277 if (type && type->next)
11279 elementSize = getSize(type->next);
11283 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11284 "can't determine element size in genArrayInit.\n");
11288 iLoop = IC_ARRAYILIST(ic);
11293 bool firstpass = TRUE;
11295 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
11296 iLoop->count, (int)iLoop->literalValue, elementSize);
11302 symbol *tlbl = NULL;
11304 count = ix > 256 ? 256 : ix;
11308 tlbl = newiTempLabel (NULL);
11309 if (firstpass || (count & 0xff))
11311 emitcode("mov", "b, #!constbyte", count & 0xff);
11314 emitcode ("", "!tlabeldef", tlbl->key + 100);
11319 for (eIndex = 0; eIndex < elementSize; eIndex++)
11321 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
11322 if (val != lastVal)
11324 emitcode("mov", "a, #!constbyte", val);
11328 emitcode("movx", "@dptr, a");
11329 emitcode("inc", "dptr");
11334 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
11340 iLoop = iLoop->next;
11343 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
11347 /*-----------------------------------------------------------------*/
11348 /* genFarFarAssign - assignment when both are in far space */
11349 /*-----------------------------------------------------------------*/
11351 genFarFarAssign (operand * result, operand * right, iCode * ic)
11353 int size = AOP_SIZE (right);
11355 symbol *rSym = NULL;
11359 /* quick & easy case. */
11360 D(emitcode(";","genFarFarAssign (1 byte case)"););
11361 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
11362 freeAsmop (right, NULL, ic, FALSE);
11363 /* now assign DPTR to result */
11365 aopOp(result, ic, FALSE, FALSE);
11367 aopPut(AOP(result), "a", 0);
11368 freeAsmop(result, NULL, ic, FALSE);
11372 /* See if we've got an underlying symbol to abuse. */
11373 if (IS_SYMOP(result) && OP_SYMBOL(result))
11375 if (IS_TRUE_SYMOP(result))
11377 rSym = OP_SYMBOL(result);
11379 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
11381 rSym = OP_SYMBOL(result)->usl.spillLoc;
11385 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
11387 /* We can use the '390 auto-toggle feature to good effect here. */
11389 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
11390 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11391 emitcode ("mov", "dptr,#%s", rSym->rname);
11392 /* DP2 = result, DP1 = right, DP1 is current. */
11395 emitcode("movx", "a,@dptr");
11396 emitcode("movx", "@dptr,a");
11399 emitcode("inc", "dptr");
11400 emitcode("inc", "dptr");
11403 emitcode("mov", "dps,#0");
11404 freeAsmop (right, NULL, ic, FALSE);
11406 some alternative code for processors without auto-toggle
11407 no time to test now, so later well put in...kpb
11408 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
11409 emitcode("mov", "dps,#1"); /* Select DPTR2. */
11410 emitcode ("mov", "dptr,#%s", rSym->rname);
11411 /* DP2 = result, DP1 = right, DP1 is current. */
11415 emitcode("movx", "a,@dptr");
11417 emitcode("inc", "dptr");
11418 emitcode("inc", "dps");
11419 emitcode("movx", "@dptr,a");
11421 emitcode("inc", "dptr");
11422 emitcode("inc", "dps");
11424 emitcode("mov", "dps,#0");
11425 freeAsmop (right, NULL, ic, FALSE);
11430 D (emitcode (";", "genFarFarAssign"););
11431 aopOp (result, ic, TRUE, TRUE);
11433 _startLazyDPSEvaluation ();
11437 aopPut (AOP (result),
11438 aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
11441 _endLazyDPSEvaluation ();
11442 freeAsmop (result, NULL, ic, FALSE);
11443 freeAsmop (right, NULL, ic, FALSE);
11447 /*-----------------------------------------------------------------*/
11448 /* genAssign - generate code for assignment */
11449 /*-----------------------------------------------------------------*/
11451 genAssign (iCode * ic)
11453 operand *result, *right;
11455 unsigned long lit = 0L;
11457 D (emitcode (";", "genAssign ");
11460 result = IC_RESULT (ic);
11461 right = IC_RIGHT (ic);
11463 /* if they are the same */
11464 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11467 aopOp (right, ic, FALSE, FALSE);
11469 emitcode (";", "genAssign: resultIsFar = %s",
11470 isOperandInFarSpace (result) ?
11473 /* special case both in far space */
11474 if ((AOP_TYPE (right) == AOP_DPTR ||
11475 AOP_TYPE (right) == AOP_DPTR2) &&
11476 /* IS_TRUE_SYMOP(result) && */
11477 isOperandInFarSpace (result))
11479 genFarFarAssign (result, right, ic);
11483 aopOp (result, ic, TRUE, FALSE);
11485 /* if they are the same registers */
11486 if (sameRegs (AOP (right), AOP (result)))
11489 /* if the result is a bit */
11490 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
11492 /* if the right size is a literal then
11493 we know what the value is */
11494 if (AOP_TYPE (right) == AOP_LIT)
11496 if (((int) operandLitValue (right)))
11497 aopPut (AOP (result), one, 0);
11499 aopPut (AOP (result), zero, 0);
11503 /* the right is also a bit variable */
11504 if (AOP_TYPE (right) == AOP_CRY)
11506 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11507 aopPut (AOP (result), "c", 0);
11511 /* we need to or */
11513 aopPut (AOP (result), "a", 0);
11517 /* bit variables done */
11519 size = AOP_SIZE (result);
11521 if (AOP_TYPE (right) == AOP_LIT)
11522 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11525 (AOP_TYPE (result) != AOP_REG) &&
11526 (AOP_TYPE (right) == AOP_LIT) &&
11527 !IS_FLOAT (operandType (right)))
11529 _startLazyDPSEvaluation ();
11530 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
11532 aopPut (AOP (result),
11533 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11538 /* And now fill the rest with zeros. */
11541 emitcode ("clr", "a");
11545 aopPut (AOP (result), "a", offset++);
11547 _endLazyDPSEvaluation ();
11551 _startLazyDPSEvaluation ();
11554 aopPut (AOP (result),
11555 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11559 _endLazyDPSEvaluation ();
11563 freeAsmop (right, NULL, ic, FALSE);
11564 freeAsmop (result, NULL, ic, TRUE);
11567 /*-----------------------------------------------------------------*/
11568 /* genJumpTab - generates code for jump table */
11569 /*-----------------------------------------------------------------*/
11571 genJumpTab (iCode * ic)
11576 D (emitcode (";", "genJumpTab ");
11579 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11580 /* get the condition into accumulator */
11581 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11583 /* multiply by four! */
11584 emitcode ("add", "a,acc");
11585 emitcode ("add", "a,acc");
11586 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11588 jtab = newiTempLabel (NULL);
11589 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11590 emitcode ("jmp", "@a+dptr");
11591 emitcode ("", "!tlabeldef", jtab->key + 100);
11592 /* now generate the jump labels */
11593 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11594 jtab = setNextItem (IC_JTLABELS (ic)))
11595 emitcode ("ljmp", "!tlabel", jtab->key + 100);
11599 /*-----------------------------------------------------------------*/
11600 /* genCast - gen code for casting */
11601 /*-----------------------------------------------------------------*/
11603 genCast (iCode * ic)
11605 operand *result = IC_RESULT (ic);
11606 sym_link *ctype = operandType (IC_LEFT (ic));
11607 sym_link *rtype = operandType (IC_RIGHT (ic));
11608 operand *right = IC_RIGHT (ic);
11611 D (emitcode (";", "genCast "););
11613 /* if they are equivalent then do nothing */
11614 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11617 aopOp (right, ic, FALSE, AOP_IS_STR (result));
11618 aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
11620 /* if the result is a bit */
11621 if (IS_BITVAR (OP_SYMBOL (result)->type)
11622 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11624 /* if the right size is a literal then
11625 we know what the value is */
11626 if (AOP_TYPE (right) == AOP_LIT)
11628 if (((int) operandLitValue (right)))
11629 aopPut (AOP (result), one, 0);
11631 aopPut (AOP (result), zero, 0);
11636 /* the right is also a bit variable */
11637 if (AOP_TYPE (right) == AOP_CRY)
11639 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11640 aopPut (AOP (result), "c", 0);
11644 /* we need to or */
11646 aopPut (AOP (result), "a", 0);
11650 /* if they are the same size : or less */
11651 if (AOP_SIZE (result) <= AOP_SIZE (right))
11654 /* if they are in the same place */
11655 if (sameRegs (AOP (right), AOP (result)))
11658 /* if they in different places then copy */
11659 size = AOP_SIZE (result);
11661 _startLazyDPSEvaluation ();
11664 aopPut (AOP (result),
11665 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11669 _endLazyDPSEvaluation ();
11674 /* if the result is of type pointer */
11675 if (IS_PTR (ctype))
11679 sym_link *type = operandType (right);
11681 /* pointer to generic pointer */
11682 if (IS_GENPTR (ctype))
11686 p_type = DCL_TYPE (type);
11690 #if OLD_CAST_BEHAVIOR
11691 /* KV: we are converting a non-pointer type to
11692 * a generic pointer. This (ifdef'd out) code
11693 * says that the resulting generic pointer
11694 * should have the same class as the storage
11695 * location of the non-pointer variable.
11697 * For example, converting an int (which happens
11698 * to be stored in DATA space) to a pointer results
11699 * in a DATA generic pointer; if the original int
11700 * in XDATA space, so will be the resulting pointer.
11702 * I don't like that behavior, and thus this change:
11703 * all such conversions will be forced to XDATA and
11704 * throw a warning. If you want some non-XDATA
11705 * type, or you want to suppress the warning, you
11706 * must go through an intermediate cast, like so:
11708 * char _generic *gp = (char _xdata *)(intVar);
11710 sym_link *etype = getSpec (type);
11712 /* we have to go by the storage class */
11713 if (SPEC_OCLS (etype) != generic)
11715 p_type = PTR_TYPE (SPEC_OCLS (etype));
11720 /* Converting unknown class (i.e. register variable)
11721 * to generic pointer. This is not good, but
11722 * we'll make a guess (and throw a warning).
11725 werror (W_INT_TO_GEN_PTR_CAST);
11729 /* the first two bytes are known */
11730 size = GPTRSIZE - 1;
11732 _startLazyDPSEvaluation ();
11735 aopPut (AOP (result),
11736 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11740 _endLazyDPSEvaluation ();
11742 /* the last byte depending on type */
11744 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11749 // pointerTypeToGPByte will have bitched.
11753 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%x", gpVal);
11754 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11759 /* just copy the pointers */
11760 size = AOP_SIZE (result);
11762 _startLazyDPSEvaluation ();
11765 aopPut (AOP (result),
11766 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11770 _endLazyDPSEvaluation ();
11774 /* so we now know that the size of destination is greater
11775 than the size of the source */
11776 /* we move to result for the size of source */
11777 size = AOP_SIZE (right);
11779 _startLazyDPSEvaluation ();
11782 aopPut (AOP (result),
11783 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11787 _endLazyDPSEvaluation ();
11789 /* now depending on the sign of the source && destination */
11790 size = AOP_SIZE (result) - AOP_SIZE (right);
11791 /* if unsigned or not an integral type */
11792 /* also, if the source is a bit, we don't need to sign extend, because
11793 * it can't possibly have set the sign bit.
11795 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11799 aopPut (AOP (result), zero, offset++);
11804 /* we need to extend the sign :{ */
11805 MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11806 FALSE, FALSE, NULL));
11807 emitcode ("rlc", "a");
11808 emitcode ("subb", "a,acc");
11810 aopPut (AOP (result), "a", offset++);
11813 /* we are done hurray !!!! */
11816 freeAsmop (right, NULL, ic, TRUE);
11817 freeAsmop (result, NULL, ic, TRUE);
11821 /*-----------------------------------------------------------------*/
11822 /* genDjnz - generate decrement & jump if not zero instrucion */
11823 /*-----------------------------------------------------------------*/
11825 genDjnz (iCode * ic, iCode * ifx)
11827 symbol *lbl, *lbl1;
11831 /* if the if condition has a false label
11832 then we cannot save */
11833 if (IC_FALSE (ifx))
11836 /* if the minus is not of the form
11838 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11839 !IS_OP_LITERAL (IC_RIGHT (ic)))
11842 if (operandLitValue (IC_RIGHT (ic)) != 1)
11845 /* if the size of this greater than one then no
11847 if (getSize (operandType (IC_RESULT (ic))) > 1)
11850 /* otherwise we can save BIG */
11851 D(emitcode(";", "genDjnz"););
11853 lbl = newiTempLabel (NULL);
11854 lbl1 = newiTempLabel (NULL);
11856 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11858 if (AOP_NEEDSACC(IC_RESULT(ic)))
11860 /* If the result is accessed indirectly via
11861 * the accumulator, we must explicitly write
11862 * it back after the decrement.
11864 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11866 if (strcmp(rByte, "a"))
11868 /* Something is hopelessly wrong */
11869 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11870 __FILE__, __LINE__);
11871 /* We can just give up; the generated code will be inefficient,
11872 * but what the hey.
11874 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11877 emitcode ("dec", "%s", rByte);
11878 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11879 emitcode ("jnz", "!tlabel", lbl->key + 100);
11881 else if (IS_AOP_PREG (IC_RESULT (ic)))
11883 emitcode ("dec", "%s",
11884 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11885 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11886 emitcode ("jnz", "!tlabel", lbl->key + 100);
11890 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11893 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11894 emitcode ("", "!tlabeldef", lbl->key + 100);
11895 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11896 emitcode ("", "!tlabeldef", lbl1->key + 100);
11898 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11899 ifx->generated = 1;
11903 /*-----------------------------------------------------------------*/
11904 /* genReceive - generate code for a receive iCode */
11905 /*-----------------------------------------------------------------*/
11907 genReceive (iCode * ic)
11909 int size = getSize (operandType (IC_RESULT (ic)));
11913 D (emitcode (";", "genReceive "););
11915 if (ic->argreg == 1)
11917 /* first parameter */
11918 if (AOP_IS_STR(IC_RESULT(ic)))
11920 /* Nothing to do: it's already in the proper place. */
11927 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11928 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11929 IS_TRUE_SYMOP (IC_RESULT (ic)));
11932 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11935 /* Sanity checking... */
11936 if (AOP_USESDPTR(IC_RESULT(ic)))
11938 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11939 "genReceive got unexpected DPTR.");
11941 assignResultValue (IC_RESULT (ic));
11946 /* second receive onwards */
11947 /* this gets a little tricky since unused recevies will be
11948 eliminated, we have saved the reg in the type field . and
11949 we use that to figure out which register to use */
11950 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11951 rb1off = ic->argreg;
11954 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11957 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11960 /*-----------------------------------------------------------------*/
11961 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11962 /*-----------------------------------------------------------------*/
11963 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11965 operand *from , *to , *count;
11970 /* we know it has to be 3 parameters */
11971 assert (nparms == 3);
11973 rsave = newBitVect(16);
11974 /* save DPTR if it needs to be saved */
11975 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11976 if (bitVectBitValue(ic->rMask,i))
11977 rsave = bitVectSetBit(rsave,i);
11979 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11980 ds390_rUmaskForOp (IC_RESULT(ic))));
11987 aopOp (from, ic->next, FALSE, FALSE);
11989 /* get from into DPTR1 */
11990 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11991 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11992 if (options.model == MODEL_FLAT24) {
11993 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11996 freeAsmop (from, NULL, ic, FALSE);
11997 aopOp (to, ic, FALSE, FALSE);
11998 /* get "to" into DPTR */
11999 /* if the operand is already in dptr
12000 then we do nothing else we move the value to dptr */
12001 if (AOP_TYPE (to) != AOP_STR) {
12002 /* if already in DPTR then we need to push */
12003 if (AOP_TYPE(to) == AOP_DPTR) {
12004 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12005 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12006 if (options.model == MODEL_FLAT24)
12007 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12008 emitcode ("pop", "dph");
12009 emitcode ("pop", "dpl");
12011 _startLazyDPSEvaluation ();
12012 /* if this is remateriazable */
12013 if (AOP_TYPE (to) == AOP_IMMD) {
12014 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12015 } else { /* we need to get it byte by byte */
12016 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12017 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12018 if (options.model == MODEL_FLAT24) {
12019 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12022 _endLazyDPSEvaluation ();
12025 freeAsmop (to, NULL, ic, FALSE);
12026 _G.dptrInUse = _G.dptr1InUse = 1;
12027 aopOp (count, ic->next->next, FALSE,FALSE);
12028 lbl =newiTempLabel(NULL);
12030 /* now for the actual copy */
12031 if (AOP_TYPE(count) == AOP_LIT &&
12032 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12033 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12035 emitcode ("lcall","__bi_memcpyc2x_s");
12037 emitcode ("lcall","__bi_memcpyx2x_s");
12039 freeAsmop (count, NULL, ic, FALSE);
12041 symbol *lbl1 = newiTempLabel(NULL);
12043 emitcode (";"," Auto increment but no djnz");
12044 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12045 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12046 freeAsmop (count, NULL, ic, FALSE);
12047 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12048 emitcode ("","!tlabeldef",lbl->key+100);
12050 emitcode ("clr","a");
12051 emitcode ("movc", "a,@a+dptr");
12053 emitcode ("movx", "a,@dptr");
12054 emitcode ("movx", "@dptr,a");
12055 emitcode ("inc", "dptr");
12056 emitcode ("inc", "dptr");
12057 emitcode ("mov","a,b");
12058 emitcode ("orl","a,_ap");
12059 emitcode ("jz","!tlabel",lbl1->key+100);
12060 emitcode ("mov","a,_ap");
12061 emitcode ("add","a,#!constbyte",0xFF);
12062 emitcode ("mov","_ap,a");
12063 emitcode ("mov","a,b");
12064 emitcode ("addc","a,#!constbyte",0xFF);
12065 emitcode ("mov","b,a");
12066 emitcode ("sjmp","!tlabel",lbl->key+100);
12067 emitcode ("","!tlabeldef",lbl1->key+100);
12069 emitcode ("mov", "dps,#0");
12070 _G.dptrInUse = _G.dptr1InUse = 0;
12071 unsavermask(rsave);
12075 /*-----------------------------------------------------------------*/
12076 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
12077 /*-----------------------------------------------------------------*/
12078 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
12080 operand *from , *to , *count;
12085 /* we know it has to be 3 parameters */
12086 assert (nparms == 3);
12088 rsave = newBitVect(16);
12089 /* save DPTR if it needs to be saved */
12090 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12091 if (bitVectBitValue(ic->rMask,i))
12092 rsave = bitVectSetBit(rsave,i);
12094 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12095 ds390_rUmaskForOp (IC_RESULT(ic))));
12102 aopOp (from, ic->next, FALSE, FALSE);
12104 /* get from into DPTR1 */
12105 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12106 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12107 if (options.model == MODEL_FLAT24) {
12108 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12111 freeAsmop (from, NULL, ic, FALSE);
12112 aopOp (to, ic, FALSE, FALSE);
12113 /* get "to" into DPTR */
12114 /* if the operand is already in dptr
12115 then we do nothing else we move the value to dptr */
12116 if (AOP_TYPE (to) != AOP_STR) {
12117 /* if already in DPTR then we need to push */
12118 if (AOP_TYPE(to) == AOP_DPTR) {
12119 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12120 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12121 if (options.model == MODEL_FLAT24)
12122 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12123 emitcode ("pop", "dph");
12124 emitcode ("pop", "dpl");
12126 _startLazyDPSEvaluation ();
12127 /* if this is remateriazable */
12128 if (AOP_TYPE (to) == AOP_IMMD) {
12129 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12130 } else { /* we need to get it byte by byte */
12131 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12132 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12133 if (options.model == MODEL_FLAT24) {
12134 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12137 _endLazyDPSEvaluation ();
12140 freeAsmop (to, NULL, ic, FALSE);
12141 _G.dptrInUse = _G.dptr1InUse = 1;
12142 aopOp (count, ic->next->next, FALSE,FALSE);
12143 lbl =newiTempLabel(NULL);
12144 lbl2 =newiTempLabel(NULL);
12146 /* now for the actual compare */
12147 if (AOP_TYPE(count) == AOP_LIT &&
12148 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12149 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12151 emitcode("lcall","__bi_memcmpc2x_s");
12153 emitcode("lcall","__bi_memcmpx2x_s");
12154 freeAsmop (count, NULL, ic, FALSE);
12155 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12156 aopPut(AOP(IC_RESULT(ic)),"a",0);
12157 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12159 symbol *lbl1 = newiTempLabel(NULL);
12161 emitcode("push","ar0");
12162 emitcode (";"," Auto increment but no djnz");
12163 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12164 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12165 freeAsmop (count, NULL, ic, FALSE);
12166 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12167 emitcode ("","!tlabeldef",lbl->key+100);
12169 emitcode ("clr","a");
12170 emitcode ("movc", "a,@a+dptr");
12172 emitcode ("movx", "a,@dptr");
12173 emitcode ("mov","r0,a");
12174 emitcode ("movx", "a,@dptr");
12175 emitcode ("clr","c");
12176 emitcode ("subb","a,r0");
12177 emitcode ("jnz","!tlabel",lbl2->key+100);
12178 emitcode ("inc", "dptr");
12179 emitcode ("inc", "dptr");
12180 emitcode ("mov","a,b");
12181 emitcode ("orl","a,_ap");
12182 emitcode ("jz","!tlabel",lbl1->key+100);
12183 emitcode ("mov","a,_ap");
12184 emitcode ("add","a,#!constbyte",0xFF);
12185 emitcode ("mov","_ap,a");
12186 emitcode ("mov","a,b");
12187 emitcode ("addc","a,#!constbyte",0xFF);
12188 emitcode ("mov","b,a");
12189 emitcode ("sjmp","!tlabel",lbl->key+100);
12190 emitcode ("","!tlabeldef",lbl1->key+100);
12191 emitcode ("clr","a");
12192 emitcode ("","!tlabeldef",lbl2->key+100);
12193 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12194 aopPut(AOP(IC_RESULT(ic)),"a",0);
12195 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12196 emitcode("pop","ar0");
12197 emitcode ("mov", "dps,#0");
12199 _G.dptrInUse = _G.dptr1InUse = 0;
12200 unsavermask(rsave);
12204 /*-----------------------------------------------------------------*/
12205 /* genInp - gen code for __builtin_inp read data from a mem mapped */
12206 /* port, first parameter output area second parameter pointer to */
12207 /* port third parameter count */
12208 /*-----------------------------------------------------------------*/
12209 static void genInp( iCode *ic, int nparms, operand **parms)
12211 operand *from , *to , *count;
12216 /* we know it has to be 3 parameters */
12217 assert (nparms == 3);
12219 rsave = newBitVect(16);
12220 /* save DPTR if it needs to be saved */
12221 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12222 if (bitVectBitValue(ic->rMask,i))
12223 rsave = bitVectSetBit(rsave,i);
12225 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12226 ds390_rUmaskForOp (IC_RESULT(ic))));
12233 aopOp (from, ic->next, FALSE, FALSE);
12235 /* get from into DPTR1 */
12236 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12237 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12238 if (options.model == MODEL_FLAT24) {
12239 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12242 freeAsmop (from, NULL, ic, FALSE);
12243 aopOp (to, ic, FALSE, FALSE);
12244 /* get "to" into DPTR */
12245 /* if the operand is already in dptr
12246 then we do nothing else we move the value to dptr */
12247 if (AOP_TYPE (to) != AOP_STR) {
12248 /* if already in DPTR then we need to push */
12249 if (AOP_TYPE(to) == AOP_DPTR) {
12250 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12251 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12252 if (options.model == MODEL_FLAT24)
12253 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12254 emitcode ("pop", "dph");
12255 emitcode ("pop", "dpl");
12257 _startLazyDPSEvaluation ();
12258 /* if this is remateriazable */
12259 if (AOP_TYPE (to) == AOP_IMMD) {
12260 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12261 } else { /* we need to get it byte by byte */
12262 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12263 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12264 if (options.model == MODEL_FLAT24) {
12265 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12268 _endLazyDPSEvaluation ();
12271 freeAsmop (to, NULL, ic, FALSE);
12273 _G.dptrInUse = _G.dptr1InUse = 1;
12274 aopOp (count, ic->next->next, FALSE,FALSE);
12275 lbl =newiTempLabel(NULL);
12277 /* now for the actual copy */
12278 if (AOP_TYPE(count) == AOP_LIT &&
12279 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12280 emitcode (";","OH JOY auto increment with djnz (very fast)");
12281 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12282 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12283 freeAsmop (count, NULL, ic, FALSE);
12284 emitcode ("","!tlabeldef",lbl->key+100);
12285 emitcode ("movx", "a,@dptr"); /* read data from port */
12286 emitcode ("dec","dps"); /* switch to DPTR */
12287 emitcode ("movx", "@dptr,a"); /* save into location */
12288 emitcode ("inc", "dptr"); /* point to next area */
12289 emitcode ("inc","dps"); /* switch to DPTR2 */
12290 emitcode ("djnz","b,!tlabel",lbl->key+100);
12292 symbol *lbl1 = newiTempLabel(NULL);
12294 emitcode (";"," Auto increment but no djnz");
12295 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12296 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12297 freeAsmop (count, NULL, ic, FALSE);
12298 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12299 emitcode ("","!tlabeldef",lbl->key+100);
12300 emitcode ("movx", "a,@dptr");
12301 emitcode ("dec","dps"); /* switch to DPTR */
12302 emitcode ("movx", "@dptr,a");
12303 emitcode ("inc", "dptr");
12304 emitcode ("inc","dps"); /* switch to DPTR2 */
12305 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
12306 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
12307 emitcode ("mov","a,b");
12308 emitcode ("orl","a,_ap");
12309 emitcode ("jz","!tlabel",lbl1->key+100);
12310 emitcode ("mov","a,_ap");
12311 emitcode ("add","a,#!constbyte",0xFF);
12312 emitcode ("mov","_ap,a");
12313 emitcode ("mov","a,b");
12314 emitcode ("addc","a,#!constbyte",0xFF);
12315 emitcode ("mov","b,a");
12316 emitcode ("sjmp","!tlabel",lbl->key+100);
12317 emitcode ("","!tlabeldef",lbl1->key+100);
12319 emitcode ("mov", "dps,#0");
12320 _G.dptrInUse = _G.dptr1InUse = 0;
12321 unsavermask(rsave);
12325 /*-----------------------------------------------------------------*/
12326 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
12327 /* port, first parameter output area second parameter pointer to */
12328 /* port third parameter count */
12329 /*-----------------------------------------------------------------*/
12330 static void genOutp( iCode *ic, int nparms, operand **parms)
12332 operand *from , *to , *count;
12337 /* we know it has to be 3 parameters */
12338 assert (nparms == 3);
12340 rsave = newBitVect(16);
12341 /* save DPTR if it needs to be saved */
12342 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12343 if (bitVectBitValue(ic->rMask,i))
12344 rsave = bitVectSetBit(rsave,i);
12346 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12347 ds390_rUmaskForOp (IC_RESULT(ic))));
12354 aopOp (from, ic->next, FALSE, FALSE);
12356 /* get from into DPTR1 */
12357 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12358 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12359 if (options.model == MODEL_FLAT24) {
12360 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12363 freeAsmop (from, NULL, ic, FALSE);
12364 aopOp (to, ic, FALSE, FALSE);
12365 /* get "to" into DPTR */
12366 /* if the operand is already in dptr
12367 then we do nothing else we move the value to dptr */
12368 if (AOP_TYPE (to) != AOP_STR) {
12369 /* if already in DPTR then we need to push */
12370 if (AOP_TYPE(to) == AOP_DPTR) {
12371 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12372 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12373 if (options.model == MODEL_FLAT24)
12374 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12375 emitcode ("pop", "dph");
12376 emitcode ("pop", "dpl");
12378 _startLazyDPSEvaluation ();
12379 /* if this is remateriazable */
12380 if (AOP_TYPE (to) == AOP_IMMD) {
12381 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12382 } else { /* we need to get it byte by byte */
12383 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12384 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12385 if (options.model == MODEL_FLAT24) {
12386 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12389 _endLazyDPSEvaluation ();
12392 freeAsmop (to, NULL, ic, FALSE);
12394 _G.dptrInUse = _G.dptr1InUse = 1;
12395 aopOp (count, ic->next->next, FALSE,FALSE);
12396 lbl =newiTempLabel(NULL);
12398 /* now for the actual copy */
12399 if (AOP_TYPE(count) == AOP_LIT &&
12400 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12401 emitcode (";","OH JOY auto increment with djnz (very fast)");
12402 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12403 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12404 emitcode ("","!tlabeldef",lbl->key+100);
12405 emitcode ("movx", "a,@dptr"); /* read data from port */
12406 emitcode ("inc","dps"); /* switch to DPTR2 */
12407 emitcode ("movx", "@dptr,a"); /* save into location */
12408 emitcode ("inc", "dptr"); /* point to next area */
12409 emitcode ("dec","dps"); /* switch to DPTR */
12410 emitcode ("djnz","b,!tlabel",lbl->key+100);
12411 freeAsmop (count, NULL, ic, FALSE);
12413 symbol *lbl1 = newiTempLabel(NULL);
12415 emitcode (";"," Auto increment but no djnz");
12416 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12417 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12418 freeAsmop (count, NULL, ic, FALSE);
12419 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12420 emitcode ("","!tlabeldef",lbl->key+100);
12421 emitcode ("movx", "a,@dptr");
12422 emitcode ("inc", "dptr");
12423 emitcode ("inc","dps"); /* switch to DPTR2 */
12424 emitcode ("movx", "@dptr,a");
12425 emitcode ("dec","dps"); /* switch to DPTR */
12426 emitcode ("mov","a,b");
12427 emitcode ("orl","a,_ap");
12428 emitcode ("jz","!tlabel",lbl1->key+100);
12429 emitcode ("mov","a,_ap");
12430 emitcode ("add","a,#!constbyte",0xFF);
12431 emitcode ("mov","_ap,a");
12432 emitcode ("mov","a,b");
12433 emitcode ("addc","a,#!constbyte",0xFF);
12434 emitcode ("mov","b,a");
12435 emitcode ("sjmp","!tlabel",lbl->key+100);
12436 emitcode ("","!tlabeldef",lbl1->key+100);
12438 emitcode ("mov", "dps,#0");
12439 _G.dptrInUse = _G.dptr1InUse = 0;
12440 unsavermask(rsave);
12444 /*-----------------------------------------------------------------*/
12445 /* genSwapW - swap lower & high order bytes */
12446 /*-----------------------------------------------------------------*/
12447 static void genSwapW(iCode *ic, int nparms, operand **parms)
12451 assert (nparms==1);
12454 dest=IC_RESULT(ic);
12456 assert(getSize(operandType(src))==2);
12458 aopOp (src, ic, FALSE, FALSE);
12459 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
12461 MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
12463 freeAsmop (src, NULL, ic, FALSE);
12465 aopOp (dest,ic, FALSE, FALSE);
12466 aopPut(AOP(dest),"b",0);
12467 aopPut(AOP(dest),"a",1);
12468 freeAsmop (dest, NULL, ic, FALSE);
12471 /*-----------------------------------------------------------------*/
12472 /* genMemsetX - gencode for memSetX data */
12473 /*-----------------------------------------------------------------*/
12474 static void genMemsetX(iCode *ic, int nparms, operand **parms)
12476 operand *to , *val , *count;
12482 /* we know it has to be 3 parameters */
12483 assert (nparms == 3);
12489 /* save DPTR if it needs to be saved */
12490 rsave = newBitVect(16);
12491 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12492 if (bitVectBitValue(ic->rMask,i))
12493 rsave = bitVectSetBit(rsave,i);
12495 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12496 ds390_rUmaskForOp (IC_RESULT(ic))));
12499 aopOp (to, ic, FALSE, FALSE);
12500 /* get "to" into DPTR */
12501 /* if the operand is already in dptr
12502 then we do nothing else we move the value to dptr */
12503 if (AOP_TYPE (to) != AOP_STR) {
12504 /* if already in DPTR then we need to push */
12505 if (AOP_TYPE(to) == AOP_DPTR) {
12506 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12507 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12508 if (options.model == MODEL_FLAT24)
12509 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12510 emitcode ("pop", "dph");
12511 emitcode ("pop", "dpl");
12513 _startLazyDPSEvaluation ();
12514 /* if this is remateriazable */
12515 if (AOP_TYPE (to) == AOP_IMMD) {
12516 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12517 } else { /* we need to get it byte by byte */
12518 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12519 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12520 if (options.model == MODEL_FLAT24) {
12521 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12524 _endLazyDPSEvaluation ();
12527 freeAsmop (to, NULL, ic, FALSE);
12529 aopOp (val, ic->next->next, FALSE,FALSE);
12530 aopOp (count, ic->next->next, FALSE,FALSE);
12531 lbl =newiTempLabel(NULL);
12532 /* now for the actual copy */
12533 if (AOP_TYPE(count) == AOP_LIT &&
12534 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12535 l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
12536 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12538 emitcode ("","!tlabeldef",lbl->key+100);
12539 emitcode ("movx", "@dptr,a");
12540 emitcode ("inc", "dptr");
12541 emitcode ("djnz","b,!tlabel",lbl->key+100);
12543 symbol *lbl1 = newiTempLabel(NULL);
12545 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12546 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12547 emitcode ("","!tlabeldef",lbl->key+100);
12548 MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
12549 emitcode ("movx", "@dptr,a");
12550 emitcode ("inc", "dptr");
12551 emitcode ("mov","a,b");
12552 emitcode ("orl","a,_ap");
12553 emitcode ("jz","!tlabel",lbl1->key+100);
12554 emitcode ("mov","a,_ap");
12555 emitcode ("add","a,#!constbyte",0xFF);
12556 emitcode ("mov","_ap,a");
12557 emitcode ("mov","a,b");
12558 emitcode ("addc","a,#!constbyte",0xFF);
12559 emitcode ("mov","b,a");
12560 emitcode ("sjmp","!tlabel",lbl->key+100);
12561 emitcode ("","!tlabeldef",lbl1->key+100);
12563 freeAsmop (count, NULL, ic, FALSE);
12564 unsavermask(rsave);
12567 /*-----------------------------------------------------------------*/
12568 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12569 /*-----------------------------------------------------------------*/
12570 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12573 operand *pnum, *result;
12576 assert (nparms==1);
12577 /* save registers that need to be saved */
12578 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12579 ds390_rUmaskForOp (IC_RESULT(ic))));
12582 aopOp (pnum, ic, FALSE, FALSE);
12583 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12584 freeAsmop (pnum, NULL, ic, FALSE);
12585 emitcode ("lcall","NatLib_LoadPrimitive");
12586 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12587 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
12588 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12589 for (i = (size-1) ; i >= 0 ; i-- ) {
12590 emitcode ("push","a%s",javaRet[i]);
12592 for (i=0; i < size ; i++ ) {
12593 emitcode ("pop","a%s",
12594 aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12597 for (i = 0 ; i < size ; i++ ) {
12598 aopPut(AOP(result),javaRet[i],i);
12601 freeAsmop (result, NULL, ic, FALSE);
12602 unsavermask(rsave);
12605 /*-----------------------------------------------------------------*/
12606 /* genNatLibLoadPointer - calls TINI api function to load pointer */
12607 /*-----------------------------------------------------------------*/
12608 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12611 operand *pnum, *result;
12615 assert (nparms==1);
12616 /* save registers that need to be saved */
12617 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12618 ds390_rUmaskForOp (IC_RESULT(ic))));
12621 aopOp (pnum, ic, FALSE, FALSE);
12622 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12623 freeAsmop (pnum, NULL, ic, FALSE);
12624 emitcode ("lcall","NatLib_LoadPointer");
12625 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12626 if (AOP_TYPE(result)!=AOP_STR) {
12627 for (i = 0 ; i < size ; i++ ) {
12628 aopPut(AOP(result),fReturn[i],i);
12631 freeAsmop (result, NULL, ic, FALSE);
12632 unsavermask(rsave);
12635 /*-----------------------------------------------------------------*/
12636 /* genNatLibInstallStateBlock - */
12637 /*-----------------------------------------------------------------*/
12638 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
12639 operand **parms, const char *name)
12642 operand *psb, *handle;
12643 assert (nparms==2);
12645 /* save registers that need to be saved */
12646 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12647 ds390_rUmaskForOp (IC_RESULT(ic))));
12651 /* put pointer to state block into DPTR1 */
12652 aopOp (psb, ic, FALSE, FALSE);
12653 if (AOP_TYPE (psb) == AOP_IMMD) {
12654 emitcode ("mov","dps,#1");
12655 emitcode ("mov", "dptr,%s",
12656 aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12657 emitcode ("mov","dps,#0");
12659 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12660 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12661 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12663 freeAsmop (psb, NULL, ic, FALSE);
12665 /* put libraryID into DPTR */
12666 emitcode ("mov","dptr,#LibraryID");
12668 /* put handle into r3:r2 */
12669 aopOp (handle, ic, FALSE, FALSE);
12670 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12671 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12672 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12673 emitcode ("pop","ar3");
12674 emitcode ("pop","ar2");
12676 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12677 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12679 freeAsmop (psb, NULL, ic, FALSE);
12681 /* make the call */
12682 emitcode ("lcall","NatLib_Install%sStateBlock",name);
12684 /* put return value into place*/
12686 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12688 aopPut(AOP(IC_RESULT(ic)),"a",0);
12689 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12690 unsavermask(rsave);
12693 /*-----------------------------------------------------------------*/
12694 /* genNatLibRemoveStateBlock - */
12695 /*-----------------------------------------------------------------*/
12696 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12702 /* save registers that need to be saved */
12703 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12704 ds390_rUmaskForOp (IC_RESULT(ic))));
12706 /* put libraryID into DPTR */
12707 emitcode ("mov","dptr,#LibraryID");
12708 /* make the call */
12709 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12710 unsavermask(rsave);
12713 /*-----------------------------------------------------------------*/
12714 /* genNatLibGetStateBlock - */
12715 /*-----------------------------------------------------------------*/
12716 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12717 operand **parms,const char *name)
12720 symbol *lbl = newiTempLabel(NULL);
12723 /* save registers that need to be saved */
12724 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12725 ds390_rUmaskForOp (IC_RESULT(ic))));
12727 /* put libraryID into DPTR */
12728 emitcode ("mov","dptr,#LibraryID");
12729 /* make the call */
12730 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12731 emitcode ("jnz","!tlabel",lbl->key+100);
12733 /* put return value into place */
12734 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12735 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12736 emitcode ("push","ar3");
12737 emitcode ("push","ar2");
12738 emitcode ("pop","%s",
12739 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12740 emitcode ("pop","%s",
12741 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12743 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12744 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12746 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12747 emitcode ("","!tlabeldef",lbl->key+100);
12748 unsavermask(rsave);
12751 /*-----------------------------------------------------------------*/
12752 /* genMMMalloc - */
12753 /*-----------------------------------------------------------------*/
12754 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12755 int size, const char *name)
12760 symbol *lbl = newiTempLabel(NULL);
12762 assert (nparms == 1);
12763 /* save registers that need to be saved */
12764 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12765 ds390_rUmaskForOp (IC_RESULT(ic))));
12768 aopOp (bsize,ic,FALSE,FALSE);
12770 /* put the size in R4-R2 */
12771 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12772 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12773 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12775 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12776 emitcode("pop","ar4");
12778 emitcode("pop","ar3");
12779 emitcode("pop","ar2");
12781 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12782 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12784 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12787 freeAsmop (bsize, NULL, ic, FALSE);
12789 /* make the call */
12790 emitcode ("lcall","MM_%s",name);
12791 emitcode ("jz","!tlabel",lbl->key+100);
12792 emitcode ("mov","r2,#!constbyte",0xff);
12793 emitcode ("mov","r3,#!constbyte",0xff);
12794 emitcode ("","!tlabeldef",lbl->key+100);
12795 /* we don't care about the pointer : we just save the handle */
12796 rsym = OP_SYMBOL(IC_RESULT(ic));
12797 if (rsym->liveFrom != rsym->liveTo) {
12798 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12799 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12800 emitcode ("push","ar3");
12801 emitcode ("push","ar2");
12802 emitcode ("pop","%s",
12803 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12804 emitcode ("pop","%s",
12805 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12807 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12808 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12810 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12812 unsavermask(rsave);
12815 /*-----------------------------------------------------------------*/
12817 /*-----------------------------------------------------------------*/
12818 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12823 assert (nparms == 1);
12824 /* save registers that need to be saved */
12825 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12826 ds390_rUmaskForOp (IC_RESULT(ic))));
12829 aopOp (handle,ic,FALSE,FALSE);
12831 /* put the size in R4-R2 */
12832 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12833 emitcode("push","%s",
12834 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12835 emitcode("push","%s",
12836 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12837 emitcode("pop","ar3");
12838 emitcode("pop","ar2");
12840 emitcode ("mov","r2,%s",
12841 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12842 emitcode ("mov","r3,%s",
12843 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12845 freeAsmop (handle, NULL, ic, FALSE);
12847 /* make the call */
12848 emitcode ("lcall","MM_Deref");
12851 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12852 if (rsym->liveFrom != rsym->liveTo) {
12853 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12854 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12855 _startLazyDPSEvaluation ();
12857 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12858 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12859 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12861 _endLazyDPSEvaluation ();
12866 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12867 unsavermask(rsave);
12870 /*-----------------------------------------------------------------*/
12871 /* genMMUnrestrictedPersist - */
12872 /*-----------------------------------------------------------------*/
12873 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12878 assert (nparms == 1);
12879 /* save registers that need to be saved */
12880 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12881 ds390_rUmaskForOp (IC_RESULT(ic))));
12884 aopOp (handle,ic,FALSE,FALSE);
12886 /* put the size in R3-R2 */
12887 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12888 emitcode("push","%s",
12889 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12890 emitcode("push","%s",
12891 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12892 emitcode("pop","ar3");
12893 emitcode("pop","ar2");
12895 emitcode ("mov","r2,%s",
12896 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12897 emitcode ("mov","r3,%s",
12898 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12900 freeAsmop (handle, NULL, ic, FALSE);
12902 /* make the call */
12903 emitcode ("lcall","MM_UnrestrictedPersist");
12906 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12907 if (rsym->liveFrom != rsym->liveTo) {
12908 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12909 aopPut(AOP(IC_RESULT(ic)),"a",0);
12910 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12913 unsavermask(rsave);
12916 /*-----------------------------------------------------------------*/
12917 /* genSystemExecJavaProcess - */
12918 /*-----------------------------------------------------------------*/
12919 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12922 operand *handle, *pp;
12924 assert (nparms==2);
12925 /* save registers that need to be saved */
12926 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12927 ds390_rUmaskForOp (IC_RESULT(ic))));
12932 /* put the handle in R3-R2 */
12933 aopOp (handle,ic,FALSE,FALSE);
12934 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12935 emitcode("push","%s",
12936 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12937 emitcode("push","%s",
12938 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12939 emitcode("pop","ar3");
12940 emitcode("pop","ar2");
12942 emitcode ("mov","r2,%s",
12943 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12944 emitcode ("mov","r3,%s",
12945 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12947 freeAsmop (handle, NULL, ic, FALSE);
12949 /* put pointer in DPTR */
12950 aopOp (pp,ic,FALSE,FALSE);
12951 if (AOP_TYPE(pp) == AOP_IMMD) {
12952 emitcode ("mov", "dptr,%s",
12953 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12954 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12955 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12956 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12957 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12959 freeAsmop (handle, NULL, ic, FALSE);
12961 /* make the call */
12962 emitcode ("lcall","System_ExecJavaProcess");
12964 /* put result in place */
12966 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12967 if (rsym->liveFrom != rsym->liveTo) {
12968 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12969 aopPut(AOP(IC_RESULT(ic)),"a",0);
12970 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12974 unsavermask(rsave);
12977 /*-----------------------------------------------------------------*/
12978 /* genSystemRTCRegisters - */
12979 /*-----------------------------------------------------------------*/
12980 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12986 assert (nparms==1);
12987 /* save registers that need to be saved */
12988 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12989 ds390_rUmaskForOp (IC_RESULT(ic))));
12992 /* put pointer in DPTR */
12993 aopOp (pp,ic,FALSE,FALSE);
12994 if (AOP_TYPE (pp) == AOP_IMMD) {
12995 emitcode ("mov","dps,#1");
12996 emitcode ("mov", "dptr,%s",
12997 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12998 emitcode ("mov","dps,#0");
13000 emitcode ("mov","dpl1,%s",
13001 aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
13002 emitcode ("mov","dph1,%s",
13003 aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
13004 emitcode ("mov","dpx1,%s",
13005 aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
13007 freeAsmop (pp, NULL, ic, FALSE);
13009 /* make the call */
13010 emitcode ("lcall","System_%sRTCRegisters",name);
13012 unsavermask(rsave);
13015 /*-----------------------------------------------------------------*/
13016 /* genSystemThreadSleep - */
13017 /*-----------------------------------------------------------------*/
13018 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
13023 assert (nparms==1);
13024 /* save registers that need to be saved */
13025 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13026 ds390_rUmaskForOp (IC_RESULT(ic))));
13029 aopOp(to,ic,FALSE,FALSE);
13030 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
13031 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
13032 emitcode ("push","%s",
13033 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
13034 emitcode ("push","%s",
13035 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
13036 emitcode ("push","%s",
13037 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
13038 emitcode ("push","%s",
13039 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
13040 emitcode ("pop","ar3");
13041 emitcode ("pop","ar2");
13042 emitcode ("pop","ar1");
13043 emitcode ("pop","ar0");
13045 emitcode ("mov","r0,%s",
13046 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
13047 emitcode ("mov","r1,%s",
13048 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
13049 emitcode ("mov","r2,%s",
13050 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
13051 emitcode ("mov","r3,%s",
13052 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
13054 freeAsmop (to, NULL, ic, FALSE);
13056 /* suspend in acc */
13058 aopOp(s,ic,FALSE,FALSE);
13059 emitcode ("mov","a,%s",
13060 aopGet(AOP(s),0,FALSE,TRUE,NULL));
13061 freeAsmop (s, NULL, ic, FALSE);
13063 /* make the call */
13064 emitcode ("lcall","System_%s",name);
13066 unsavermask(rsave);
13069 /*-----------------------------------------------------------------*/
13070 /* genSystemThreadResume - */
13071 /*-----------------------------------------------------------------*/
13072 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
13077 assert (nparms==2);
13078 /* save registers that need to be saved */
13079 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13080 ds390_rUmaskForOp (IC_RESULT(ic))));
13086 aopOp(pid,ic,FALSE,FALSE);
13087 emitcode ("mov","r0,%s",
13088 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13089 freeAsmop (pid, NULL, ic, FALSE);
13092 aopOp(tid,ic,FALSE,FALSE);
13093 emitcode ("mov","a,%s",
13094 aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
13095 freeAsmop (tid, NULL, ic, FALSE);
13097 emitcode ("lcall","System_ThreadResume");
13099 /* put result into place */
13101 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13102 if (rsym->liveFrom != rsym->liveTo) {
13103 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13104 aopPut(AOP(IC_RESULT(ic)),"a",0);
13105 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13108 unsavermask(rsave);
13111 /*-----------------------------------------------------------------*/
13112 /* genSystemProcessResume - */
13113 /*-----------------------------------------------------------------*/
13114 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
13119 assert (nparms==1);
13120 /* save registers that need to be saved */
13121 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13122 ds390_rUmaskForOp (IC_RESULT(ic))));
13127 aopOp(pid,ic,FALSE,FALSE);
13128 emitcode ("mov","a,%s",
13129 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13130 freeAsmop (pid, NULL, ic, FALSE);
13132 emitcode ("lcall","System_ProcessResume");
13134 unsavermask(rsave);
13137 /*-----------------------------------------------------------------*/
13139 /*-----------------------------------------------------------------*/
13140 static void genSystem (iCode *ic,int nparms,char *name)
13142 assert(nparms == 0);
13144 emitcode ("lcall","System_%s",name);
13147 /*-----------------------------------------------------------------*/
13148 /* genSystemPoll - */
13149 /*-----------------------------------------------------------------*/
13150 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
13155 assert (nparms==1);
13156 /* save registers that need to be saved */
13157 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13158 ds390_rUmaskForOp (IC_RESULT(ic))));
13161 aopOp (fp,ic,FALSE,FALSE);
13162 if (AOP_TYPE (fp) == AOP_IMMD) {
13163 emitcode ("mov", "dptr,%s",
13164 aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
13165 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
13166 emitcode ("mov","dpl,%s",
13167 aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
13168 emitcode ("mov","dph,%s",
13169 aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
13170 emitcode ("mov","dpx,%s",
13171 aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
13173 freeAsmop (fp, NULL, ic, FALSE);
13175 emitcode ("lcall","System_%sPoll",name);
13177 /* put result into place */
13179 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13180 if (rsym->liveFrom != rsym->liveTo) {
13181 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13182 aopPut(AOP(IC_RESULT(ic)),"a",0);
13183 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13186 unsavermask(rsave);
13189 /*-----------------------------------------------------------------*/
13190 /* genSystemGetCurrentID - */
13191 /*-----------------------------------------------------------------*/
13192 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
13194 assert (nparms==0);
13196 emitcode ("lcall","System_GetCurrent%sId",name);
13197 /* put result into place */
13199 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13200 if (rsym->liveFrom != rsym->liveTo) {
13201 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13202 aopPut(AOP(IC_RESULT(ic)),"a",0);
13203 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13208 /*-----------------------------------------------------------------*/
13209 /* genDummyRead - generate code for dummy read of volatiles */
13210 /*-----------------------------------------------------------------*/
13212 genDummyRead (iCode * ic)
13217 D(emitcode("; genDummyRead",""));
13219 op = IC_RIGHT (ic);
13220 if (op && IS_SYMOP (op))
13222 aopOp (op, ic, FALSE, FALSE);
13224 /* if the result is a bit */
13225 if (AOP_TYPE (op) == AOP_CRY)
13226 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13229 /* bit variables done */
13231 size = AOP_SIZE (op);
13235 MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13240 freeAsmop (op, NULL, ic, TRUE);
13244 if (op && IS_SYMOP (op))
13246 aopOp (op, ic, FALSE, FALSE);
13248 /* if the result is a bit */
13249 if (AOP_TYPE (op) == AOP_CRY)
13250 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13253 /* bit variables done */
13255 size = AOP_SIZE (op);
13259 MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13264 freeAsmop (op, NULL, ic, TRUE);
13269 /*-----------------------------------------------------------------*/
13270 /* genCritical - generate code for start of a critical sequence */
13271 /*-----------------------------------------------------------------*/
13273 genCritical (iCode *ic)
13275 symbol *tlbl = newiTempLabel (NULL);
13277 D(emitcode("; genCritical",""));
13279 if (IC_RESULT (ic))
13280 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
13282 emitcode ("setb", "c");
13283 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
13284 emitcode ("clr", "c");
13285 emitcode ("", "%05d$:", (tlbl->key + 100));
13287 if (IC_RESULT (ic))
13288 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
13290 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
13292 if (IC_RESULT (ic))
13293 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13296 /*-----------------------------------------------------------------*/
13297 /* genEndCritical - generate code for end of a critical sequence */
13298 /*-----------------------------------------------------------------*/
13300 genEndCritical (iCode *ic)
13302 D(emitcode("; genEndCritical",""));
13306 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
13307 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
13309 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
13310 emitcode ("mov", "ea,c");
13314 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE));
13315 emitcode ("rrc", "a");
13316 emitcode ("mov", "ea,c");
13318 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
13322 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
13323 emitcode ("mov", "ea,c");
13329 /*-----------------------------------------------------------------*/
13330 /* genBuiltIn - calls the appropriate function to generating code */
13331 /* for a built in function */
13332 /*-----------------------------------------------------------------*/
13333 static void genBuiltIn (iCode *ic)
13335 operand *bi_parms[MAX_BUILTIN_ARGS];
13340 /* get all the arguments for a built in function */
13341 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
13343 /* which function is it */
13344 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
13345 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
13346 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
13347 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
13348 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
13349 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
13350 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
13351 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
13352 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
13353 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
13354 genMemsetX(bi_iCode,nbi_parms,bi_parms);
13355 } else if (strcmp(bif->name,"__builtin_inp")==0) {
13356 genInp(bi_iCode,nbi_parms,bi_parms);
13357 } else if (strcmp(bif->name,"__builtin_outp")==0) {
13358 genOutp(bi_iCode,nbi_parms,bi_parms);
13359 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
13360 genSwapW(bi_iCode,nbi_parms,bi_parms);
13361 /* JavaNative builtIns */
13362 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
13363 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
13364 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
13365 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
13366 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
13367 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
13368 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
13369 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
13370 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
13371 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13372 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
13373 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13374 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
13375 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
13376 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
13377 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
13378 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
13379 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13380 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
13381 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13382 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
13383 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
13384 } else if (strcmp(bif->name,"MM_Malloc")==0) {
13385 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
13386 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
13387 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
13388 } else if (strcmp(bif->name,"MM_Free")==0) {
13389 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
13390 } else if (strcmp(bif->name,"MM_Deref")==0) {
13391 genMMDeref(bi_iCode,nbi_parms,bi_parms);
13392 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
13393 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
13394 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
13395 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
13396 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
13397 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
13398 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
13399 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
13400 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
13401 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
13402 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
13403 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
13404 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
13405 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
13406 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
13407 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
13408 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13409 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13410 } else if (strcmp(bif->name,"System_SaveThread")==0) {
13411 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13412 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13413 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13414 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
13415 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
13416 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
13417 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
13418 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
13419 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
13420 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
13421 genSystem(bi_iCode,nbi_parms,"ProcessYield");
13422 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
13423 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
13424 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
13425 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
13426 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
13427 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
13428 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
13429 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
13430 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
13431 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
13433 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
13439 /*-----------------------------------------------------------------*/
13440 /* gen390Code - generate code for Dallas 390 based controllers */
13441 /*-----------------------------------------------------------------*/
13443 gen390Code (iCode * lic)
13448 lineHead = lineCurr = NULL;
13449 dptrn[1][0] = "dpl1";
13450 dptrn[1][1] = "dph1";
13451 dptrn[1][2] = "dpx1";
13453 if (options.model == MODEL_FLAT24) {
13454 fReturnSizeDS390 = 5;
13455 fReturn = fReturn24;
13457 fReturnSizeDS390 = 4;
13458 fReturn = fReturn16;
13459 options.stack10bit=0;
13462 /* print the allocation information */
13463 if (allocInfo && currFunc)
13464 printAllocInfo (currFunc, codeOutFile);
13466 /* if debug information required */
13467 if (options.debug && currFunc)
13469 debugFile->writeFunction (currFunc, lic);
13471 /* stack pointer name */
13472 if (options.useXstack)
13478 for (ic = lic; ic; ic = ic->next)
13480 _G.current_iCode = ic;
13482 if (ic->lineno && cln != ic->lineno)
13486 debugFile->writeCLine (ic);
13488 if (!options.noCcodeInAsm) {
13489 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
13490 printCLine(ic->filename, ic->lineno));
13494 if (options.iCodeInAsm) {
13495 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
13497 /* if the result is marked as
13498 spilt and rematerializable or code for
13499 this has already been generated then
13501 if (resultRemat (ic) || ic->generated)
13504 /* depending on the operation */
13524 /* IPOP happens only when trying to restore a
13525 spilt live range, if there is an ifx statement
13526 following this pop then the if statement might
13527 be using some of the registers being popped which
13528 would destory the contents of the register so
13529 we need to check for this condition and handle it */
13531 ic->next->op == IFX &&
13532 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
13533 genIfx (ic->next, ic);
13551 genEndFunction (ic);
13571 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
13588 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
13592 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
13599 /* note these two are xlated by algebraic equivalence
13600 during parsing SDCC.y */
13601 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13602 "got '>=' or '<=' shouldn't have come here");
13606 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
13618 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
13622 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
13626 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
13650 genRightShift (ic);
13653 case GET_VALUE_AT_ADDRESS:
13654 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13658 if (POINTER_SET (ic))
13659 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13685 if (ic->builtinSEND) genBuiltIn(ic);
13686 else addSet (&_G.sendSet, ic);
13689 case DUMMY_READ_VOLATILE:
13698 genEndCritical (ic);
13705 #if 0 // obsolete, and buggy for != xdata
13717 /* now we are ready to call the
13718 peep hole optimizer */
13719 if (!options.nopeep)
13720 peepHole (&lineHead);
13722 /* now do the actual printing */
13723 printLine (lineHead, codeOutFile);