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 -------------------------------------------------------------------------*/
36 #include "SDCCglobl.h"
39 #define BETTER_LITERAL_SHIFT
41 char *aopLiteral (value * val, int offset);
44 /* this is the down and dirty file with all kinds of
45 kludgy & hacky stuff. This is what it is all about
46 CODE GENERATION for a specific MCU . some of the
47 routines may be reusable, will have to see */
49 static char *zero = "#0";
50 static char *one = "#1";
55 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
56 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
58 unsigned fReturnSizeDS390 = 5; /* shared with ralloc.c */
59 static char *fReturn24[] =
60 {"dpl", "dph", "dpx", "b", "a"};
61 static char *fReturn16[] =
62 {"dpl", "dph", "b", "a"};
63 static char **fReturn = fReturn24;
64 static char *accUse[] =
66 static char *dptrn[2][3];
67 static char *javaRet[] = { "r0","r1","r2","r3"};
68 static short rbank = -1;
85 static char *rb1regs[] = {
86 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
89 static void saveRBank (int, iCode *, bool);
91 #define RESULTONSTACK(x) \
92 (IC_RESULT(x) && IC_RESULT(x)->aop && \
93 IC_RESULT(x)->aop->type == AOP_STK )
95 #define MOVA(x) _movA(x)
96 #define MOVB(x) _movB(x)
98 #define CLRC emitcode("clr","c")
99 #define SETC emitcode("setb","c")
101 // A scratch register which will be used to hold
102 // result bytes from operands in far space via DPTR2.
103 #define DP2_RESULT_REG "_ap"
105 static lineNode *lineHead = NULL;
106 static lineNode *lineCurr = NULL;
108 static unsigned char SLMask[] =
109 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
110 0xE0, 0xC0, 0x80, 0x00};
111 static unsigned char SRMask[] =
112 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
113 0x07, 0x03, 0x01, 0x00};
119 #define PROTECT_SP {if (options.protect_sp_update) { \
120 symbol *lbl = newiTempLabel(NULL); \
121 emitcode ("setb","F1"); \
122 emitcode ("jbc","EA,!tlabel",lbl->key+100); \
123 emitcode ("clr","F1"); \
124 emitcode ("","!tlabeldef",lbl->key+100); \
126 #define UNPROTECT_SP { if (options.protect_sp_update) { \
127 symbol *lbl = newiTempLabel(NULL); \
128 emitcode ("jnb","F1,!tlabel",lbl->key+100); \
129 emitcode ("setb","EA"); \
130 emitcode ("","!tlabeldef",lbl->key+100); \
134 /*-----------------------------------------------------------------*/
135 /* emitcode - writes the code into a file : for now it is simple */
136 /*-----------------------------------------------------------------*/
138 emitcode (char *inst, char *fmt,...)
141 char lb[INITIAL_INLINEASM];
150 SNPRINTF (lb, sizeof(lb), "%s\t", inst);
154 SNPRINTF (lb, sizeof(lb), "%s", inst);
157 tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb),
162 tvsprintf (lb, sizeof(lb), fmt, ap);
166 while (isspace (*lbp))
173 lineCurr = (lineCurr ?
174 connectLine (lineCurr, newLineNode (lb)) :
175 (lineHead = newLineNode (lb)));
178 lineCurr->isInline = _G.inLine;
179 lineCurr->isDebug = _G.debugLine;
184 // Move the passed value into A unless it is already there.
189 if (strcmp(s,"a") && strcmp(s,"acc"))
191 emitcode("mov","a,%s",s);
196 // Move the passed value into B unless it is already there.
203 emitcode("mov","b,%s",s);
207 /*-----------------------------------------------------------------*/
208 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
209 /*-----------------------------------------------------------------*/
211 getFreePtr (iCode * ic, asmop ** aopp, bool result)
216 /* the logic: if r0 & r1 used in the instruction
217 then we are in trouble otherwise */
219 /* first check if r0 & r1 are used by this
220 instruction, in which case we are in trouble */
221 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
222 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
227 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
228 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
230 /* if no usage of r0 then return it */
233 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
234 (*aopp)->type = AOP_R0;
236 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
239 /* if no usage of r1 then return it */
242 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
243 (*aopp)->type = AOP_R1;
245 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
248 /* now we know they both have usage */
249 /* if r0 not used in this instruction */
252 /* push it if not already pushed */
255 emitcode ("push", "%s",
256 ds390_regWithIdx (R0_IDX)->dname);
260 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
261 (*aopp)->type = AOP_R0;
263 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
266 /* if r1 not used then */
270 /* push it if not already pushed */
273 emitcode ("push", "%s",
274 ds390_regWithIdx (R1_IDX)->dname);
278 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
279 (*aopp)->type = AOP_R1;
280 return ds390_regWithIdx (R1_IDX);
284 /* I said end of world but not quite end of world yet */
285 /* if this is a result then we can push it on the stack */
288 (*aopp)->type = AOP_STK;
292 /* other wise this is true end of the world */
293 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
294 "getFreePtr should never reach here");
297 return NULL; // notreached, but makes compiler happy.
300 /*-----------------------------------------------------------------*/
301 /* newAsmop - creates a new asmOp */
302 /*-----------------------------------------------------------------*/
304 newAsmop (short type)
308 aop = Safe_calloc (1, sizeof (asmop));
313 static int _currentDPS; /* Current processor DPS. */
314 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
315 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
317 /*-----------------------------------------------------------------*/
318 /* genSetDPTR: generate code to select which DPTR is in use (zero */
319 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
320 /* alternate DPTR (DPL1/DPH1/DPX1). */
321 /*-----------------------------------------------------------------*/
326 /* If we are doing lazy evaluation, simply note the desired
327 * change, but don't emit any code yet.
337 emitcode ("mov", "dps,#0");
342 emitcode ("mov", "dps,#1");
346 /*-----------------------------------------------------------------*/
347 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
349 /* Any code that operates on DPTR (NB: not on the individual */
350 /* components, like DPH) *must* call _flushLazyDPS() before using */
351 /* DPTR within a lazy DPS evaluation block. */
353 /* Note that aopPut and aopGet already contain the proper calls to */
354 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
355 /* DPS evaluation block. */
357 /* Also, _flushLazyDPS must be called before any flow control */
358 /* operations that could potentially branch out of the block. */
360 /* Lazy DPS evaluation is simply an optimization (though an */
361 /* important one), so if in doubt, leave it out. */
362 /*-----------------------------------------------------------------*/
364 _startLazyDPSEvaluation (void)
368 #ifdef BETTER_LITERAL_SHIFT
375 /*-----------------------------------------------------------------*/
376 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
377 /* desired one. Call before using DPTR within a lazy DPS evaluation */
379 /*-----------------------------------------------------------------*/
389 if (_desiredDPS != _currentDPS)
393 emitcode ("inc", "dps");
397 emitcode ("dec", "dps");
399 _currentDPS = _desiredDPS;
403 /*-----------------------------------------------------------------*/
404 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
406 /* Forces us back to the safe state (standard DPTR selected). */
407 /*-----------------------------------------------------------------*/
409 _endLazyDPSEvaluation (void)
411 #ifdef BETTER_LITERAL_SHIFT
430 /*-----------------------------------------------------------------*/
431 /* pointerCode - returns the code for a pointer type */
432 /*-----------------------------------------------------------------*/
434 pointerCode (sym_link * etype)
437 return PTR_TYPE (SPEC_OCLS (etype));
441 /*-----------------------------------------------------------------*/
442 /* leftRightUseAcc - returns size of accumulator use by operands */
443 /*-----------------------------------------------------------------*/
445 leftRightUseAcc(iCode *ic)
454 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
455 "null iCode pointer");
462 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
465 size = getSize (OP_SYMBOL (op)->type);
470 else if (ic->op == JUMPTABLE)
473 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
476 size = getSize (OP_SYMBOL (op)->type);
484 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
487 size = getSize (OP_SYMBOL (op)->type);
492 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
495 size = getSize (OP_SYMBOL (op)->type);
507 /*-----------------------------------------------------------------*/
508 /* aopForSym - for a true symbol */
509 /*-----------------------------------------------------------------*/
511 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
514 memmap *space = SPEC_OCLS (sym->etype);
515 int accuse = leftRightUseAcc (ic);
517 /* if already has one */
520 if ((sym->aop->type == AOP_DPTR && useDP2)
521 || (sym->aop->type == AOP_DPTR2 && !useDP2))
527 /* assign depending on the storage class */
528 /* if it is on the stack or indirectly addressable */
529 /* space we need to assign either r0 or r1 to it */
530 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
532 sym->aop = aop = newAsmop (0);
533 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
534 aop->size = getSize (sym->type);
536 /* now assign the address of the variable to
537 the pointer register */
538 if (aop->type != AOP_STK)
543 if (_G.accInUse || accuse)
544 emitcode ("push", "acc");
546 if (_G.bInUse || (accuse>1))
547 emitcode ("push", "b");
549 emitcode ("mov", "a,_bp");
550 emitcode ("add", "a,#!constbyte",
552 ((char) (sym->stack - _G.nRegsSaved)) :
553 ((char) sym->stack)) & 0xff);
554 emitcode ("mov", "%s,a",
555 aop->aopu.aop_ptr->name);
557 if (_G.bInUse || (accuse>1))
558 emitcode ("pop", "b");
560 if (_G.accInUse || accuse)
561 emitcode ("pop", "acc");
564 emitcode ("mov", "%s,#%s",
565 aop->aopu.aop_ptr->name,
567 aop->paged = space->paged;
570 aop->aopu.aop_stk = sym->stack;
574 if (sym->onStack && options.stack10bit)
576 short stack_val = -((sym->stack < 0) ?
577 ((short) (sym->stack - _G.nRegsSaved)) :
578 ((short) sym->stack)) ;
579 if (useDP2 && _G.dptr1InUse) {
580 emitcode ("push","dpl1");
581 emitcode ("push","dph1");
582 emitcode ("push","dpx1");
583 } else if (_G.dptrInUse ) {
584 emitcode ("push","dpl");
585 emitcode ("push","dph");
586 emitcode ("push","dpx");
588 /* It's on the 10 bit stack, which is located in
591 if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
593 if (options.model == MODEL_FLAT24)
595 emitcode ("mov", "dpx1,#!constbyte",
596 (options.stack_loc >> 16) & 0xff);
598 emitcode ("mov", "dph1,_bpx+1");
600 emitcode ("mov", "dpl1,_bpx");
601 emitcode ("mov","dps,#1");
603 if (options.model == MODEL_FLAT24)
605 emitcode ("mov", "dpx,#!constbyte",
606 (options.stack_loc >> 16) & 0xff);
608 emitcode ("mov", "dph,_bpx+1");
609 emitcode ("mov", "dpl,_bpx");
611 stack_val = -stack_val;
612 while (stack_val--) {
613 emitcode ("inc","dptr");
616 emitcode("mov","dps,#0");
619 if (_G.accInUse || accuse)
620 emitcode ("push", "acc");
622 if (_G.bInUse || (accuse>1))
623 emitcode ("push", "b");
625 emitcode ("mov", "a,_bpx");
626 emitcode ("clr","c");
627 emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
628 emitcode ("mov","b,a");
629 emitcode ("mov","a,_bpx+1");
630 emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
632 if (options.model == MODEL_FLAT24)
634 emitcode ("mov", "dpx1,#!constbyte",
635 (options.stack_loc >> 16) & 0xff);
637 emitcode ("mov", "dph1,a");
638 emitcode ("mov", "dpl1,b");
640 if (options.model == MODEL_FLAT24)
642 emitcode ("mov", "dpx,#!constbyte",
643 (options.stack_loc >> 16) & 0xff);
645 emitcode ("mov", "dph,a");
646 emitcode ("mov", "dpl,b");
649 if (_G.bInUse || (accuse>1))
650 emitcode ("pop", "b");
652 if (_G.accInUse || accuse)
653 emitcode ("pop", "acc");
655 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
656 aop->size = getSize (sym->type);
660 /* if in bit space */
661 if (IN_BITSPACE (space))
663 sym->aop = aop = newAsmop (AOP_CRY);
664 aop->aopu.aop_dir = sym->rname;
665 aop->size = getSize (sym->type);
668 /* if it is in direct space */
669 if (IN_DIRSPACE (space))
671 sym->aop = aop = newAsmop (AOP_DIR);
672 aop->aopu.aop_dir = sym->rname;
673 aop->size = getSize (sym->type);
677 /* special case for a function */
678 if (IS_FUNC (sym->type) && !(sym->isitmp))
680 sym->aop = aop = newAsmop (AOP_IMMD);
681 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
682 aop->size = FPTRSIZE;
686 /* only remaining is far space */
687 /* in which case DPTR gets the address */
688 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
693 emitcode ("mov", "dptr,#%s", sym->rname);
698 emitcode ("mov", "dptr,#%s", sym->rname);
700 aop->size = getSize (sym->type);
702 /* if it is in code space */
703 if (IN_CODESPACE (space))
709 /*-----------------------------------------------------------------*/
710 /* aopForRemat - rematerialzes an object */
711 /*-----------------------------------------------------------------*/
713 aopForRemat (symbol * sym)
715 iCode *ic = sym->rematiCode;
716 asmop *aop = newAsmop (AOP_IMMD);
723 val += (int) operandLitValue (IC_RIGHT (ic));
724 else if (ic->op == '-')
725 val -= (int) operandLitValue (IC_RIGHT (ic));
726 else if (IS_CAST_ICODE(ic)) {
727 sym_link *from_type = operandType(IC_RIGHT(ic));
728 aop->aopu.aop_immd.from_cast_remat = 1;
729 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
730 ptr_type = DCL_TYPE(from_type);
731 if (ptr_type == IPOINTER) {
738 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
743 SNPRINTF (buffer, sizeof(buffer),
745 OP_SYMBOL (IC_LEFT (ic))->rname,
746 val >= 0 ? '+' : '-',
747 abs (val) & 0xffffff);
751 if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
753 SNPRINTF(buffer, sizeof(buffer),
754 "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
758 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
762 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
763 /* set immd2 field if required */
764 if (aop->aopu.aop_immd.from_cast_remat)
766 tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
767 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
773 /*-----------------------------------------------------------------*/
774 /* aopHasRegs - returns true if aop has regs between from-to */
775 /*-----------------------------------------------------------------*/
776 static int aopHasRegs(asmop *aop, int from, int to)
780 if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
782 for (; size < aop->size ; size++) {
784 for (reg = from ; reg <= to ; reg++)
785 if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
790 /*-----------------------------------------------------------------*/
791 /* regsInCommon - two operands have some registers in common */
792 /*-----------------------------------------------------------------*/
794 regsInCommon (operand * op1, operand * op2)
799 /* if they have registers in common */
800 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
803 sym1 = OP_SYMBOL (op1);
804 sym2 = OP_SYMBOL (op2);
806 if (sym1->nRegs == 0 || sym2->nRegs == 0)
809 for (i = 0; i < sym1->nRegs; i++)
815 for (j = 0; j < sym2->nRegs; j++)
820 if (sym2->regs[j] == sym1->regs[i])
828 /*-----------------------------------------------------------------*/
829 /* operandsEqu - equivalent */
830 /*-----------------------------------------------------------------*/
832 operandsEqu (operand * op1, operand * op2)
836 /* if they not symbols */
837 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
840 sym1 = OP_SYMBOL (op1);
841 sym2 = OP_SYMBOL (op2);
843 /* if both are itemps & one is spilt
844 and the other is not then false */
845 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
846 sym1->isspilt != sym2->isspilt)
849 /* if they are the same */
853 if (strcmp (sym1->rname, sym2->rname) == 0)
857 /* if left is a tmp & right is not */
858 if (IS_ITEMP (op1) &&
861 (sym1->usl.spillLoc == sym2))
864 if (IS_ITEMP (op2) &&
868 (sym2->usl.spillLoc == sym1))
871 /* are they spilt to the same location */
872 if (IS_ITEMP (op2) &&
876 (sym1->usl.spillLoc == sym2->usl.spillLoc))
882 /*-----------------------------------------------------------------*/
883 /* sameRegs - two asmops have the same registers */
884 /*-----------------------------------------------------------------*/
886 sameRegs (asmop * aop1, asmop * aop2)
892 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
899 if (aop1->type != AOP_REG ||
900 aop2->type != AOP_REG)
903 if (aop1->size != aop2->size)
906 for (i = 0; i < aop1->size; i++)
907 if (aop1->aopu.aop_reg[i] !=
908 aop2->aopu.aop_reg[i])
914 /*-----------------------------------------------------------------*/
915 /* aopOp - allocates an asmop for an operand : */
916 /*-----------------------------------------------------------------*/
918 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
927 /* if this a literal */
928 if (IS_OP_LITERAL (op))
930 op->aop = aop = newAsmop (AOP_LIT);
931 aop->aopu.aop_lit = op->operand.valOperand;
932 aop->size = getSize (operandType (op));
936 /* if already has a asmop then continue */
939 if ((op->aop->type == AOP_DPTR && useDP2)
940 || (op->aop->type == AOP_DPTR2 && !useDP2))
946 /* if the underlying symbol has a aop */
947 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
949 op->aop = OP_SYMBOL (op)->aop;
950 if ((op->aop->type == AOP_DPTR && useDP2)
951 || (op->aop->type == AOP_DPTR2 && !useDP2))
957 /* if this is a true symbol */
958 if (IS_TRUE_SYMOP (op))
960 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
964 /* this is a temporary : this has
970 e) can be a return use only */
972 sym = OP_SYMBOL (op);
975 /* if the type is a conditional */
976 if (sym->regType == REG_CND)
978 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
983 /* if it is spilt then two situations
985 b) has a spill location */
986 if (sym->isspilt || sym->nRegs == 0)
989 /* rematerialize it NOW */
992 sym->aop = op->aop = aop =
994 aop->size = getSize (sym->type);
1001 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
1002 aop->size = getSize (sym->type);
1003 for (i = 0; i < 2; i++)
1004 aop->aopu.aop_str[i] = accUse[i];
1014 /* a AOP_STR uses DPTR, but DPTR is already in use;
1017 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
1020 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1021 aop->size = getSize (sym->type);
1022 for (i = 0; i < (int) fReturnSizeDS390; i++)
1023 aop->aopu.aop_str[i] = fReturn[i];
1027 if (sym->dptr) { /* has been allocated to a DPTRn */
1028 aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
1029 aop->size = getSize (sym->type);
1030 aop->aopu.dptr = sym->dptr;
1034 if (sym->usl.spillLoc)
1036 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1038 /* force a new aop if sizes differ */
1039 sym->usl.spillLoc->aop = NULL;
1041 sym->aop = op->aop = aop =
1042 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
1043 aop->size = getSize (sym->type);
1047 /* else must be a dummy iTemp */
1048 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1049 aop->size = getSize (sym->type);
1053 /* must be in a register */
1054 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1055 aop->size = sym->nRegs;
1056 for (i = 0; i < sym->nRegs; i++)
1057 aop->aopu.aop_reg[i] = sym->regs[i];
1060 /*-----------------------------------------------------------------*/
1061 /* freeAsmop - free up the asmop given to an operand */
1062 /*----------------------------------------------------------------*/
1064 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1081 /* depending on the asmop type only three cases need work AOP_RO
1082 , AOP_R1 && AOP_STK */
1090 emitcode ("pop", "ar0");
1094 bitVectUnSetBit (ic->rUsed, R0_IDX);
1102 emitcode ("pop", "ar1");
1106 bitVectUnSetBit (ic->rUsed, R1_IDX);
1112 int stk = aop->aopu.aop_stk + aop->size;
1113 bitVectUnSetBit (ic->rUsed, R0_IDX);
1114 bitVectUnSetBit (ic->rUsed, R1_IDX);
1116 getFreePtr (ic, &aop, FALSE);
1118 if (options.stack10bit)
1120 /* I'm not sure what to do here yet... */
1123 "*** Warning: probably generating bad code for "
1124 "10 bit stack mode.\n");
1129 emitcode ("mov", "a,_bp");
1130 emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1131 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1135 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1140 emitcode ("pop", "acc");
1141 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1144 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1147 freeAsmop (op, NULL, ic, TRUE);
1150 emitcode ("pop", "ar0");
1156 emitcode ("pop", "ar1");
1161 if (_G.dptr1InUse) {
1162 emitcode ("pop","dpx1");
1163 emitcode ("pop","dph1");
1164 emitcode ("pop","dpl1");
1169 emitcode ("pop","dpx");
1170 emitcode ("pop","dph");
1171 emitcode ("pop","dpl");
1176 /* all other cases just dealloc */
1182 OP_SYMBOL (op)->aop = NULL;
1183 /* if the symbol has a spill */
1185 SPIL_LOC (op)->aop = NULL;
1190 #define DEFAULT_ACC_WARNING 0
1191 static int saveAccWarn = DEFAULT_ACC_WARNING;
1193 /*-------------------------------------------------------------------*/
1194 /* aopGet - for fetching value of the aop */
1196 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1197 /* in the accumulator. Set it to the name of a free register */
1198 /* if acc must be preserved; the register will be used to preserve */
1199 /* acc temporarily and to return the result byte. */
1200 /*-------------------------------------------------------------------*/
1209 /* offset is greater than
1211 if (offset > (aop->size - 1) &&
1212 aop->type != AOP_LIT)
1215 /* depending on type */
1223 /* if we need to increment it */
1224 while (offset > aop->coff)
1226 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1230 while (offset < aop->coff)
1232 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1239 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1240 return (dname ? "acc" : "a");
1242 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1243 return Safe_strdup(buffer);
1246 assert(offset <= 3);
1247 return dptrn[aop->aopu.dptr][offset];
1252 if (aop->type == AOP_DPTR2)
1260 // if (aop->type != AOP_DPTR2)
1262 // if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1263 // emitcode(";", "spanky: saveAcc for DPTR");
1266 emitcode ("xch", "a, %s", saveAcc);
1271 while (offset > aop->coff)
1273 emitcode ("inc", "dptr");
1277 while (offset < aop->coff)
1279 emitcode ("lcall", "__decdptr");
1286 emitcode ("clr", "a");
1287 emitcode ("movc", "a,@a+dptr");
1291 emitcode ("movx", "a,@dptr");
1294 if (aop->type == AOP_DPTR2)
1302 emitcode ("xch", "a, %s", saveAcc);
1303 // if (strcmp(saveAcc, "_ap"))
1305 // emitcode(";", "spiffy: non _ap return from aopGet.");
1310 return (dname ? "acc" : "a");
1313 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1315 SNPRINTF(buffer, sizeof(buffer),
1316 "%s",aop->aopu.aop_immd.aop_immd2);
1320 SNPRINTF(buffer, sizeof(buffer),
1321 "#%s", aop->aopu.aop_immd.aop_immd1);
1327 tsprintf(buffer, sizeof(buffer),
1328 "#!his",aop->aopu.aop_immd.aop_immd1);
1331 tsprintf(buffer, sizeof(buffer),
1332 "#!hihis",aop->aopu.aop_immd.aop_immd1);
1335 tsprintf(buffer, sizeof(buffer),
1336 "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1338 default: /* should not need this (just in case) */
1339 SNPRINTF (buffer, sizeof(buffer),
1341 aop->aopu.aop_immd.aop_immd1,
1347 SNPRINTF (buffer, sizeof(buffer),
1348 "#%s", aop->aopu.aop_immd.aop_immd1);
1350 return Safe_strdup(buffer);
1355 SNPRINTF (buffer, sizeof(buffer),
1362 SNPRINTF(buffer, sizeof(buffer),
1363 "%s", aop->aopu.aop_dir);
1366 return Safe_strdup(buffer);
1370 return aop->aopu.aop_reg[offset]->dname;
1372 return aop->aopu.aop_reg[offset]->name;
1375 emitcode ("clr", "a");
1376 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1377 emitcode ("rlc", "a");
1378 return (dname ? "acc" : "a");
1381 if (!offset && dname)
1383 return aop->aopu.aop_str[offset];
1386 return aopLiteral (aop->aopu.aop_lit, offset);
1390 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1394 return aop->aopu.aop_str[offset];
1398 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1399 "aopget got unsupported aop->type");
1402 return NULL; // not reached, but makes compiler happy.
1404 /*-----------------------------------------------------------------*/
1405 /* aopPut - puts a string for a aop */
1406 /*-----------------------------------------------------------------*/
1408 aopPut (asmop * aop, char *s, int offset)
1410 if (aop->size && offset > (aop->size - 1))
1412 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1413 "aopPut got offset > aop->size");
1417 /* will assign value to value */
1418 /* depending on where it is ofcourse */
1422 MOVA (s); /* read s in case it was volatile */
1428 SNPRINTF (buffer, sizeof(buffer),
1430 aop->aopu.aop_dir, offset);
1434 SNPRINTF (buffer, sizeof(buffer),
1435 "%s", aop->aopu.aop_dir);
1439 if (strcmp (buffer, s))
1441 emitcode ("mov", "%s,%s", buffer, s);
1446 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1447 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1450 strcmp (s, "r0") == 0 ||
1451 strcmp (s, "r1") == 0 ||
1452 strcmp (s, "r2") == 0 ||
1453 strcmp (s, "r3") == 0 ||
1454 strcmp (s, "r4") == 0 ||
1455 strcmp (s, "r5") == 0 ||
1456 strcmp (s, "r6") == 0 ||
1457 strcmp (s, "r7") == 0)
1459 emitcode ("mov", "%s,%s",
1460 aop->aopu.aop_reg[offset]->dname, s);
1464 emitcode ("mov", "%s,%s",
1465 aop->aopu.aop_reg[offset]->name, s);
1471 emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1477 if (aop->type == AOP_DPTR2)
1485 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1486 "aopPut writting to code space");
1490 while (offset > aop->coff)
1493 emitcode ("inc", "dptr");
1496 while (offset < aop->coff)
1499 emitcode ("lcall", "__decdptr");
1504 /* if not in accumulater */
1507 emitcode ("movx", "@dptr,a");
1509 if (aop->type == AOP_DPTR2)
1517 while (offset > aop->coff)
1520 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1522 while (offset < aop->coff)
1525 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1532 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1538 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1540 else if (strcmp (s, "r0") == 0 ||
1541 strcmp (s, "r1") == 0 ||
1542 strcmp (s, "r2") == 0 ||
1543 strcmp (s, "r3") == 0 ||
1544 strcmp (s, "r4") == 0 ||
1545 strcmp (s, "r5") == 0 ||
1546 strcmp (s, "r6") == 0 ||
1547 strcmp (s, "r7") == 0)
1550 SNPRINTF(buff, sizeof(buff),
1552 emitcode ("mov", "@%s,%s",
1553 aop->aopu.aop_ptr->name, buff);
1557 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1562 if (strcmp (s, "a") == 0)
1563 emitcode ("push", "acc");
1567 emitcode ("push", "acc");
1569 emitcode ("push", s);
1575 /* if bit variable */
1576 if (!aop->aopu.aop_dir)
1578 emitcode ("clr", "a");
1579 emitcode ("rlc", "a");
1584 emitcode ("clr", "%s", aop->aopu.aop_dir);
1586 emitcode ("setb", "%s", aop->aopu.aop_dir);
1587 else if (!strcmp (s, "c"))
1588 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1591 if (strcmp (s, "a"))
1596 /* set C, if a >= 1 */
1597 emitcode ("add", "a,#!constbyte",0xff);
1598 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1606 if (strcmp (aop->aopu.aop_str[offset], s))
1607 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1612 if (!offset && (strcmp (s, "acc") == 0))
1615 if (strcmp (aop->aopu.aop_str[offset], s))
1616 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1620 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1621 "aopPut got unsupported aop->type");
1628 /*--------------------------------------------------------------------*/
1629 /* reAdjustPreg - points a register back to where it should (coff==0) */
1630 /*--------------------------------------------------------------------*/
1632 reAdjustPreg (asmop * aop)
1634 if ((aop->coff==0) || (aop->size <= 1)) {
1643 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1647 if (aop->type == AOP_DPTR2)
1654 emitcode ("lcall", "__decdptr");
1657 if (aop->type == AOP_DPTR2)
1667 #define AOP(op) op->aop
1668 #define AOP_TYPE(op) AOP(op)->type
1669 #define AOP_SIZE(op) AOP(op)->size
1670 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1671 AOP_TYPE(x) == AOP_R0))
1673 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1674 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1677 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1678 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1679 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1680 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1681 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1682 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1684 // The following two macros can be used even if the aop has not yet been aopOp'd.
1685 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1686 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1688 /* Workaround for DS80C390 bug: div ab may return bogus results
1689 * if A is accessed in instruction immediately before the div.
1691 * Will be fixed in B4 rev of processor, Dallas claims.
1694 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1695 if (!AOP_NEEDSACC(RIGHT)) \
1697 /* We can load A first, then B, since \
1698 * B (the RIGHT operand) won't clobber A, \
1699 * thus avoiding touching A right before the div. \
1701 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1702 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1704 L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1709 /* Just stuff in a nop after loading A. */ \
1710 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1711 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1713 emitcode("nop", "; workaround for DS80C390 div bug."); \
1717 /*-----------------------------------------------------------------*/
1718 /* opIsGptr: returns non-zero if the passed operand is */
1719 /* a generic pointer type. */
1720 /*-----------------------------------------------------------------*/
1722 opIsGptr (operand * op)
1724 sym_link *type = operandType (op);
1726 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1733 /*-----------------------------------------------------------------*/
1734 /* getDataSize - get the operand data size */
1735 /*-----------------------------------------------------------------*/
1737 getDataSize (operand * op)
1740 size = AOP_SIZE (op);
1741 if (size == GPTRSIZE)
1743 sym_link *type = operandType (op);
1744 if (IS_GENPTR (type))
1746 /* generic pointer; arithmetic operations
1747 * should ignore the high byte (pointer type).
1755 /*-----------------------------------------------------------------*/
1756 /* outAcc - output Acc */
1757 /*-----------------------------------------------------------------*/
1759 outAcc (operand * result)
1762 size = getDataSize (result);
1765 aopPut (AOP (result), "a", 0);
1768 /* unsigned or positive */
1771 aopPut (AOP (result), zero, offset++);
1776 /*-----------------------------------------------------------------*/
1777 /* outBitC - output a bit C */
1778 /*-----------------------------------------------------------------*/
1780 outBitC (operand * result)
1782 /* if the result is bit */
1783 if (AOP_TYPE (result) == AOP_CRY)
1785 aopPut (AOP (result), "c", 0);
1789 emitcode ("clr", "a");
1790 emitcode ("rlc", "a");
1795 /*-----------------------------------------------------------------*/
1796 /* toBoolean - emit code for orl a,operator(sizeop) */
1797 /*-----------------------------------------------------------------*/
1799 toBoolean (operand * oper)
1801 int size = AOP_SIZE (oper) - 1;
1805 /* The generic part of a generic pointer should
1806 * not participate in it's truth value.
1808 * i.e. 0x10000000 is zero.
1810 if (opIsGptr (oper))
1812 D (emitcode (";", "toBoolean: generic ptr special case."););
1816 _startLazyDPSEvaluation ();
1817 if (AOP_NEEDSACC (oper) && size)
1822 emitcode ("push", "b");
1824 MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1828 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1835 emitcode ("orl", "b,%s",
1836 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1840 emitcode ("orl", "a,%s",
1841 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1844 _endLazyDPSEvaluation ();
1848 emitcode ("mov", "a,b");
1851 emitcode ("pop", "b");
1858 /*-----------------------------------------------------------------*/
1859 /* genNot - generate code for ! operation */
1860 /*-----------------------------------------------------------------*/
1866 D (emitcode (";", "genNot "););
1868 /* assign asmOps to operand & result */
1869 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1870 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1872 /* if in bit space then a special case */
1873 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1875 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1876 emitcode ("cpl", "c");
1877 outBitC (IC_RESULT (ic));
1881 toBoolean (IC_LEFT (ic));
1883 tlbl = newiTempLabel (NULL);
1884 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1885 emitcode ("", "!tlabeldef", tlbl->key + 100);
1886 outBitC (IC_RESULT (ic));
1889 /* release the aops */
1890 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1891 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1895 /*-----------------------------------------------------------------*/
1896 /* genCpl - generate code for complement */
1897 /*-----------------------------------------------------------------*/
1905 D (emitcode (";", "genCpl "););
1908 /* assign asmOps to operand & result */
1909 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1910 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1912 /* special case if in bit space */
1913 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1914 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1915 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1916 emitcode ("cpl", "c");
1917 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1920 tlbl=newiTempLabel(NULL);
1921 emitcode ("cjne", "%s,#0x01,%05d$",
1922 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1923 emitcode ("", "%05d$:", tlbl->key+100);
1924 outBitC (IC_RESULT(ic));
1928 size = AOP_SIZE (IC_RESULT (ic));
1929 _startLazyDPSEvaluation ();
1932 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1933 emitcode ("cpl", "a");
1934 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1936 _endLazyDPSEvaluation ();
1940 /* release the aops */
1941 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1942 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1945 /*-----------------------------------------------------------------*/
1946 /* genUminusFloat - unary minus for floating points */
1947 /*-----------------------------------------------------------------*/
1949 genUminusFloat (operand * op, operand * result)
1951 int size, offset = 0;
1953 D(emitcode (";", "genUminusFloat"););
1955 /* for this we just copy and then flip the bit */
1957 _startLazyDPSEvaluation ();
1958 size = AOP_SIZE (op) - 1;
1962 aopPut (AOP (result),
1963 aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1968 MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1970 emitcode ("cpl", "acc.7");
1971 aopPut (AOP (result), "a", offset);
1972 _endLazyDPSEvaluation ();
1975 /*-----------------------------------------------------------------*/
1976 /* genUminus - unary minus code generation */
1977 /*-----------------------------------------------------------------*/
1979 genUminus (iCode * ic)
1984 D (emitcode (";", "genUminus "););
1987 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1988 aopOp (IC_RESULT (ic), ic, TRUE, (AOP_TYPE(IC_LEFT (ic)) == AOP_DPTR));
1990 /* if both in bit space then special
1992 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1993 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1996 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1997 emitcode ("cpl", "c");
1998 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2002 optype = operandType (IC_LEFT (ic));
2004 /* if float then do float stuff */
2005 if (IS_FLOAT (optype))
2007 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2011 /* otherwise subtract from zero */
2012 size = AOP_SIZE (IC_LEFT (ic));
2014 _startLazyDPSEvaluation ();
2017 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
2018 if (!strcmp (l, "a"))
2022 emitcode ("cpl", "a");
2023 emitcode ("addc", "a,#0");
2029 emitcode ("clr", "a");
2030 emitcode ("subb", "a,%s", l);
2032 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2034 _endLazyDPSEvaluation ();
2036 /* if any remaining bytes in the result */
2037 /* we just need to propagate the sign */
2038 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
2040 emitcode ("rlc", "a");
2041 emitcode ("subb", "a,acc");
2043 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2047 /* release the aops */
2048 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2049 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2052 /*-----------------------------------------------------------------*/
2053 /* savermask - saves registers in the mask */
2054 /*-----------------------------------------------------------------*/
2055 static void savermask(bitVect *rs_mask)
2058 if (options.useXstack) {
2059 if (bitVectBitValue (rs_mask, R0_IDX))
2060 emitcode ("mov", "b,r0");
2061 emitcode ("mov", "r0,%s", spname);
2062 for (i = 0; i < ds390_nRegs; i++) {
2063 if (bitVectBitValue (rs_mask, i)) {
2065 emitcode ("mov", "a,b");
2067 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2068 emitcode ("movx", "@r0,a");
2069 emitcode ("inc", "r0");
2072 emitcode ("mov", "%s,r0", spname);
2073 if (bitVectBitValue (rs_mask, R0_IDX))
2074 emitcode ("mov", "r0,b");
2076 for (i = 0; i < ds390_nRegs; i++) {
2077 if (bitVectBitValue (rs_mask, i))
2078 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2083 /*-----------------------------------------------------------------*/
2084 /* saveRegisters - will look for a call and save the registers */
2085 /*-----------------------------------------------------------------*/
2087 saveRegisters (iCode * lic)
2093 for (ic = lic; ic; ic = ic->next)
2094 if (ic->op == CALL || ic->op == PCALL)
2099 fprintf (stderr, "found parameter push with no function call\n");
2103 /* if the registers have been saved already then
2106 || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2109 /* special case if DPTR alive across a function call then must save it
2110 even though callee saves */
2111 if (IS_SYMOP(IC_LEFT(ic)) &&
2112 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2114 rsave = newBitVect(ic->rMask->size);
2115 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2116 if (bitVectBitValue(ic->rMask,i))
2117 rsave = bitVectSetBit(rsave,i);
2119 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2121 /* safe the registers in use at this time but skip the
2122 ones for the result */
2123 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2124 ds390_rUmaskForOp (IC_RESULT(ic)));
2130 /*-----------------------------------------------------------------*/
2131 /* usavermask - restore registers with mask */
2132 /*-----------------------------------------------------------------*/
2133 static void unsavermask(bitVect *rs_mask)
2136 if (options.useXstack) {
2137 emitcode ("mov", "r0,%s", spname);
2138 for (i = ds390_nRegs; i >= 0; i--) {
2139 if (bitVectBitValue (rs_mask, i)) {
2140 emitcode ("dec", "r0");
2141 emitcode ("movx", "a,@r0");
2143 emitcode ("mov", "b,a");
2145 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2148 emitcode ("mov", "%s,r0", spname);
2149 if (bitVectBitValue (rs_mask, R0_IDX))
2150 emitcode ("mov", "r0,b");
2152 for (i = ds390_nRegs; i >= 0; i--) {
2153 if (bitVectBitValue (rs_mask, i))
2154 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2159 /*-----------------------------------------------------------------*/
2160 /* unsaveRegisters - pop the pushed registers */
2161 /*-----------------------------------------------------------------*/
2163 unsaveRegisters (iCode * ic)
2167 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2169 rsave = newBitVect(ic->rMask->size);
2170 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2171 if (bitVectBitValue(ic->rMask,i))
2172 rsave = bitVectSetBit(rsave,i);
2174 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2176 /* restore the registers in use at this time but skip the
2177 ones for the result */
2178 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2179 ds390_rUmaskForOp (IC_RESULT(ic)));
2185 /*-----------------------------------------------------------------*/
2187 /*-----------------------------------------------------------------*/
2189 pushSide (operand * oper, int size)
2192 _startLazyDPSEvaluation ();
2195 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2196 if (AOP_TYPE (oper) != AOP_REG &&
2197 AOP_TYPE (oper) != AOP_DIR &&
2200 emitcode ("mov", "a,%s", l);
2201 emitcode ("push", "acc");
2204 emitcode ("push", "%s", l);
2206 _endLazyDPSEvaluation ();
2209 /*-----------------------------------------------------------------*/
2210 /* assignResultValue - */
2211 /*-----------------------------------------------------------------*/
2213 assignResultValue (operand * oper)
2216 int size = AOP_SIZE (oper);
2217 bool pushedAcc = FALSE;
2219 if (size == fReturnSizeDS390)
2221 /* I don't think this case can ever happen... */
2222 /* ACC is the last part of this. If writing the result
2223 * uses AC, we must preserve it.
2225 if (AOP_NEEDSACC(oper))
2227 emitcode(";", "assignResultValue special case for ACC.");
2228 emitcode("push", "acc");
2235 _startLazyDPSEvaluation ();
2238 aopPut (AOP (oper), fReturn[offset], offset);
2241 _endLazyDPSEvaluation ();
2245 emitcode("pop", "acc");
2246 aopPut(AOP(oper), "a", offset);
2251 /*-----------------------------------------------------------------*/
2252 /* genXpush - pushes onto the external stack */
2253 /*-----------------------------------------------------------------*/
2255 genXpush (iCode * ic)
2257 asmop *aop = newAsmop (0);
2259 int size, offset = 0;
2261 D (emitcode (";", "genXpush ");
2264 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2265 r = getFreePtr (ic, &aop, FALSE);
2268 emitcode ("mov", "%s,_spx", r->name);
2270 size = AOP_SIZE (IC_LEFT (ic));
2271 _startLazyDPSEvaluation ();
2275 MOVA (aopGet (AOP (IC_LEFT (ic)),
2276 offset++, FALSE, FALSE, NULL));
2277 emitcode ("movx", "@%s,a", r->name);
2278 emitcode ("inc", "%s", r->name);
2281 _endLazyDPSEvaluation ();
2284 emitcode ("mov", "_spx,%s", r->name);
2286 freeAsmop (NULL, aop, ic, TRUE);
2287 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2290 /*-----------------------------------------------------------------*/
2291 /* genIpush - generate code for pushing this gets a little complex */
2292 /*-----------------------------------------------------------------*/
2294 genIpush (iCode * ic)
2296 int size, offset = 0;
2299 D (emitcode (";", "genIpush ");
2302 /* if this is not a parm push : ie. it is spill push
2303 and spill push is always done on the local stack */
2307 /* and the item is spilt then do nothing */
2308 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2311 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2312 size = AOP_SIZE (IC_LEFT (ic));
2313 /* push it on the stack */
2314 _startLazyDPSEvaluation ();
2317 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2323 emitcode ("push", "%s", l);
2325 _endLazyDPSEvaluation ();
2329 /* this is a paramter push: in this case we call
2330 the routine to find the call and save those
2331 registers that need to be saved */
2334 /* if use external stack then call the external
2335 stack pushing routine */
2336 if (options.useXstack)
2342 /* then do the push */
2343 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2345 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2346 size = AOP_SIZE (IC_LEFT (ic));
2348 _startLazyDPSEvaluation ();
2351 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2352 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2353 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2356 emitcode ("mov", "a,%s", l);
2357 emitcode ("push", "acc");
2361 emitcode ("push", "%s", l);
2364 _endLazyDPSEvaluation ();
2366 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2369 /*-----------------------------------------------------------------*/
2370 /* genIpop - recover the registers: can happen only for spilling */
2371 /*-----------------------------------------------------------------*/
2373 genIpop (iCode * ic)
2377 D (emitcode (";", "genIpop ");
2381 /* if the temp was not pushed then */
2382 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2385 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2386 size = AOP_SIZE (IC_LEFT (ic));
2387 offset = (size - 1);
2388 _startLazyDPSEvaluation ();
2391 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2392 FALSE, TRUE, NULL));
2394 _endLazyDPSEvaluation ();
2396 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2399 /*-----------------------------------------------------------------*/
2400 /* unsaveRBank - restores the resgister bank from stack */
2401 /*-----------------------------------------------------------------*/
2403 unsaveRBank (int bank, iCode * ic, bool popPsw)
2409 if (options.useXstack)
2413 /* Assume r0 is available for use. */
2414 r = ds390_regWithIdx (R0_IDX);;
2419 r = getFreePtr (ic, &aop, FALSE);
2421 emitcode ("mov", "%s,_spx", r->name);
2426 if (options.useXstack)
2428 emitcode ("movx", "a,@%s", r->name);
2429 emitcode ("mov", "psw,a");
2430 emitcode ("dec", "%s", r->name);
2434 emitcode ("pop", "psw");
2438 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2440 if (options.useXstack)
2442 emitcode ("movx", "a,@%s", r->name);
2443 emitcode ("mov", "(%s+%d),a",
2444 regs390[i].base, 8 * bank + regs390[i].offset);
2445 emitcode ("dec", "%s", r->name);
2449 emitcode ("pop", "(%s+%d)",
2450 regs390[i].base, 8 * bank + regs390[i].offset);
2453 if (options.useXstack)
2455 emitcode ("mov", "_spx,%s", r->name);
2460 freeAsmop (NULL, aop, ic, TRUE);
2464 /*-----------------------------------------------------------------*/
2465 /* saveRBank - saves an entire register bank on the stack */
2466 /*-----------------------------------------------------------------*/
2468 saveRBank (int bank, iCode * ic, bool pushPsw)
2474 if (options.useXstack)
2478 /* Assume r0 is available for use. */
2479 r = ds390_regWithIdx (R0_IDX);;
2484 r = getFreePtr (ic, &aop, FALSE);
2486 emitcode ("mov", "%s,_spx", r->name);
2489 for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2491 if (options.useXstack)
2493 emitcode ("inc", "%s", r->name);
2494 emitcode ("mov", "a,(%s+%d)",
2495 regs390[i].base, 8 * bank + regs390[i].offset);
2496 emitcode ("movx", "@%s,a", r->name);
2499 emitcode ("push", "(%s+%d)",
2500 regs390[i].base, 8 * bank + regs390[i].offset);
2505 if (options.useXstack)
2507 emitcode ("mov", "a,psw");
2508 emitcode ("movx", "@%s,a", r->name);
2509 emitcode ("inc", "%s", r->name);
2510 emitcode ("mov", "_spx,%s", r->name);
2514 emitcode ("push", "psw");
2517 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2522 freeAsmop (NULL, aop, ic, TRUE);
2531 /*-----------------------------------------------------------------*/
2532 /* genSend - gen code for SEND */
2533 /*-----------------------------------------------------------------*/
2534 static void genSend(set *sendSet)
2538 static int rb1_count = 0;
2540 for (sic = setFirstItem (sendSet); sic;
2541 sic = setNextItem (sendSet)) {
2542 int size, offset = 0;
2544 size=getSize(operandType(IC_LEFT(sic)));
2545 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2546 if (sendCount == 0) { /* first parameter */
2547 // we know that dpl(hxb) is the result, so
2549 _startLazyDPSEvaluation ();
2551 aopOp (IC_LEFT (sic), sic, FALSE,
2552 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2554 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2557 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2558 FALSE, FALSE, NULL);
2559 if (strcmp (l, fReturn[offset])) {
2560 emitcode ("mov", "%s,%s",
2566 _endLazyDPSEvaluation ();
2567 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2569 } else { /* if more parameter in registers */
2570 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2572 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2573 FALSE, FALSE, NULL));
2575 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2582 adjustEsp(const char *reg)
2584 emitcode ("anl","%s,#3", reg);
2585 if (TARGET_IS_DS400)
2587 emitcode ("orl","%s,#!constbyte",
2589 (options.stack_loc >> 8) & 0xff);
2593 /*-----------------------------------------------------------------*/
2594 /* genCall - generates a call statement */
2595 /*-----------------------------------------------------------------*/
2597 genCall (iCode * ic)
2600 bool restoreBank = FALSE;
2601 bool swapBanks = FALSE;
2603 D (emitcode (";", "genCall "););
2605 /* if we are calling a not _naked function that is not using
2606 the same register bank then we need to save the
2607 destination registers on the stack */
2608 dtype = operandType (IC_LEFT (ic));
2609 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2610 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2611 IFFUNC_ISISR (currFunc->type))
2615 /* This is unexpected; the bank should have been saved in
2618 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2624 /* if caller saves & we have not saved then */
2628 /* if send set is not empty the assign */
2629 /* We've saved all the registers we care about;
2630 * therefore, we may clobber any register not used
2631 * in the calling convention (i.e. anything not in
2636 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2637 genSend(reverseSet(_G.sendSet));
2639 genSend(_G.sendSet);
2646 emitcode ("mov", "psw,#!constbyte",
2647 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2651 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2652 OP_SYMBOL (IC_LEFT (ic))->rname :
2653 OP_SYMBOL (IC_LEFT (ic))->name));
2657 emitcode ("mov", "psw,#!constbyte",
2658 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2661 /* if we need assign a result value */
2662 if ((IS_ITEMP (IC_RESULT (ic)) &&
2663 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2664 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2665 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2666 IS_TRUE_SYMOP (IC_RESULT (ic)))
2668 if (isOperandInFarSpace (IC_RESULT (ic))
2669 && getSize (operandType (IC_RESULT (ic))) <= 2)
2671 int size = getSize (operandType (IC_RESULT (ic)));
2673 /* Special case for 1 or 2 byte return in far space. */
2677 emitcode ("mov", "b,%s", fReturn[1]);
2682 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2688 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2692 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2694 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2699 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2702 assignResultValue (IC_RESULT (ic));
2704 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2708 /* adjust the stack for parameters if
2710 if (ic->parmBytes) {
2712 if (options.stack10bit) {
2713 if (ic->parmBytes <= 10) {
2714 emitcode(";","stack adjustment for parms");
2715 for (i=0; i < ic->parmBytes ; i++) {
2716 emitcode("pop","acc");
2720 emitcode ("clr","c");
2721 emitcode ("mov","a,sp");
2722 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2723 emitcode ("mov","sp,a");
2724 emitcode ("mov","a,esp");
2726 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2727 emitcode ("mov","esp,a");
2731 if (ic->parmBytes > 3) {
2732 emitcode ("mov", "a,%s", spname);
2733 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2734 emitcode ("mov", "%s,a", spname);
2736 for (i = 0; i < ic->parmBytes; i++)
2737 emitcode ("dec", "%s", spname);
2741 /* if we hade saved some registers then unsave them */
2743 unsaveRegisters (ic);
2745 /* if register bank was saved then pop them */
2747 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2750 /*-----------------------------------------------------------------*/
2751 /* genPcall - generates a call by pointer statement */
2752 /*-----------------------------------------------------------------*/
2754 genPcall (iCode * ic)
2757 symbol *rlbl = newiTempLabel (NULL);
2758 bool restoreBank=FALSE;
2760 D (emitcode (";", "genPcall ");
2764 /* if caller saves & we have not saved then */
2768 /* if we are calling a function that is not using
2769 the same register bank then we need to save the
2770 destination registers on the stack */
2771 dtype = operandType (IC_LEFT (ic));
2772 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2773 IFFUNC_ISISR (currFunc->type) &&
2774 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2775 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2779 /* push the return address on to the stack */
2780 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2781 emitcode ("push", "acc");
2782 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2783 emitcode ("push", "acc");
2785 if (options.model == MODEL_FLAT24)
2787 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2788 emitcode ("push", "acc");
2791 /* now push the calling address */
2792 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2794 pushSide (IC_LEFT (ic), FPTRSIZE);
2796 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2798 /* if send set is not empty the assign */
2801 genSend(reverseSet(_G.sendSet));
2805 emitcode ("ret", "");
2806 emitcode ("", "!tlabeldef", (rlbl->key + 100));
2809 /* if we need assign a result value */
2810 if ((IS_ITEMP (IC_RESULT (ic)) &&
2811 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2812 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2813 IS_TRUE_SYMOP (IC_RESULT (ic)))
2817 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2820 assignResultValue (IC_RESULT (ic));
2822 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2825 /* adjust the stack for parameters if
2830 if (options.stack10bit) {
2831 if (ic->parmBytes <= 10) {
2832 emitcode(";","stack adjustment for parms");
2833 for (i=0; i < ic->parmBytes ; i++) {
2834 emitcode("pop","acc");
2838 emitcode ("clr","c");
2839 emitcode ("mov","a,sp");
2840 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2841 emitcode ("mov","sp,a");
2842 emitcode ("mov","a,esp");
2844 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2845 emitcode ("mov","esp,a");
2849 if (ic->parmBytes > 3) {
2850 emitcode ("mov", "a,%s", spname);
2851 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2852 emitcode ("mov", "%s,a", spname);
2855 for (i = 0; i < ic->parmBytes; i++)
2856 emitcode ("dec", "%s", spname);
2860 /* if register bank was saved then unsave them */
2862 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2864 /* if we hade saved some registers then
2867 unsaveRegisters (ic);
2871 /*-----------------------------------------------------------------*/
2872 /* resultRemat - result is rematerializable */
2873 /*-----------------------------------------------------------------*/
2875 resultRemat (iCode * ic)
2877 if (SKIP_IC (ic) || ic->op == IFX)
2880 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2882 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2883 if (sym->remat && !POINTER_SET (ic))
2890 #if defined(__BORLANDC__) || defined(_MSC_VER)
2891 #define STRCASECMP stricmp
2893 #define STRCASECMP strcasecmp
2896 /*-----------------------------------------------------------------*/
2897 /* inExcludeList - return 1 if the string is in exclude Reg list */
2898 /*-----------------------------------------------------------------*/
2900 regsCmp(void *p1, void *p2)
2902 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2906 inExcludeList (char *s)
2908 const char *p = setFirstItem(options.excludeRegsSet);
2910 if (p == NULL || STRCASECMP(p, "none") == 0)
2914 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2917 /*-----------------------------------------------------------------*/
2918 /* genFunction - generated code for function entry */
2919 /*-----------------------------------------------------------------*/
2921 genFunction (iCode * ic)
2925 bool switchedPSW = FALSE;
2927 D (emitcode (";", "genFunction "););
2930 /* create the function header */
2931 emitcode (";", "-----------------------------------------");
2932 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2933 emitcode (";", "-----------------------------------------");
2935 emitcode ("", "%s:", sym->rname);
2936 ftype = operandType (IC_LEFT (ic));
2938 if (IFFUNC_ISNAKED(ftype))
2940 emitcode(";", "naked function: no prologue.");
2944 if (options.stack_probe)
2945 emitcode ("lcall","__stack_probe");
2947 /* here we need to generate the equates for the
2948 register bank if required */
2949 if (FUNC_REGBANK (ftype) != rbank)
2953 rbank = FUNC_REGBANK (ftype);
2954 for (i = 0; i < ds390_nRegs; i++)
2956 if (regs390[i].print) {
2957 if (strcmp (regs390[i].base, "0") == 0)
2958 emitcode ("", "%s !equ !constbyte",
2960 8 * rbank + regs390[i].offset);
2962 emitcode ("", "%s !equ %s + !constbyte",
2965 8 * rbank + regs390[i].offset);
2970 /* if this is an interrupt service routine then
2971 save acc, b, dpl, dph */
2972 if (IFFUNC_ISISR (sym->type))
2974 if (!inExcludeList ("acc"))
2975 emitcode ("push", "acc");
2976 if (!inExcludeList ("b"))
2977 emitcode ("push", "b");
2978 if (!inExcludeList ("dpl"))
2979 emitcode ("push", "dpl");
2980 if (!inExcludeList ("dph"))
2981 emitcode ("push", "dph");
2982 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2984 emitcode ("push", "dpx");
2985 /* Make sure we're using standard DPTR */
2986 emitcode ("push", "dps");
2987 emitcode ("mov", "dps,#0");
2988 if (options.stack10bit)
2990 /* This ISR could conceivably use DPTR2. Better save it. */
2991 emitcode ("push", "dpl1");
2992 emitcode ("push", "dph1");
2993 emitcode ("push", "dpx1");
2994 emitcode ("push", DP2_RESULT_REG);
2997 /* if this isr has no bank i.e. is going to
2998 run with bank 0 , then we need to save more
3000 if (!FUNC_REGBANK (sym->type))
3004 /* if this function does not call any other
3005 function then we can be economical and
3006 save only those registers that are used */
3007 if (!IFFUNC_HASFCALL(sym->type))
3010 /* if any registers used */
3013 /* save the registers used */
3014 for (i = 0; i < sym->regsUsed->size; i++)
3016 if (bitVectBitValue (sym->regsUsed, i) ||
3017 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3018 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3025 /* this function has a function call cannot
3026 determines register usage so we will have to push the
3028 saveRBank (0, ic, FALSE);
3029 if (options.parms_in_bank1) {
3030 for (i=0; i < 8 ; i++ ) {
3031 emitcode ("push","%s",rb1regs[i]);
3038 /* This ISR uses a non-zero bank.
3040 * We assume that the bank is available for our
3043 * However, if this ISR calls a function which uses some
3044 * other bank, we must save that bank entirely.
3046 unsigned long banksToSave = 0;
3048 if (IFFUNC_HASFCALL(sym->type))
3051 #define MAX_REGISTER_BANKS 4
3056 for (i = ic; i; i = i->next)
3058 if (i->op == ENDFUNCTION)
3060 /* we got to the end OK. */
3068 dtype = operandType (IC_LEFT(i));
3070 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3072 /* Mark this bank for saving. */
3073 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3075 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3079 banksToSave |= (1 << FUNC_REGBANK(dtype));
3082 /* And note that we don't need to do it in
3090 /* This is a mess; we have no idea what
3091 * register bank the called function might
3094 * The only thing I can think of to do is
3095 * throw a warning and hope.
3097 werror(W_FUNCPTR_IN_USING_ISR);
3101 if (banksToSave && options.useXstack)
3103 /* Since we aren't passing it an ic,
3104 * saveRBank will assume r0 is available to abuse.
3106 * So switch to our (trashable) bank now, so
3107 * the caller's R0 isn't trashed.
3109 emitcode ("push", "psw");
3110 emitcode ("mov", "psw,#!constbyte",
3111 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3115 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3117 if (banksToSave & (1 << ix))
3119 saveRBank(ix, NULL, FALSE);
3123 // TODO: this needs a closer look
3124 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3129 /* if callee-save to be used for this function
3130 then save the registers being used in this function */
3131 if (IFFUNC_CALLEESAVES(sym->type))
3135 /* if any registers used */
3138 /* save the registers used */
3139 for (i = 0; i < sym->regsUsed->size; i++)
3141 if (bitVectBitValue (sym->regsUsed, i) ||
3142 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3144 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3152 /* set the register bank to the desired value */
3153 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3156 emitcode ("push", "psw");
3157 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3160 if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3161 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3162 if (options.stack10bit) {
3163 emitcode ("push","_bpx");
3164 emitcode ("push","_bpx+1");
3165 emitcode ("mov","_bpx,%s",spname);
3166 emitcode ("mov","_bpx+1,esp");
3167 adjustEsp("_bpx+1");
3169 if (options.useXstack) {
3170 emitcode ("mov", "r0,%s", spname);
3171 emitcode ("mov", "a,_bp");
3172 emitcode ("movx", "@r0,a");
3173 emitcode ("inc", "%s", spname);
3175 /* set up the stack */
3176 emitcode ("push", "_bp"); /* save the callers stack */
3178 emitcode ("mov", "_bp,%s", spname);
3182 /* adjust the stack for the function */
3185 if (options.stack10bit) {
3186 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3187 assert (sym->recvSize <= 4);
3188 if (sym->stack <= 8) {
3189 while (i--) emitcode ("push","acc");
3192 emitcode ("mov","a,sp");
3193 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3194 emitcode ("mov","sp,a");
3195 emitcode ("mov","a,esp");
3197 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3198 emitcode ("mov","esp,a");
3203 werror (W_STACK_OVERFLOW, sym->name);
3205 if (i > 3 && sym->recvSize < 4) {
3207 emitcode ("mov", "a,sp");
3208 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3209 emitcode ("mov", "sp,a");
3213 emitcode ("inc", "sp");
3220 emitcode ("mov", "a,_spx");
3221 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3222 emitcode ("mov", "_spx,a");
3225 /* if critical function then turn interrupts off */
3226 if (IFFUNC_ISCRITICAL (ftype))
3228 symbol *tlbl = newiTempLabel (NULL);
3229 emitcode ("setb", "c");
3230 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3231 emitcode ("clr", "c");
3232 emitcode ("", "%05d$:", (tlbl->key + 100));
3233 emitcode ("push", "psw"); /* save old ea via c in psw */
3238 /*-----------------------------------------------------------------*/
3239 /* genEndFunction - generates epilogue for functions */
3240 /*-----------------------------------------------------------------*/
3242 genEndFunction (iCode * ic)
3244 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3246 D (emitcode (";", "genEndFunction "););
3248 if (IFFUNC_ISNAKED(sym->type))
3250 emitcode(";", "naked function: no epilogue.");
3254 if (IFFUNC_ISCRITICAL (sym->type))
3256 emitcode ("pop", "psw"); /* restore ea via c in psw */
3257 emitcode ("mov", "ea,c");
3260 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3261 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3263 if (options.stack10bit) {
3265 emitcode ("mov", "sp,_bpx", spname);
3266 emitcode ("mov", "esp,_bpx+1", spname);
3269 emitcode ("mov", "%s,_bp", spname);
3273 /* if use external stack but some variables were
3274 added to the local stack then decrement the
3276 if (options.useXstack && sym->stack) {
3277 emitcode ("mov", "a,sp");
3278 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3279 emitcode ("mov", "sp,a");
3283 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3284 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3286 if (options.useXstack) {
3287 emitcode ("mov", "r0,%s", spname);
3288 emitcode ("movx", "a,@r0");
3289 emitcode ("mov", "_bp,a");
3290 emitcode ("dec", "%s", spname);
3292 if (options.stack10bit) {
3293 emitcode ("pop", "_bpx+1");
3294 emitcode ("pop", "_bpx");
3296 emitcode ("pop", "_bp");
3301 /* restore the register bank */
3302 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3304 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3305 || !options.useXstack)
3307 /* Special case of ISR using non-zero bank with useXstack
3310 emitcode ("pop", "psw");
3314 if (IFFUNC_ISISR (sym->type))
3317 /* now we need to restore the registers */
3318 /* if this isr has no bank i.e. is going to
3319 run with bank 0 , then we need to save more
3321 if (!FUNC_REGBANK (sym->type))
3324 /* if this function does not call any other
3325 function then we can be economical and
3326 save only those registers that are used */
3327 if (!IFFUNC_HASFCALL(sym->type))
3330 /* if any registers used */
3333 /* save the registers used */
3334 for (i = sym->regsUsed->size; i >= 0; i--)
3336 if (bitVectBitValue (sym->regsUsed, i) ||
3337 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3338 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3345 /* this function has a function call cannot
3346 determines register usage so we will have to pop the
3348 if (options.parms_in_bank1) {
3349 for (i = 7 ; i >= 0 ; i-- ) {
3350 emitcode ("pop","%s",rb1regs[i]);
3353 unsaveRBank (0, ic, FALSE);
3358 /* This ISR uses a non-zero bank.
3360 * Restore any register banks saved by genFunction
3363 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3366 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3368 if (savedBanks & (1 << ix))
3370 unsaveRBank(ix, NULL, FALSE);
3374 if (options.useXstack)
3376 /* Restore bank AFTER calling unsaveRBank,
3377 * since it can trash r0.
3379 emitcode ("pop", "psw");
3383 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3385 if (options.stack10bit)
3387 emitcode ("pop", DP2_RESULT_REG);
3388 emitcode ("pop", "dpx1");
3389 emitcode ("pop", "dph1");
3390 emitcode ("pop", "dpl1");
3392 emitcode ("pop", "dps");
3393 emitcode ("pop", "dpx");
3395 if (!inExcludeList ("dph"))
3396 emitcode ("pop", "dph");
3397 if (!inExcludeList ("dpl"))
3398 emitcode ("pop", "dpl");
3399 if (!inExcludeList ("b"))
3400 emitcode ("pop", "b");
3401 if (!inExcludeList ("acc"))
3402 emitcode ("pop", "acc");
3404 /* if debug then send end of function */
3405 if (options.debug && currFunc) {
3407 emitcode ("", "C$%s$%d$%d$%d ==.",
3408 FileBaseName (ic->filename), currFunc->lastLine,
3409 ic->level, ic->block);
3410 if (IS_STATIC (currFunc->etype))
3411 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3413 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3417 emitcode ("reti", "");
3421 if (IFFUNC_CALLEESAVES(sym->type))
3425 /* if any registers used */
3428 /* save the registers used */
3429 for (i = sym->regsUsed->size; i >= 0; i--)
3431 if (bitVectBitValue (sym->regsUsed, i) ||
3432 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3433 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3439 /* if debug then send end of function */
3440 if (options.debug && currFunc)
3443 emitcode ("", "C$%s$%d$%d$%d ==.",
3444 FileBaseName (ic->filename), currFunc->lastLine,
3445 ic->level, ic->block);
3446 if (IS_STATIC (currFunc->etype))
3447 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3449 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3453 emitcode ("ret", "");
3458 /*-----------------------------------------------------------------*/
3459 /* genJavaNativeRet - generate code for return JavaNative */
3460 /*-----------------------------------------------------------------*/
3461 static void genJavaNativeRet(iCode *ic)
3465 aopOp (IC_LEFT (ic), ic, FALSE,
3466 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3467 size = AOP_SIZE (IC_LEFT (ic));
3471 /* it is assigned to GPR0-R3 then push them */
3472 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3473 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3474 for (i = 0 ; i < size ; i++ ) {
3475 emitcode ("push","%s",
3476 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3478 for (i = (size-1) ; i >= 0 ; i--) {
3479 emitcode ("pop","a%s",javaRet[i]);
3482 for (i = 0 ; i < size ; i++)
3483 emitcode ("mov","%s,%s",javaRet[i],
3484 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3486 for (i = size ; i < 4 ; i++ )
3487 emitcode ("mov","%s,#0",javaRet[i]);
3491 /*-----------------------------------------------------------------*/
3492 /* genRet - generate code for return statement */
3493 /*-----------------------------------------------------------------*/
3497 int size, offset = 0, pushed = 0;
3499 D (emitcode (";", "genRet "););
3501 /* if we have no return value then
3502 just generate the "ret" */
3506 /* if this is a JavaNative function then return
3507 value in different register */
3508 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3509 genJavaNativeRet(ic);
3512 /* we have something to return then
3513 move the return value into place */
3514 aopOp (IC_LEFT (ic), ic, FALSE,
3515 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3516 size = AOP_SIZE (IC_LEFT (ic));
3518 _startLazyDPSEvaluation ();
3522 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3524 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3526 emitcode ("push", "%s", l);
3531 /* Since A is the last element of fReturn,
3532 * is is OK to clobber it in the aopGet.
3534 l = aopGet (AOP (IC_LEFT (ic)), offset,
3535 FALSE, FALSE, NULL);
3536 if (strcmp (fReturn[offset], l))
3537 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3540 _endLazyDPSEvaluation ();
3547 if (strcmp (fReturn[pushed], "a"))
3548 emitcode ("pop", fReturn[pushed]);
3550 emitcode ("pop", "acc");
3553 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3556 /* generate a jump to the return label
3557 if the next is not the return statement */
3558 if (!(ic->next && ic->next->op == LABEL &&
3559 IC_LABEL (ic->next) == returnLabel))
3561 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3565 /*-----------------------------------------------------------------*/
3566 /* genLabel - generates a label */
3567 /*-----------------------------------------------------------------*/
3569 genLabel (iCode * ic)
3571 /* special case never generate */
3572 if (IC_LABEL (ic) == entryLabel)
3575 D (emitcode (";", "genLabel ");
3578 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3581 /*-----------------------------------------------------------------*/
3582 /* genGoto - generates a ljmp */
3583 /*-----------------------------------------------------------------*/
3585 genGoto (iCode * ic)
3587 D (emitcode (";", "genGoto ");
3589 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3592 /*-----------------------------------------------------------------*/
3593 /* findLabelBackwards: walks back through the iCode chain looking */
3594 /* for the given label. Returns number of iCode instructions */
3595 /* between that label and given ic. */
3596 /* Returns zero if label not found. */
3597 /*-----------------------------------------------------------------*/
3599 findLabelBackwards (iCode * ic, int key)
3608 /* If we have any pushes or pops, we cannot predict the distance.
3609 I don't like this at all, this should be dealt with in the
3611 if (ic->op == IPUSH || ic->op == IPOP) {
3615 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3617 /* printf("findLabelBackwards = %d\n", count); */
3625 /*-----------------------------------------------------------------*/
3626 /* genPlusIncr :- does addition with increment if possible */
3627 /*-----------------------------------------------------------------*/
3629 genPlusIncr (iCode * ic)
3631 unsigned int icount;
3632 unsigned int size = getDataSize (IC_RESULT (ic));
3634 /* will try to generate an increment */
3635 /* if the right side is not a literal
3637 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3640 /* if the literal value of the right hand side
3641 is greater than 4 then it is not worth it */
3642 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3645 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3646 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3648 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3652 /* if increment 16 bits in register */
3654 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3655 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3656 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3665 /* If the next instruction is a goto and the goto target
3666 * is <= 5 instructions previous to this, we can generate
3667 * jumps straight to that target.
3669 if (ic->next && ic->next->op == GOTO
3670 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3673 D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3674 tlbl = IC_LABEL (ic->next);
3679 tlbl = newiTempLabel (NULL);
3683 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3684 emitcode ("inc", "%s", l);
3686 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3687 IS_AOP_PREG (IC_RESULT (ic)))
3689 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3693 emitcode ("clr", "a");
3694 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3697 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
3698 emitcode ("inc", "%s", l);
3701 if (!strcmp(l, "acc"))
3703 emitcode("jnz", "!tlabel", tlbl->key + 100);
3705 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3706 IS_AOP_PREG (IC_RESULT (ic)))
3708 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3712 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3715 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3716 emitcode ("inc", "%s", l);
3720 if (!strcmp(l, "acc"))
3722 emitcode("jnz", "!tlabel", tlbl->key + 100);
3724 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3725 IS_AOP_PREG (IC_RESULT (ic)))
3727 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3731 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3734 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3735 emitcode ("inc", "%s", l); }
3739 emitcode ("", "!tlabeldef", tlbl->key + 100);
3744 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3745 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
3746 options.model == MODEL_FLAT24 ) {
3750 emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3752 emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3754 emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3757 while (icount--) emitcode ("inc","dptr");
3761 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3762 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3764 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3765 while (icount--) emitcode ("inc","dptr");
3766 emitcode ("mov","dps,#0");
3770 /* if the sizes are greater than 1 then we cannot */
3771 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3772 AOP_SIZE (IC_LEFT (ic)) > 1)
3775 /* we can if the aops of the left & result match or
3776 if they are in registers and the registers are the
3779 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3780 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3781 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3786 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3787 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3788 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3793 _startLazyDPSEvaluation ();
3796 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3798 _endLazyDPSEvaluation ();
3807 /*-----------------------------------------------------------------*/
3808 /* outBitAcc - output a bit in acc */
3809 /*-----------------------------------------------------------------*/
3811 outBitAcc (operand * result)
3813 symbol *tlbl = newiTempLabel (NULL);
3814 /* if the result is a bit */
3815 if (AOP_TYPE (result) == AOP_CRY)
3817 aopPut (AOP (result), "a", 0);
3821 emitcode ("jz", "!tlabel", tlbl->key + 100);
3822 emitcode ("mov", "a,%s", one);
3823 emitcode ("", "!tlabeldef", tlbl->key + 100);
3828 /*-----------------------------------------------------------------*/
3829 /* genPlusBits - generates code for addition of two bits */
3830 /*-----------------------------------------------------------------*/
3832 genPlusBits (iCode * ic)
3834 D (emitcode (";", "genPlusBits "););
3836 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3838 symbol *lbl = newiTempLabel (NULL);
3839 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3840 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3841 emitcode ("cpl", "c");
3842 emitcode ("", "!tlabeldef", (lbl->key + 100));
3843 outBitC (IC_RESULT (ic));
3847 emitcode ("clr", "a");
3848 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3849 emitcode ("rlc", "a");
3850 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3851 emitcode ("addc", "a,#0");
3852 outAcc (IC_RESULT (ic));
3857 adjustArithmeticResult (iCode * ic)
3859 if (opIsGptr (IC_RESULT (ic)) &&
3860 opIsGptr (IC_LEFT (ic)) &&
3861 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3863 aopPut (AOP (IC_RESULT (ic)),
3864 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3868 if (opIsGptr (IC_RESULT (ic)) &&
3869 opIsGptr (IC_RIGHT (ic)) &&
3870 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3872 aopPut (AOP (IC_RESULT (ic)),
3873 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3877 if (opIsGptr (IC_RESULT (ic)) &&
3878 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3879 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3880 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3881 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3884 SNPRINTF (buff, sizeof(buff),
3885 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3886 aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3890 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3891 // generates the result if possible. If result is generated, returns TRUE; otherwise
3892 // returns false and caller must deal with fact that result isn't aopOp'd.
3893 bool aopOp3(iCode * ic)
3895 bool dp1InUse, dp2InUse;
3898 // First, generate the right opcode. DPTR may be used if neither left nor result are
3901 // D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3902 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3903 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3904 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3906 // D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3907 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3908 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3909 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3912 // Right uses DPTR unless left or result is an AOP_STR; however,
3913 // if right is an AOP_STR, it must use DPTR regardless.
3914 if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
3915 && !AOP_IS_STR(IC_RIGHT(ic)))
3924 aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
3926 // if the right used DPTR, left MUST use DPTR2.
3927 // if the right used DPTR2, left MUST use DPTR.
3928 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3929 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3930 // enabling us to assign DPTR to result.
3932 if (AOP_USESDPTR(IC_RIGHT(ic)))
3936 else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3942 if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3952 aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3955 // We've op'd the left & right. So, if left or right are the same operand as result,
3956 // we know aopOp will succeed, and we can just do it & bail.
3957 if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))
3959 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
3962 if (isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3964 // D(emitcode(";", "aopOp3: (left | right) & result equal"););
3965 aopOp(IC_RESULT(ic),ic,TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
3969 // Operands may be equivalent (but not equal) if they share a spill location. If
3970 // so, use the same DPTR or DPTR2.
3971 if (operandsEqu (IC_LEFT(ic), IC_RESULT(ic)))
3973 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
3976 if (operandsEqu (IC_RIGHT(ic), IC_RESULT(ic)))
3978 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
3982 // Note which dptrs are currently in use.
3983 dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3984 dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3986 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
3988 if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3993 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3994 if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3999 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
4000 if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
4005 aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
4007 // Some sanity checking...
4008 if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
4011 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
4012 __FILE__, __LINE__, ic->filename, ic->lineno);
4013 emitcode(";", ">>> unexpected DPTR here.");
4016 if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
4019 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
4020 __FILE__, __LINE__, ic->filename, ic->lineno);
4021 emitcode(";", ">>> unexpected DPTR2 here.");
4027 // Macro to aopOp all three operands of an ic. If this cannot be done,
4028 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
4029 // will be set TRUE. The caller must then handle the case specially, noting
4030 // that the IC_RESULT operand is not aopOp'd.
4032 #define AOP_OP_3_NOFATAL(ic, rc) \
4033 do { rc = !aopOp3(ic); } while (0)
4035 // aopOp the left & right operands of an ic.
4036 #define AOP_OP_2(ic) \
4037 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
4038 aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
4040 // convienience macro.
4041 #define AOP_SET_LOCALS(ic) \
4042 left = IC_LEFT(ic); \
4043 right = IC_RIGHT(ic); \
4044 result = IC_RESULT(ic);
4047 // Given an integer value of pushedSize bytes on the stack,
4048 // adjust it to be resultSize bytes, either by discarding
4049 // the most significant bytes or by zero-padding.
4051 // On exit from this macro, pushedSize will have been adjusted to
4052 // equal resultSize, and ACC may be trashed.
4053 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
4054 /* If the pushed data is bigger than the result, \
4055 * simply discard unused bytes. Icky, but works. \
4057 while (pushedSize > resultSize) \
4059 D (emitcode (";", "discarding unused result byte."););\
4060 emitcode ("pop", "acc"); \
4063 if (pushedSize < resultSize) \
4065 emitcode ("clr", "a"); \
4066 /* Conversly, we haven't pushed enough here. \
4067 * just zero-pad, and all is well. \
4069 while (pushedSize < resultSize) \
4071 emitcode("push", "acc"); \
4075 assert(pushedSize == resultSize);
4077 /*-----------------------------------------------------------------*/
4078 /* genPlus - generates code for addition */
4079 /*-----------------------------------------------------------------*/
4081 genPlus (iCode * ic)
4083 int size, offset = 0;
4087 D (emitcode (";", "genPlus "););
4089 /* special cases :- */
4090 if ( AOP_IS_STR(IC_LEFT(ic)) &&
4091 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4092 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4093 size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4095 while (size--) emitcode ("inc","dptr");
4097 emitcode ("mov","a,dpl");
4098 emitcode ("add","a,#!constbyte",size & 0xff);
4099 emitcode ("mov","dpl,a");
4100 emitcode ("mov","a,dph");
4101 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4102 emitcode ("mov","dph,a");
4103 emitcode ("mov","a,dpx");
4104 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4105 emitcode ("mov","dpx,a");
4107 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4110 if ( IS_SYMOP(IC_LEFT(ic)) &&
4111 OP_SYMBOL(IC_LEFT(ic))->remat &&
4112 isOperandInFarSpace(IC_RIGHT(ic))) {
4113 operand *op = IC_RIGHT(ic);
4114 IC_RIGHT(ic) = IC_LEFT(ic);
4118 AOP_OP_3_NOFATAL (ic, pushResult);
4122 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4127 /* if literal, literal on the right or
4128 if left requires ACC or right is already
4130 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4131 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4132 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4134 operand *t = IC_RIGHT (ic);
4135 IC_RIGHT (ic) = IC_LEFT (ic);
4137 emitcode (";", "Swapped plus args.");
4140 /* if both left & right are in bit
4142 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4143 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4149 /* if left in bit space & right literal */
4150 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4151 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4153 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4154 /* if result in bit space */
4155 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4157 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4158 emitcode ("cpl", "c");
4159 outBitC (IC_RESULT (ic));
4163 size = getDataSize (IC_RESULT (ic));
4164 _startLazyDPSEvaluation ();
4167 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4168 emitcode ("addc", "a,#0");
4169 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4171 _endLazyDPSEvaluation ();
4176 /* if I can do an increment instead
4177 of add then GOOD for ME */
4178 if (genPlusIncr (ic) == TRUE)
4180 emitcode (";", "did genPlusIncr");
4185 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4187 _startLazyDPSEvaluation ();
4190 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4192 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4194 emitcode ("add", "a,%s",
4195 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4197 emitcode ("addc", "a,%s",
4198 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4202 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4204 /* right is going to use ACC or we would have taken the
4207 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4209 D(emitcode(";", "+ AOP_ACC special case."););
4210 emitcode("xch", "a, %s", DP2_RESULT_REG);
4212 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4215 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4218 emitcode("add", "a, %s", DP2_RESULT_REG);
4222 emitcode ("add", "a,%s",
4223 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4229 emitcode ("addc", "a,%s",
4230 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4236 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4240 emitcode ("push", "acc");
4244 _endLazyDPSEvaluation ();
4248 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4250 size = getDataSize (IC_LEFT (ic));
4251 rSize = getDataSize (IC_RESULT (ic));
4253 ADJUST_PUSHED_RESULT(size, rSize);
4255 _startLazyDPSEvaluation ();
4258 emitcode ("pop", "acc");
4259 aopPut (AOP (IC_RESULT (ic)), "a", size);
4261 _endLazyDPSEvaluation ();
4264 adjustArithmeticResult (ic);
4267 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4268 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4269 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4272 /*-----------------------------------------------------------------*/
4273 /* genMinusDec :- does subtraction with deccrement if possible */
4274 /*-----------------------------------------------------------------*/
4276 genMinusDec (iCode * ic)
4278 unsigned int icount;
4279 unsigned int size = getDataSize (IC_RESULT (ic));
4281 /* will try to generate an increment */
4282 /* if the right side is not a literal
4284 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4287 /* if the literal value of the right hand side
4288 is greater than 4 then it is not worth it */
4289 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4292 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4293 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4295 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4299 /* if decrement 16 bits in register */
4300 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4301 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4302 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4311 /* If the next instruction is a goto and the goto target
4312 * is <= 5 instructions previous to this, we can generate
4313 * jumps straight to that target.
4315 if (ic->next && ic->next->op == GOTO
4316 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4319 emitcode (";", "tail decrement optimized (range %d)", labelRange);
4320 tlbl = IC_LABEL (ic->next);
4325 tlbl = newiTempLabel (NULL);
4329 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4330 emitcode ("dec", "%s", l);
4332 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4333 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4334 IS_AOP_PREG (IC_RESULT (ic)))
4336 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4340 emitcode ("mov", "a,#!constbyte",0xff);
4341 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4343 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4344 emitcode ("dec", "%s", l);
4347 if (!strcmp(l, "acc"))
4349 emitcode("jnz", "!tlabel", tlbl->key + 100);
4351 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4352 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4353 IS_AOP_PREG (IC_RESULT (ic)))
4355 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4359 emitcode ("mov", "a,#!constbyte",0xff);
4360 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4362 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4363 emitcode ("dec", "%s", l);
4367 if (!strcmp(l, "acc"))
4369 emitcode("jnz", "!tlabel", tlbl->key + 100);
4371 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4372 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4373 IS_AOP_PREG (IC_RESULT (ic)))
4375 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4379 emitcode ("mov", "a,#!constbyte",0xff);
4380 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4382 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4383 emitcode ("dec", "%s", l);
4387 emitcode ("", "!tlabeldef", tlbl->key + 100);
4392 /* if the sizes are greater than 1 then we cannot */
4393 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4394 AOP_SIZE (IC_LEFT (ic)) > 1)
4397 /* we can if the aops of the left & result match or
4398 if they are in registers and the registers are the
4401 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4402 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4403 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4406 _startLazyDPSEvaluation ();
4409 emitcode ("dec", "%s",
4410 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4412 _endLazyDPSEvaluation ();
4420 /*-----------------------------------------------------------------*/
4421 /* addSign - complete with sign */
4422 /*-----------------------------------------------------------------*/
4424 addSign (operand * result, int offset, int sign)
4426 int size = (getDataSize (result) - offset);
4429 _startLazyDPSEvaluation();
4432 emitcode ("rlc", "a");
4433 emitcode ("subb", "a,acc");
4436 aopPut (AOP (result), "a", offset++);
4443 aopPut (AOP (result), zero, offset++);
4446 _endLazyDPSEvaluation();
4450 /*-----------------------------------------------------------------*/
4451 /* genMinusBits - generates code for subtraction of two bits */
4452 /*-----------------------------------------------------------------*/
4454 genMinusBits (iCode * ic)
4456 symbol *lbl = newiTempLabel (NULL);
4458 D (emitcode (";", "genMinusBits "););
4460 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4462 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4463 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4464 emitcode ("cpl", "c");
4465 emitcode ("", "!tlabeldef", (lbl->key + 100));
4466 outBitC (IC_RESULT (ic));
4470 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4471 emitcode ("subb", "a,acc");
4472 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4473 emitcode ("inc", "a");
4474 emitcode ("", "!tlabeldef", (lbl->key + 100));
4475 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4476 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4480 /*-----------------------------------------------------------------*/
4481 /* genMinus - generates code for subtraction */
4482 /*-----------------------------------------------------------------*/
4484 genMinus (iCode * ic)
4486 int size, offset = 0;
4491 D (emitcode (";", "genMinus "););
4493 AOP_OP_3_NOFATAL(ic, pushResult);
4497 /* special cases :- */
4498 /* if both left & right are in bit space */
4499 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4500 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4506 /* if I can do an decrement instead
4507 of subtract then GOOD for ME */
4508 if (genMinusDec (ic) == TRUE)
4513 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4515 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4521 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4526 /* if literal, add a,#-lit, else normal subb */
4527 _startLazyDPSEvaluation ();
4529 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4530 if (AOP_USESDPTR(IC_RIGHT(ic))) {
4531 emitcode ("mov","b,%s",
4532 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4533 MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4534 emitcode ("subb","a,b");
4536 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4537 emitcode ("subb", "a,%s",
4538 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE,
4542 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4543 /* first add without previous c */
4545 if (!size && lit==-1) {
4546 emitcode ("dec", "a");
4548 emitcode ("add", "a,#!constbyte",
4549 (unsigned int) (lit & 0x0FFL));
4552 emitcode ("addc", "a,#!constbyte",
4553 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4558 emitcode ("push", "acc");
4560 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4564 _endLazyDPSEvaluation ();
4568 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4570 size = getDataSize (IC_LEFT (ic));
4571 rSize = getDataSize (IC_RESULT (ic));
4573 ADJUST_PUSHED_RESULT(size, rSize);
4575 _startLazyDPSEvaluation ();
4578 emitcode ("pop", "acc");
4579 aopPut (AOP (IC_RESULT (ic)), "a", size);
4581 _endLazyDPSEvaluation ();
4584 adjustArithmeticResult (ic);
4587 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4588 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4589 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4593 /*-----------------------------------------------------------------*/
4594 /* genMultbits :- multiplication of bits */
4595 /*-----------------------------------------------------------------*/
4597 genMultbits (operand * left,
4602 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4603 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4604 aopOp(result, ic, TRUE, FALSE);
4609 /*-----------------------------------------------------------------*/
4610 /* genMultOneByte : 8*8=8/16 bit multiplication */
4611 /*-----------------------------------------------------------------*/
4613 genMultOneByte (operand * left,
4618 sym_link *opetype = operandType (result);
4622 /* (if two literals: the value is computed before) */
4623 /* if one literal, literal on the right */
4624 if (AOP_TYPE (left) == AOP_LIT)
4629 emitcode (";", "swapped left and right");
4632 if (SPEC_USIGN(opetype)
4633 // ignore the sign of left and right, what else can we do?
4634 || (SPEC_USIGN(operandType(left)) &&
4635 SPEC_USIGN(operandType(right)))) {
4636 // just an unsigned 8*8=8/16 multiply
4637 //emitcode (";","unsigned");
4638 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4639 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4640 emitcode ("mul", "ab");
4642 _G.accInUse++; _G.bInUse++;
4643 aopOp(result, ic, TRUE, FALSE);
4645 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4647 // this should never happen
4648 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4649 AOP_SIZE(result), __FILE__, lineno);
4653 aopPut (AOP (result), "a", 0);
4654 _G.accInUse--; _G.bInUse--;
4655 if (AOP_SIZE(result)==2)
4657 aopPut (AOP (result), "b", 1);
4662 // we have to do a signed multiply
4664 emitcode (";", "signed");
4665 emitcode ("clr", "F0"); // reset sign flag
4666 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4668 lbl=newiTempLabel(NULL);
4669 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4670 // left side is negative, 8-bit two's complement, this fails for -128
4671 emitcode ("setb", "F0"); // set sign flag
4672 emitcode ("cpl", "a");
4673 emitcode ("inc", "a");
4675 emitcode ("", "!tlabeldef", lbl->key+100);
4678 if (AOP_TYPE(right)==AOP_LIT) {
4679 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
4680 /* AND literal negative */
4681 if ((int) val < 0) {
4682 emitcode ("cpl", "F0"); // complement sign flag
4683 emitcode ("mov", "b,#!constbyte", -val);
4685 emitcode ("mov", "b,#!constbyte", val);
4688 lbl=newiTempLabel(NULL);
4689 emitcode ("mov", "b,a");
4690 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4691 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4692 // right side is negative, 8-bit two's complement
4693 emitcode ("cpl", "F0"); // complement sign flag
4694 emitcode ("cpl", "a");
4695 emitcode ("inc", "a");
4696 emitcode ("", "!tlabeldef", lbl->key+100);
4698 emitcode ("mul", "ab");
4700 _G.accInUse++;_G.bInUse++;
4701 aopOp(result, ic, TRUE, FALSE);
4703 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4705 // this should never happen
4706 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4707 AOP_SIZE(result), __FILE__, lineno);
4711 lbl=newiTempLabel(NULL);
4712 emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4713 // only ONE op was negative, we have to do a 8/16-bit two's complement
4714 emitcode ("cpl", "a"); // lsb
4715 if (AOP_SIZE(result)==1) {
4716 emitcode ("inc", "a");
4718 emitcode ("add", "a,#1");
4719 emitcode ("xch", "a,b");
4720 emitcode ("cpl", "a"); // msb
4721 emitcode ("addc", "a,#0");
4722 emitcode ("xch", "a,b");
4725 emitcode ("", "!tlabeldef", lbl->key+100);
4726 aopPut (AOP (result), "a", 0);
4727 _G.accInUse--;_G.bInUse--;
4728 if (AOP_SIZE(result)==2) {
4729 aopPut (AOP (result), "b", 1);
4733 /*-----------------------------------------------------------------*/
4734 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4735 /*-----------------------------------------------------------------*/
4736 static void genMultTwoByte (operand *left, operand *right,
4737 operand *result, iCode *ic)
4739 sym_link *retype = getSpec(operandType(right));
4740 sym_link *letype = getSpec(operandType(left));
4741 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4744 if (AOP_TYPE (left) == AOP_LIT) {
4749 /* save EA bit in F1 */
4750 lbl = newiTempLabel(NULL);
4751 emitcode ("setb","F1");
4752 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4753 emitcode ("clr","F1");
4754 emitcode("","!tlabeldef",lbl->key+100);
4756 /* load up MB with right */
4758 emitcode("clr","F0");
4759 if (AOP_TYPE(right) == AOP_LIT) {
4760 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4762 emitcode("setb","F0");
4765 emitcode ("mov","mb,#!constbyte",val & 0xff);
4766 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4768 lbl = newiTempLabel(NULL);
4769 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4770 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4771 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4772 emitcode ("xch", "a,b");
4773 emitcode ("cpl","a");
4774 emitcode ("add", "a,#1");
4775 emitcode ("xch", "a,b");
4776 emitcode ("cpl", "a"); // msb
4777 emitcode ("addc", "a,#0");
4778 emitcode ("setb","F0");
4779 emitcode ("","!tlabeldef",lbl->key+100);
4780 emitcode ("mov","mb,b");
4781 emitcode ("mov","mb,a");
4784 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4785 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4787 /* load up MA with left */
4789 lbl = newiTempLabel(NULL);
4790 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4791 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4792 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4793 emitcode ("xch", "a,b");
4794 emitcode ("cpl","a");
4795 emitcode ("add", "a,#1");
4796 emitcode ("xch", "a,b");
4797 emitcode ("cpl", "a"); // msb
4798 emitcode ("addc","a,#0");
4799 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4800 emitcode ("setb","F0");
4801 emitcode ("","!tlabeldef",lbl->key+100);
4802 emitcode ("mov","ma,b");
4803 emitcode ("mov","ma,a");
4805 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4806 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4808 /* wait for multiplication to finish */
4809 lbl = newiTempLabel(NULL);
4810 emitcode("","!tlabeldef", lbl->key+100);
4811 emitcode("mov","a,mcnt1");
4812 emitcode("anl","a,#!constbyte",0x80);
4813 emitcode("jnz","!tlabel",lbl->key+100);
4815 freeAsmop (left, NULL, ic, TRUE);
4816 freeAsmop (right, NULL, ic,TRUE);
4817 aopOp(result, ic, TRUE, FALSE);
4819 /* if unsigned then simple */
4821 emitcode ("mov","a,ma");
4822 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4823 emitcode ("mov","a,ma");
4824 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4825 aopPut(AOP(result),"ma",1);
4826 aopPut(AOP(result),"ma",0);
4828 emitcode("push","ma");
4829 emitcode("push","ma");
4830 emitcode("push","ma");
4832 /* negate result if needed */
4833 lbl = newiTempLabel(NULL);
4834 emitcode("jnb","F0,!tlabel",lbl->key+100);
4835 emitcode("cpl","a");
4836 emitcode("add","a,#1");
4837 emitcode("","!tlabeldef", lbl->key+100);
4838 if (AOP_TYPE(result) == AOP_ACC)
4840 D(emitcode(";", "ACC special case."););
4841 /* We know result is the only live aop, and
4842 * it's obviously not a DPTR2, so AP is available.
4844 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4848 aopPut(AOP(result),"a",0);
4851 emitcode("pop","acc");
4852 lbl = newiTempLabel(NULL);
4853 emitcode("jnb","F0,!tlabel",lbl->key+100);
4854 emitcode("cpl","a");
4855 emitcode("addc","a,#0");
4856 emitcode("","!tlabeldef", lbl->key+100);
4857 aopPut(AOP(result),"a",1);
4858 emitcode("pop","acc");
4859 if (AOP_SIZE(result) >= 3) {
4860 lbl = newiTempLabel(NULL);
4861 emitcode("jnb","F0,!tlabel",lbl->key+100);
4862 emitcode("cpl","a");
4863 emitcode("addc","a,#0");
4864 emitcode("","!tlabeldef", lbl->key+100);
4865 aopPut(AOP(result),"a",2);
4867 emitcode("pop","acc");
4868 if (AOP_SIZE(result) >= 4) {
4869 lbl = newiTempLabel(NULL);
4870 emitcode("jnb","F0,!tlabel",lbl->key+100);
4871 emitcode("cpl","a");
4872 emitcode("addc","a,#0");
4873 emitcode("","!tlabeldef", lbl->key+100);
4874 aopPut(AOP(result),"a",3);
4876 if (AOP_TYPE(result) == AOP_ACC)
4878 /* We stashed the result away above. */
4879 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4883 freeAsmop (result, NULL, ic, TRUE);
4885 /* restore EA bit in F1 */
4886 lbl = newiTempLabel(NULL);
4887 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4888 emitcode ("setb","EA");
4889 emitcode("","!tlabeldef",lbl->key+100);
4893 /*-----------------------------------------------------------------*/
4894 /* genMult - generates code for multiplication */
4895 /*-----------------------------------------------------------------*/
4897 genMult (iCode * ic)
4899 operand *left = IC_LEFT (ic);
4900 operand *right = IC_RIGHT (ic);
4901 operand *result = IC_RESULT (ic);
4903 D (emitcode (";", "genMult "););
4905 /* assign the amsops */
4908 /* special cases first */
4910 if (AOP_TYPE (left) == AOP_CRY &&
4911 AOP_TYPE (right) == AOP_CRY)
4913 genMultbits (left, right, result, ic);
4917 /* if both are of size == 1 */
4918 if (AOP_SIZE (left) == 1 &&
4919 AOP_SIZE (right) == 1)
4921 genMultOneByte (left, right, result, ic);
4925 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4926 /* use the ds390 ARITHMETIC accel UNIT */
4927 genMultTwoByte (left, right, result, ic);
4930 /* should have been converted to function call */
4934 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4935 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4936 freeAsmop (result, NULL, ic, TRUE);
4939 /*-----------------------------------------------------------------*/
4940 /* genDivbits :- division of bits */
4941 /*-----------------------------------------------------------------*/
4943 genDivbits (operand * left,
4951 /* the result must be bit */
4952 LOAD_AB_FOR_DIV (left, right, l);
4953 emitcode ("div", "ab");
4954 emitcode ("rrc", "a");
4955 aopOp(result, ic, TRUE, FALSE);
4957 aopPut (AOP (result), "c", 0);
4960 /*-----------------------------------------------------------------*/
4961 /* genDivOneByte : 8 bit division */
4962 /*-----------------------------------------------------------------*/
4964 genDivOneByte (operand * left,
4969 sym_link *opetype = operandType (result);
4975 /* signed or unsigned */
4976 if (SPEC_USIGN (opetype))
4978 /* unsigned is easy */
4979 LOAD_AB_FOR_DIV (left, right, l);
4980 emitcode ("div", "ab");
4983 aopOp(result, ic, TRUE, FALSE);
4984 aopPut (AOP (result), "a", 0);
4987 size = AOP_SIZE (result) - 1;
4991 aopPut (AOP (result), zero, offset++);
4996 /* signed is a little bit more difficult */
4998 /* save the signs of the operands */
4999 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5000 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
5001 emitcode ("push", "acc"); /* save it on the stack */
5003 /* now sign adjust for both left & right */
5004 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5005 lbl = newiTempLabel (NULL);
5006 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5007 emitcode ("cpl", "a");
5008 emitcode ("inc", "a");
5009 emitcode ("", "!tlabeldef", (lbl->key + 100));
5010 emitcode ("mov", "b,a");
5012 /* sign adjust left side */
5013 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5015 lbl = newiTempLabel (NULL);
5016 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5017 emitcode ("cpl", "a");
5018 emitcode ("inc", "a");
5019 emitcode ("", "!tlabeldef", (lbl->key + 100));
5021 /* now the division */
5022 emitcode ("nop", "; workaround for DS80C390 div bug.");
5023 emitcode ("div", "ab");
5024 /* we are interested in the lower order
5026 emitcode ("mov", "b,a");
5027 lbl = newiTempLabel (NULL);
5028 emitcode ("pop", "acc");
5029 /* if there was an over flow we don't
5030 adjust the sign of the result */
5031 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5032 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5034 emitcode ("clr", "a");
5035 emitcode ("subb", "a,b");
5036 emitcode ("mov", "b,a");
5037 emitcode ("", "!tlabeldef", (lbl->key + 100));
5039 /* now we are done */
5040 _G.accInUse++; _G.bInUse++;
5041 aopOp(result, ic, TRUE, FALSE);
5043 aopPut (AOP (result), "b", 0);
5045 size = AOP_SIZE (result) - 1;
5049 emitcode ("mov", "c,b.7");
5050 emitcode ("subb", "a,acc");
5054 aopPut (AOP (result), "a", offset++);
5056 _G.accInUse--; _G.bInUse--;
5060 /*-----------------------------------------------------------------*/
5061 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
5062 /*-----------------------------------------------------------------*/
5063 static void genDivTwoByte (operand *left, operand *right,
5064 operand *result, iCode *ic)
5066 sym_link *retype = getSpec(operandType(right));
5067 sym_link *letype = getSpec(operandType(left));
5068 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5071 /* save EA bit in F1 */
5072 lbl = newiTempLabel(NULL);
5073 emitcode ("setb","F1");
5074 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5075 emitcode ("clr","F1");
5076 emitcode("","!tlabeldef",lbl->key+100);
5078 /* load up MA with left */
5080 emitcode("clr","F0");
5081 lbl = newiTempLabel(NULL);
5082 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5083 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5084 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5085 emitcode ("xch", "a,b");
5086 emitcode ("cpl","a");
5087 emitcode ("add", "a,#1");
5088 emitcode ("xch", "a,b");
5089 emitcode ("cpl", "a"); // msb
5090 emitcode ("addc","a,#0");
5091 emitcode ("setb","F0");
5092 emitcode ("","!tlabeldef",lbl->key+100);
5093 emitcode ("mov","ma,b");
5094 emitcode ("mov","ma,a");
5096 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5097 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5100 /* load up MB with right */
5102 if (AOP_TYPE(right) == AOP_LIT) {
5103 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5105 lbl = newiTempLabel(NULL);
5106 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5107 emitcode("setb","F0");
5108 emitcode ("","!tlabeldef",lbl->key+100);
5111 emitcode ("mov","mb,#!constbyte",val & 0xff);
5112 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5114 lbl = newiTempLabel(NULL);
5115 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5116 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5117 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5118 emitcode ("xch", "a,b");
5119 emitcode ("cpl","a");
5120 emitcode ("add", "a,#1");
5121 emitcode ("xch", "a,b");
5122 emitcode ("cpl", "a"); // msb
5123 emitcode ("addc", "a,#0");
5124 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5125 emitcode ("setb","F0");
5126 emitcode ("","!tlabeldef",lbl->key+100);
5127 emitcode ("mov","mb,b");
5128 emitcode ("mov","mb,a");
5131 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5132 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5135 /* wait for multiplication to finish */
5136 lbl = newiTempLabel(NULL);
5137 emitcode("","!tlabeldef", lbl->key+100);
5138 emitcode("mov","a,mcnt1");
5139 emitcode("anl","a,#!constbyte",0x80);
5140 emitcode("jnz","!tlabel",lbl->key+100);
5142 freeAsmop (left, NULL, ic, TRUE);
5143 freeAsmop (right, NULL, ic,TRUE);
5144 aopOp(result, ic, TRUE, FALSE);
5146 /* if unsigned then simple */
5148 aopPut(AOP(result),"ma",1);
5149 aopPut(AOP(result),"ma",0);
5151 emitcode("push","ma");
5153 /* negate result if needed */
5154 lbl = newiTempLabel(NULL);
5155 emitcode("jnb","F0,!tlabel",lbl->key+100);
5156 emitcode("cpl","a");
5157 emitcode("add","a,#1");
5158 emitcode("","!tlabeldef", lbl->key+100);
5159 aopPut(AOP(result),"a",0);
5160 emitcode("pop","acc");
5161 lbl = newiTempLabel(NULL);
5162 emitcode("jnb","F0,!tlabel",lbl->key+100);
5163 emitcode("cpl","a");
5164 emitcode("addc","a,#0");
5165 emitcode("","!tlabeldef", lbl->key+100);
5166 aopPut(AOP(result),"a",1);
5168 freeAsmop (result, NULL, ic, TRUE);
5169 /* restore EA bit in F1 */
5170 lbl = newiTempLabel(NULL);
5171 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5172 emitcode ("setb","EA");
5173 emitcode("","!tlabeldef",lbl->key+100);
5177 /*-----------------------------------------------------------------*/
5178 /* genDiv - generates code for division */
5179 /*-----------------------------------------------------------------*/
5183 operand *left = IC_LEFT (ic);
5184 operand *right = IC_RIGHT (ic);
5185 operand *result = IC_RESULT (ic);
5187 D (emitcode (";", "genDiv "););
5189 /* assign the amsops */
5192 /* special cases first */
5194 if (AOP_TYPE (left) == AOP_CRY &&
5195 AOP_TYPE (right) == AOP_CRY)
5197 genDivbits (left, right, result, ic);
5201 /* if both are of size == 1 */
5202 if (AOP_SIZE (left) == 1 &&
5203 AOP_SIZE (right) == 1)
5205 genDivOneByte (left, right, result, ic);
5209 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5210 /* use the ds390 ARITHMETIC accel UNIT */
5211 genDivTwoByte (left, right, result, ic);
5214 /* should have been converted to function call */
5217 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5218 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5219 freeAsmop (result, NULL, ic, TRUE);
5222 /*-----------------------------------------------------------------*/
5223 /* genModbits :- modulus of bits */
5224 /*-----------------------------------------------------------------*/
5226 genModbits (operand * left,
5234 /* the result must be bit */
5235 LOAD_AB_FOR_DIV (left, right, l);
5236 emitcode ("div", "ab");
5237 emitcode ("mov", "a,b");
5238 emitcode ("rrc", "a");
5239 aopOp(result, ic, TRUE, FALSE);
5240 aopPut (AOP (result), "c", 0);
5243 /*-----------------------------------------------------------------*/
5244 /* genModOneByte : 8 bit modulus */
5245 /*-----------------------------------------------------------------*/
5247 genModOneByte (operand * left,
5252 sym_link *opetype = operandType (result);
5256 /* signed or unsigned */
5257 if (SPEC_USIGN (opetype))
5259 /* unsigned is easy */
5260 LOAD_AB_FOR_DIV (left, right, l);
5261 emitcode ("div", "ab");
5262 aopOp(result, ic, TRUE, FALSE);
5263 aopPut (AOP (result), "b", 0);
5267 /* signed is a little bit more difficult */
5269 /* save the signs of the operands */
5270 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5272 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5273 emitcode ("push", "acc"); /* save it on the stack */
5275 /* now sign adjust for both left & right */
5276 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5278 lbl = newiTempLabel (NULL);
5279 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5280 emitcode ("cpl", "a");
5281 emitcode ("inc", "a");
5282 emitcode ("", "!tlabeldef", (lbl->key + 100));
5283 emitcode ("mov", "b,a");
5285 /* sign adjust left side */
5286 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5288 lbl = newiTempLabel (NULL);
5289 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5290 emitcode ("cpl", "a");
5291 emitcode ("inc", "a");
5292 emitcode ("", "!tlabeldef", (lbl->key + 100));
5294 /* now the multiplication */
5295 emitcode ("nop", "; workaround for DS80C390 div bug.");
5296 emitcode ("div", "ab");
5297 /* we are interested in the lower order
5299 lbl = newiTempLabel (NULL);
5300 emitcode ("pop", "acc");
5301 /* if there was an over flow we don't
5302 adjust the sign of the result */
5303 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5304 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5306 emitcode ("clr", "a");
5307 emitcode ("subb", "a,b");
5308 emitcode ("mov", "b,a");
5309 emitcode ("", "!tlabeldef", (lbl->key + 100));
5312 /* now we are done */
5313 aopOp(result, ic, TRUE, FALSE);
5314 aopPut (AOP (result), "b", 0);
5319 /*-----------------------------------------------------------------*/
5320 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
5321 /*-----------------------------------------------------------------*/
5322 static void genModTwoByte (operand *left, operand *right,
5323 operand *result, iCode *ic)
5325 sym_link *retype = getSpec(operandType(right));
5326 sym_link *letype = getSpec(operandType(left));
5327 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5330 /* load up MA with left */
5331 /* save EA bit in F1 */
5332 lbl = newiTempLabel(NULL);
5333 emitcode ("setb","F1");
5334 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5335 emitcode ("clr","F1");
5336 emitcode("","!tlabeldef",lbl->key+100);
5339 lbl = newiTempLabel(NULL);
5340 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5341 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5342 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5343 emitcode ("xch", "a,b");
5344 emitcode ("cpl","a");
5345 emitcode ("add", "a,#1");
5346 emitcode ("xch", "a,b");
5347 emitcode ("cpl", "a"); // msb
5348 emitcode ("addc","a,#0");
5349 emitcode ("","!tlabeldef",lbl->key+100);
5350 emitcode ("mov","ma,b");
5351 emitcode ("mov","ma,a");
5353 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5354 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5357 /* load up MB with right */
5359 if (AOP_TYPE(right) == AOP_LIT) {
5360 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5364 emitcode ("mov","mb,#!constbyte",val & 0xff);
5365 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5367 lbl = newiTempLabel(NULL);
5368 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5369 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5370 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5371 emitcode ("xch", "a,b");
5372 emitcode ("cpl","a");
5373 emitcode ("add", "a,#1");
5374 emitcode ("xch", "a,b");
5375 emitcode ("cpl", "a"); // msb
5376 emitcode ("addc", "a,#0");
5377 emitcode ("","!tlabeldef",lbl->key+100);
5378 emitcode ("mov","mb,b");
5379 emitcode ("mov","mb,a");
5382 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5383 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5386 /* wait for multiplication to finish */
5387 lbl = newiTempLabel(NULL);
5388 emitcode("","!tlabeldef", lbl->key+100);
5389 emitcode("mov","a,mcnt1");
5390 emitcode("anl","a,#!constbyte",0x80);
5391 emitcode("jnz","!tlabel",lbl->key+100);
5393 freeAsmop (left, NULL, ic, TRUE);
5394 freeAsmop (right, NULL, ic,TRUE);
5395 aopOp(result, ic, TRUE, FALSE);
5397 aopPut(AOP(result),"mb",1);
5398 aopPut(AOP(result),"mb",0);
5399 freeAsmop (result, NULL, ic, TRUE);
5401 /* restore EA bit in F1 */
5402 lbl = newiTempLabel(NULL);
5403 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5404 emitcode ("setb","EA");
5405 emitcode("","!tlabeldef",lbl->key+100);
5409 /*-----------------------------------------------------------------*/
5410 /* genMod - generates code for division */
5411 /*-----------------------------------------------------------------*/
5415 operand *left = IC_LEFT (ic);
5416 operand *right = IC_RIGHT (ic);
5417 operand *result = IC_RESULT (ic);
5419 D (emitcode (";", "genMod "); );
5421 /* assign the amsops */
5424 /* special cases first */
5426 if (AOP_TYPE (left) == AOP_CRY &&
5427 AOP_TYPE (right) == AOP_CRY)
5429 genModbits (left, right, result, ic);
5433 /* if both are of size == 1 */
5434 if (AOP_SIZE (left) == 1 &&
5435 AOP_SIZE (right) == 1)
5437 genModOneByte (left, right, result, ic);
5441 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5442 /* use the ds390 ARITHMETIC accel UNIT */
5443 genModTwoByte (left, right, result, ic);
5447 /* should have been converted to function call */
5451 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5452 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5453 freeAsmop (result, NULL, ic, TRUE);
5456 /*-----------------------------------------------------------------*/
5457 /* genIfxJump :- will create a jump depending on the ifx */
5458 /*-----------------------------------------------------------------*/
5460 genIfxJump (iCode * ic, char *jval)
5463 symbol *tlbl = newiTempLabel (NULL);
5466 D (emitcode (";", "genIfxJump"););
5468 /* if true label then we jump if condition
5472 jlbl = IC_TRUE (ic);
5473 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5474 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5478 /* false label is present */
5479 jlbl = IC_FALSE (ic);
5480 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5481 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5483 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5484 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5486 emitcode (inst, "!tlabel", tlbl->key + 100);
5487 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5488 emitcode ("", "!tlabeldef", tlbl->key + 100);
5490 /* mark the icode as generated */
5494 /*-----------------------------------------------------------------*/
5495 /* genCmp :- greater or less than comparison */
5496 /*-----------------------------------------------------------------*/
5498 genCmp (operand * left, operand * right,
5499 iCode * ic, iCode * ifx, int sign)
5501 int size, offset = 0;
5502 unsigned long lit = 0L;
5505 D (emitcode (";", "genCmp"););
5507 result = IC_RESULT (ic);
5509 /* if left & right are bit variables */
5510 if (AOP_TYPE (left) == AOP_CRY &&
5511 AOP_TYPE (right) == AOP_CRY)
5513 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5514 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5518 /* subtract right from left if at the
5519 end the carry flag is set then we know that
5520 left is greater than right */
5521 size = max (AOP_SIZE (left), AOP_SIZE (right));
5523 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5524 if ((size == 1) && !sign
5525 && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5527 symbol *lbl = newiTempLabel (NULL);
5528 emitcode ("cjne", "%s,%s,!tlabel",
5529 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5530 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5532 emitcode ("", "!tlabeldef", lbl->key + 100);
5536 if (AOP_TYPE (right) == AOP_LIT)
5538 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5539 /* optimize if(x < 0) or if(x >= 0) */
5548 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5550 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5551 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5553 aopOp (result, ic, FALSE, FALSE);
5555 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5557 freeAsmop (result, NULL, ic, TRUE);
5558 genIfxJump (ifx, "acc.7");
5563 emitcode ("rlc", "a");
5565 goto release_freedLR;
5573 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5574 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5575 // emitcode (";", "genCmp #2");
5576 if (sign && (size == 0))
5578 // emitcode (";", "genCmp #3");
5579 emitcode ("xrl", "a,#!constbyte",0x80);
5580 if (AOP_TYPE (right) == AOP_LIT)
5582 unsigned long lit = (unsigned long)
5583 floatFromVal (AOP (right)->aopu.aop_lit);
5584 // emitcode (";", "genCmp #3.1");
5585 emitcode ("subb", "a,#!constbyte",
5586 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5590 // emitcode (";", "genCmp #3.2");
5592 MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5593 saveAccWarn = DEFAULT_ACC_WARNING;
5594 emitcode ("xrl", "b,#!constbyte",0x80);
5595 emitcode ("subb", "a,b");
5602 // emitcode (";", "genCmp #4");
5604 s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5605 saveAccWarn = DEFAULT_ACC_WARNING;
5607 emitcode ("subb", "a,%s", s);
5614 /* Don't need the left & right operands any more; do need the result. */
5615 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5616 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5618 aopOp (result, ic, FALSE, FALSE);
5622 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5628 /* if the result is used in the next
5629 ifx conditional branch then generate
5630 code a little differently */
5633 genIfxJump (ifx, "c");
5639 /* leave the result in acc */
5641 freeAsmop (result, NULL, ic, TRUE);
5644 /*-----------------------------------------------------------------*/
5645 /* genCmpGt :- greater than comparison */
5646 /*-----------------------------------------------------------------*/
5648 genCmpGt (iCode * ic, iCode * ifx)
5650 operand *left, *right;
5651 sym_link *letype, *retype;
5654 D (emitcode (";", "genCmpGt ");
5657 left = IC_LEFT (ic);
5658 right = IC_RIGHT (ic);
5660 letype = getSpec (operandType (left));
5661 retype = getSpec (operandType (right));
5662 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5664 /* assign the left & right amsops */
5667 genCmp (right, left, ic, ifx, sign);
5670 /*-----------------------------------------------------------------*/
5671 /* genCmpLt - less than comparisons */
5672 /*-----------------------------------------------------------------*/
5674 genCmpLt (iCode * ic, iCode * ifx)
5676 operand *left, *right;
5677 sym_link *letype, *retype;
5680 D (emitcode (";", "genCmpLt "););
5682 left = IC_LEFT (ic);
5683 right = IC_RIGHT (ic);
5685 letype = getSpec (operandType (left));
5686 retype = getSpec (operandType (right));
5687 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5689 /* assign the left & right amsops */
5692 genCmp (left, right, ic, ifx, sign);
5695 /*-----------------------------------------------------------------*/
5696 /* gencjneshort - compare and jump if not equal */
5697 /*-----------------------------------------------------------------*/
5699 gencjneshort (operand * left, operand * right, symbol * lbl)
5701 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5703 unsigned long lit = 0L;
5705 D (emitcode (";", "gencjneshort");
5708 /* if the left side is a literal or
5709 if the right is in a pointer register and left
5711 if ((AOP_TYPE (left) == AOP_LIT) ||
5712 (AOP_TYPE (left) == AOP_IMMD) ||
5713 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5720 if (AOP_TYPE (right) == AOP_LIT)
5721 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5723 if (opIsGptr (left) || opIsGptr (right))
5725 /* We are comparing a generic pointer to something.
5726 * Exclude the generic type byte from the comparison.
5729 D (emitcode (";", "cjneshort: generic ptr special case."););
5733 /* if the right side is a literal then anything goes */
5734 if (AOP_TYPE (right) == AOP_LIT &&
5735 AOP_TYPE (left) != AOP_DIR)
5739 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5740 emitcode ("cjne", "a,%s,!tlabel",
5741 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5747 /* if the right side is in a register or in direct space or
5748 if the left is a pointer register & right is not */
5749 else if (AOP_TYPE (right) == AOP_REG ||
5750 AOP_TYPE (right) == AOP_DIR ||
5751 AOP_TYPE (right) == AOP_LIT ||
5752 AOP_TYPE (right) == AOP_IMMD ||
5753 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5754 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5758 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5759 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5760 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5761 emitcode ("jnz", "!tlabel", lbl->key + 100);
5763 emitcode ("cjne", "a,%s,!tlabel",
5764 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5771 /* right is a pointer reg need both a & b */
5774 MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5775 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5776 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5782 /*-----------------------------------------------------------------*/
5783 /* gencjne - compare and jump if not equal */
5784 /*-----------------------------------------------------------------*/
5786 gencjne (operand * left, operand * right, symbol * lbl)
5788 symbol *tlbl = newiTempLabel (NULL);
5790 D (emitcode (";", "gencjne");
5793 gencjneshort (left, right, lbl);
5795 emitcode ("mov", "a,%s", one);
5796 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5797 emitcode ("", "!tlabeldef", lbl->key + 100);
5798 emitcode ("clr", "a");
5799 emitcode ("", "!tlabeldef", tlbl->key + 100);
5802 /*-----------------------------------------------------------------*/
5803 /* genCmpEq - generates code for equal to */
5804 /*-----------------------------------------------------------------*/
5806 genCmpEq (iCode * ic, iCode * ifx)
5808 operand *left, *right, *result;
5810 D (emitcode (";", "genCmpEq ");
5814 AOP_SET_LOCALS (ic);
5816 /* if literal, literal on the right or
5817 if the right is in a pointer register and left
5819 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5820 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5822 operand *t = IC_RIGHT (ic);
5823 IC_RIGHT (ic) = IC_LEFT (ic);
5827 if (ifx && /* !AOP_SIZE(result) */
5828 OP_SYMBOL (result) &&
5829 OP_SYMBOL (result)->regType == REG_CND)
5832 /* if they are both bit variables */
5833 if (AOP_TYPE (left) == AOP_CRY &&
5834 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5836 if (AOP_TYPE (right) == AOP_LIT)
5838 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5841 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5842 emitcode ("cpl", "c");
5846 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5850 emitcode ("clr", "c");
5852 /* AOP_TYPE(right) == AOP_CRY */
5856 symbol *lbl = newiTempLabel (NULL);
5857 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5858 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5859 emitcode ("cpl", "c");
5860 emitcode ("", "!tlabeldef", (lbl->key + 100));
5862 /* if true label then we jump if condition
5864 tlbl = newiTempLabel (NULL);
5867 emitcode ("jnc", "!tlabel", tlbl->key + 100);
5868 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5872 emitcode ("jc", "!tlabel", tlbl->key + 100);
5873 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5875 emitcode ("", "!tlabeldef", tlbl->key + 100);
5879 tlbl = newiTempLabel (NULL);
5880 gencjneshort (left, right, tlbl);
5883 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5884 emitcode ("", "!tlabeldef", tlbl->key + 100);
5888 symbol *lbl = newiTempLabel (NULL);
5889 emitcode ("sjmp", "!tlabel", lbl->key + 100);
5890 emitcode ("", "!tlabeldef", tlbl->key + 100);
5891 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5892 emitcode ("", "!tlabeldef", lbl->key + 100);
5895 /* mark the icode as generated */
5898 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5899 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5903 /* if they are both bit variables */
5904 if (AOP_TYPE (left) == AOP_CRY &&
5905 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5907 if (AOP_TYPE (right) == AOP_LIT)
5909 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5912 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5913 emitcode ("cpl", "c");
5917 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5921 emitcode ("clr", "c");
5923 /* AOP_TYPE(right) == AOP_CRY */
5927 symbol *lbl = newiTempLabel (NULL);
5928 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5929 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5930 emitcode ("cpl", "c");
5931 emitcode ("", "!tlabeldef", (lbl->key + 100));
5934 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5935 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5937 aopOp (result, ic, TRUE, FALSE);
5940 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5947 genIfxJump (ifx, "c");
5950 /* if the result is used in an arithmetic operation
5951 then put the result in place */
5956 gencjne (left, right, newiTempLabel (NULL));
5958 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5959 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5961 aopOp (result, ic, TRUE, FALSE);
5963 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5965 aopPut (AOP (result), "a", 0);
5970 genIfxJump (ifx, "a");
5973 /* if the result is used in an arithmetic operation
5974 then put the result in place */
5975 if (AOP_TYPE (result) != AOP_CRY)
5977 /* leave the result in acc */
5981 freeAsmop (result, NULL, ic, TRUE);
5984 /*-----------------------------------------------------------------*/
5985 /* ifxForOp - returns the icode containing the ifx for operand */
5986 /*-----------------------------------------------------------------*/
5988 ifxForOp (operand * op, iCode * ic)
5990 /* if true symbol then needs to be assigned */
5991 if (IS_TRUE_SYMOP (op))
5994 /* if this has register type condition and
5995 the next instruction is ifx with the same operand
5996 and live to of the operand is upto the ifx only then */
5998 ic->next->op == IFX &&
5999 IC_COND (ic->next)->key == op->key &&
6000 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6005 /*-----------------------------------------------------------------*/
6006 /* hasInc - operand is incremented before any other use */
6007 /*-----------------------------------------------------------------*/
6009 hasInc (operand *op, iCode *ic, int osize)
6011 sym_link *type = operandType(op);
6012 sym_link *retype = getSpec (type);
6013 iCode *lic = ic->next;
6016 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6017 if (!IS_SYMOP(op)) return NULL;
6019 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6020 if (IS_AGGREGATE(type->next)) return NULL;
6021 if (osize != (isize = getSize(type->next))) return NULL;
6024 /* if operand of the form op = op + <sizeof *op> */
6025 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6026 isOperandEqual(IC_RESULT(lic),op) &&
6027 isOperandLiteral(IC_RIGHT(lic)) &&
6028 operandLitValue(IC_RIGHT(lic)) == isize) {
6031 /* if the operand used or deffed */
6032 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
6035 /* if GOTO or IFX */
6036 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6042 /*-----------------------------------------------------------------*/
6043 /* genAndOp - for && operation */
6044 /*-----------------------------------------------------------------*/
6046 genAndOp (iCode * ic)
6048 operand *left, *right, *result;
6051 D (emitcode (";", "genAndOp "););
6053 /* note here that && operations that are in an
6054 if statement are taken away by backPatchLabels
6055 only those used in arthmetic operations remain */
6057 AOP_SET_LOCALS (ic);
6059 /* if both are bit variables */
6060 if (AOP_TYPE (left) == AOP_CRY &&
6061 AOP_TYPE (right) == AOP_CRY)
6063 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6064 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6065 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6066 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6068 aopOp (result,ic,FALSE, FALSE);
6073 tlbl = newiTempLabel (NULL);
6075 emitcode ("jz", "!tlabel", tlbl->key + 100);
6077 emitcode ("", "!tlabeldef", tlbl->key + 100);
6078 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6079 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6081 aopOp (result,ic,FALSE, FALSE);
6084 freeAsmop (result, NULL, ic, TRUE);
6088 /*-----------------------------------------------------------------*/
6089 /* genOrOp - for || operation */
6090 /*-----------------------------------------------------------------*/
6092 genOrOp (iCode * ic)
6094 operand *left, *right, *result;
6097 D (emitcode (";", "genOrOp "););
6099 /* note here that || operations that are in an
6100 if statement are taken away by backPatchLabels
6101 only those used in arthmetic operations remain */
6103 AOP_SET_LOCALS (ic);
6105 /* if both are bit variables */
6106 if (AOP_TYPE (left) == AOP_CRY &&
6107 AOP_TYPE (right) == AOP_CRY)
6109 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6110 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6111 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6112 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6114 aopOp (result,ic,FALSE, FALSE);
6120 tlbl = newiTempLabel (NULL);
6122 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6124 emitcode ("", "!tlabeldef", tlbl->key + 100);
6125 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6126 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6128 aopOp (result,ic,FALSE, FALSE);
6133 freeAsmop (result, NULL, ic, TRUE);
6136 /*-----------------------------------------------------------------*/
6137 /* isLiteralBit - test if lit == 2^n */
6138 /*-----------------------------------------------------------------*/
6140 isLiteralBit (unsigned long lit)
6142 unsigned long pw[32] =
6143 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6144 0x100L, 0x200L, 0x400L, 0x800L,
6145 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6146 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6147 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6148 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6149 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6152 for (idx = 0; idx < 32; idx++)
6158 /*-----------------------------------------------------------------*/
6159 /* continueIfTrue - */
6160 /*-----------------------------------------------------------------*/
6162 continueIfTrue (iCode * ic)
6165 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6169 /*-----------------------------------------------------------------*/
6171 /*-----------------------------------------------------------------*/
6173 jumpIfTrue (iCode * ic)
6176 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6180 /*-----------------------------------------------------------------*/
6181 /* jmpTrueOrFalse - */
6182 /*-----------------------------------------------------------------*/
6184 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6186 // ugly but optimized by peephole
6189 symbol *nlbl = newiTempLabel (NULL);
6190 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6191 emitcode ("", "!tlabeldef", tlbl->key + 100);
6192 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6193 emitcode ("", "!tlabeldef", nlbl->key + 100);
6197 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6198 emitcode ("", "!tlabeldef", tlbl->key + 100);
6203 // Generate code to perform a bit-wise logic operation
6204 // on two operands in far space (assumed to already have been
6205 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6206 // in far space. This requires pushing the result on the stack
6207 // then popping it into the result.
6209 genFarFarLogicOp(iCode *ic, char *logicOp)
6211 int size, resultSize, compSize;
6215 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6216 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
6217 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6219 _startLazyDPSEvaluation();
6220 for (size = compSize; (size--); offset++)
6222 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6223 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6224 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6226 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6227 emitcode ("push", "acc");
6229 _endLazyDPSEvaluation();
6231 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6232 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6233 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6235 resultSize = AOP_SIZE(IC_RESULT(ic));
6237 ADJUST_PUSHED_RESULT(compSize, resultSize);
6239 _startLazyDPSEvaluation();
6242 emitcode ("pop", "acc");
6243 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6245 _endLazyDPSEvaluation();
6246 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6250 /*-----------------------------------------------------------------*/
6251 /* genAnd - code for and */
6252 /*-----------------------------------------------------------------*/
6254 genAnd (iCode * ic, iCode * ifx)
6256 operand *left, *right, *result;
6257 int size, offset = 0;
6258 unsigned long lit = 0L;
6263 D (emitcode (";", "genAnd "););
6265 AOP_OP_3_NOFATAL (ic, pushResult);
6266 AOP_SET_LOCALS (ic);
6270 genFarFarLogicOp(ic, "anl");
6275 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6277 AOP_TYPE (left), AOP_TYPE (right));
6278 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6280 AOP_SIZE (left), AOP_SIZE (right));
6283 /* if left is a literal & right is not then exchange them */
6284 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6285 #ifdef LOGIC_OPS_BROKEN
6286 || AOP_NEEDSACC (left)
6290 operand *tmp = right;
6295 /* if result = right then exchange them */
6296 if (sameRegs (AOP (result), AOP (right)))
6298 operand *tmp = right;
6303 /* if right is bit then exchange them */
6304 if (AOP_TYPE (right) == AOP_CRY &&
6305 AOP_TYPE (left) != AOP_CRY)
6307 operand *tmp = right;
6311 if (AOP_TYPE (right) == AOP_LIT)
6312 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6314 size = AOP_SIZE (result);
6317 // result = bit & yy;
6318 if (AOP_TYPE (left) == AOP_CRY)
6320 // c = bit & literal;
6321 if (AOP_TYPE (right) == AOP_LIT)
6325 if (size && sameRegs (AOP (result), AOP (left)))
6328 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6333 if (size && (AOP_TYPE (result) == AOP_CRY))
6335 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6338 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6343 emitcode ("clr", "c");
6348 if (AOP_TYPE (right) == AOP_CRY)
6351 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6352 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6357 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6359 emitcode ("rrc", "a");
6360 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6368 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6369 genIfxJump (ifx, "c");
6373 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6374 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6375 if ((AOP_TYPE (right) == AOP_LIT) &&
6376 (AOP_TYPE (result) == AOP_CRY) &&
6377 (AOP_TYPE (left) != AOP_CRY))
6379 int posbit = isLiteralBit (lit);
6384 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6387 emitcode ("mov", "c,acc.%d", posbit & 0x07);
6393 SNPRINTF (buff, sizeof(buff),
6394 "acc.%d", posbit & 0x07);
6395 genIfxJump (ifx, buff);
6399 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6406 symbol *tlbl = newiTempLabel (NULL);
6407 int sizel = AOP_SIZE (left);
6409 emitcode ("setb", "c");
6412 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6414 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6416 if ((posbit = isLiteralBit (bytelit)) != 0)
6417 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6420 if (bytelit != 0x0FFL)
6421 emitcode ("anl", "a,%s",
6422 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6423 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6428 // bit = left & literal
6431 emitcode ("clr", "c");
6432 emitcode ("", "!tlabeldef", tlbl->key + 100);
6434 // if(left & literal)
6438 jmpTrueOrFalse (ifx, tlbl);
6440 emitcode ("", "!tlabeldef", tlbl->key + 100);
6448 /* if left is same as result */
6449 if (sameRegs (AOP (result), AOP (left)))
6451 for (; size--; offset++)
6453 if (AOP_TYPE (right) == AOP_LIT)
6455 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6457 else if (bytelit == 0)
6458 aopPut (AOP (result), zero, offset);
6459 else if (IS_AOP_PREG (result))
6461 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6462 emitcode ("anl", "a,%s",
6463 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6464 aopPut (AOP (result), "a", offset);
6467 emitcode ("anl", "%s,%s",
6468 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6469 aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6473 if (AOP_TYPE (left) == AOP_ACC)
6474 emitcode ("anl", "a,%s",
6475 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6478 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6479 if (IS_AOP_PREG (result))
6481 emitcode ("anl", "a,%s",
6482 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6483 aopPut (AOP (result), "a", offset);
6486 emitcode ("anl", "%s,a",
6487 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6494 // left & result in different registers
6495 if (AOP_TYPE (result) == AOP_CRY)
6498 // if(size), result in bit
6499 // if(!size && ifx), conditional oper: if(left & right)
6500 symbol *tlbl = newiTempLabel (NULL);
6501 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6503 emitcode ("setb", "c");
6506 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6507 emitcode ("anl", "a,%s",
6508 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6510 if (AOP_TYPE(left)==AOP_ACC) {
6511 emitcode("mov", "b,a");
6512 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6513 emitcode("anl", "a,b");
6515 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6516 emitcode ("anl", "a,%s",
6517 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6520 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6526 emitcode ("", "!tlabeldef", tlbl->key + 100);
6530 jmpTrueOrFalse (ifx, tlbl);
6532 emitcode ("", "!tlabeldef", tlbl->key + 100);
6536 for (; (size--); offset++)
6539 // result = left & right
6540 if (AOP_TYPE (right) == AOP_LIT)
6542 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6544 aopPut (AOP (result),
6545 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6549 else if (bytelit == 0)
6551 aopPut (AOP (result), zero, offset);
6554 D (emitcode (";", "better literal AND."););
6555 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6556 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6557 FALSE, FALSE, DP2_RESULT_REG));
6562 // faster than result <- left, anl result,right
6563 // and better if result is SFR
6564 if (AOP_TYPE (left) == AOP_ACC)
6566 emitcode ("anl", "a,%s",
6567 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6571 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6572 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6574 emitcode("mov", "b,a");
6578 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6579 emitcode ("anl", "a,%s", rOp);
6582 aopPut (AOP (result), "a", offset);
6588 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6589 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6590 freeAsmop (result, NULL, ic, TRUE);
6594 /*-----------------------------------------------------------------*/
6595 /* genOr - code for or */
6596 /*-----------------------------------------------------------------*/
6598 genOr (iCode * ic, iCode * ifx)
6600 operand *left, *right, *result;
6601 int size, offset = 0;
6602 unsigned long lit = 0L;
6605 D (emitcode (";", "genOr "););
6607 AOP_OP_3_NOFATAL (ic, pushResult);
6608 AOP_SET_LOCALS (ic);
6612 genFarFarLogicOp(ic, "orl");
6618 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6620 AOP_TYPE (left), AOP_TYPE (right));
6621 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6623 AOP_SIZE (left), AOP_SIZE (right));
6626 /* if left is a literal & right is not then exchange them */
6627 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6628 #ifdef LOGIC_OPS_BROKEN
6629 || AOP_NEEDSACC (left) // I think this is a net loss now.
6633 operand *tmp = right;
6638 /* if result = right then exchange them */
6639 if (sameRegs (AOP (result), AOP (right)))
6641 operand *tmp = right;
6646 /* if right is bit then exchange them */
6647 if (AOP_TYPE (right) == AOP_CRY &&
6648 AOP_TYPE (left) != AOP_CRY)
6650 operand *tmp = right;
6654 if (AOP_TYPE (right) == AOP_LIT)
6655 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6657 size = AOP_SIZE (result);
6661 if (AOP_TYPE (left) == AOP_CRY)
6663 if (AOP_TYPE (right) == AOP_LIT)
6665 // c = bit & literal;
6668 // lit != 0 => result = 1
6669 if (AOP_TYPE (result) == AOP_CRY)
6672 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6674 continueIfTrue (ifx);
6677 emitcode ("setb", "c");
6681 // lit == 0 => result = left
6682 if (size && sameRegs (AOP (result), AOP (left)))
6684 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6689 if (AOP_TYPE (right) == AOP_CRY)
6692 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6693 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6698 symbol *tlbl = newiTempLabel (NULL);
6699 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6700 emitcode ("setb", "c");
6701 emitcode ("jb", "%s,!tlabel",
6702 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6704 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6705 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6707 jmpTrueOrFalse (ifx, tlbl);
6713 emitcode ("", "!tlabeldef", tlbl->key + 100);
6722 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6723 genIfxJump (ifx, "c");
6727 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6728 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6729 if ((AOP_TYPE (right) == AOP_LIT) &&
6730 (AOP_TYPE (result) == AOP_CRY) &&
6731 (AOP_TYPE (left) != AOP_CRY))
6737 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6739 continueIfTrue (ifx);
6744 // lit = 0, result = boolean(left)
6746 emitcode ("setb", "c");
6750 symbol *tlbl = newiTempLabel (NULL);
6751 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6753 emitcode ("", "!tlabeldef", tlbl->key + 100);
6757 genIfxJump (ifx, "a");
6765 /* if left is same as result */
6766 if (sameRegs (AOP (result), AOP (left)))
6768 for (; size--; offset++)
6770 if (AOP_TYPE (right) == AOP_LIT)
6772 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6778 if (IS_AOP_PREG (left))
6780 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6781 emitcode ("orl", "a,%s",
6782 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6783 aopPut (AOP (result), "a", offset);
6787 emitcode ("orl", "%s,%s",
6788 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6789 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6795 if (AOP_TYPE (left) == AOP_ACC)
6797 emitcode ("orl", "a,%s",
6798 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6802 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6803 if (IS_AOP_PREG (left))
6805 emitcode ("orl", "a,%s",
6806 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6807 aopPut (AOP (result), "a", offset);
6811 emitcode ("orl", "%s,a",
6812 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6820 // left & result in different registers
6821 if (AOP_TYPE (result) == AOP_CRY)
6824 // if(size), result in bit
6825 // if(!size && ifx), conditional oper: if(left | right)
6826 symbol *tlbl = newiTempLabel (NULL);
6827 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6829 emitcode ("setb", "c");
6832 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6833 emitcode ("orl", "a,%s",
6834 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6836 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6837 emitcode ("orl", "a,%s",
6838 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6840 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6846 emitcode ("", "!tlabeldef", tlbl->key + 100);
6850 jmpTrueOrFalse (ifx, tlbl);
6852 emitcode ("", "!tlabeldef", tlbl->key + 100);
6856 _startLazyDPSEvaluation();
6857 for (; (size--); offset++)
6860 // result = left & right
6861 if (AOP_TYPE (right) == AOP_LIT)
6863 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6865 aopPut (AOP (result),
6866 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6870 D (emitcode (";", "better literal OR."););
6871 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6872 emitcode ("orl", "a, %s",
6873 aopGet (AOP (right), offset,
6874 FALSE, FALSE, DP2_RESULT_REG));
6879 // faster than result <- left, anl result,right
6880 // and better if result is SFR
6881 if (AOP_TYPE (left) == AOP_ACC)
6883 emitcode ("orl", "a,%s",
6884 aopGet (AOP (right), offset,
6885 FALSE, FALSE, DP2_RESULT_REG));
6889 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6891 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6893 emitcode("mov", "b,a");
6897 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6898 emitcode ("orl", "a,%s", rOp);
6901 aopPut (AOP (result), "a", offset);
6903 _endLazyDPSEvaluation();
6908 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6909 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6910 freeAsmop (result, NULL, ic, TRUE);
6913 /*-----------------------------------------------------------------*/
6914 /* genXor - code for xclusive or */
6915 /*-----------------------------------------------------------------*/
6917 genXor (iCode * ic, iCode * ifx)
6919 operand *left, *right, *result;
6920 int size, offset = 0;
6921 unsigned long lit = 0L;
6924 D (emitcode (";", "genXor "););
6926 AOP_OP_3_NOFATAL (ic, pushResult);
6927 AOP_SET_LOCALS (ic);
6931 genFarFarLogicOp(ic, "xrl");
6936 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6938 AOP_TYPE (left), AOP_TYPE (right));
6939 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6941 AOP_SIZE (left), AOP_SIZE (right));
6944 /* if left is a literal & right is not ||
6945 if left needs acc & right does not */
6946 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6947 #ifdef LOGIC_OPS_BROKEN
6948 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6952 operand *tmp = right;
6957 /* if result = right then exchange them */
6958 if (sameRegs (AOP (result), AOP (right)))
6960 operand *tmp = right;
6965 /* if right is bit then exchange them */
6966 if (AOP_TYPE (right) == AOP_CRY &&
6967 AOP_TYPE (left) != AOP_CRY)
6969 operand *tmp = right;
6973 if (AOP_TYPE (right) == AOP_LIT)
6974 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6976 size = AOP_SIZE (result);
6980 if (AOP_TYPE (left) == AOP_CRY)
6982 if (AOP_TYPE (right) == AOP_LIT)
6984 // c = bit & literal;
6987 // lit>>1 != 0 => result = 1
6988 if (AOP_TYPE (result) == AOP_CRY)
6991 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6993 continueIfTrue (ifx);
6996 emitcode ("setb", "c");
7003 // lit == 0, result = left
7004 if (size && sameRegs (AOP (result), AOP (left)))
7006 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7010 // lit == 1, result = not(left)
7011 if (size && sameRegs (AOP (result), AOP (left)))
7013 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7018 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7019 emitcode ("cpl", "c");
7028 symbol *tlbl = newiTempLabel (NULL);
7029 if (AOP_TYPE (right) == AOP_CRY)
7032 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7036 int sizer = AOP_SIZE (right);
7038 // if val>>1 != 0, result = 1
7039 emitcode ("setb", "c");
7042 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
7044 // test the msb of the lsb
7045 emitcode ("anl", "a,#!constbyte",0xfe);
7046 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7050 emitcode ("rrc", "a");
7052 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7053 emitcode ("cpl", "c");
7054 emitcode ("", "!tlabeldef", (tlbl->key + 100));
7061 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7062 genIfxJump (ifx, "c");
7066 if (sameRegs (AOP (result), AOP (left)))
7068 /* if left is same as result */
7069 for (; size--; offset++)
7071 if (AOP_TYPE (right) == AOP_LIT)
7073 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7075 else if (IS_AOP_PREG (left))
7077 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7078 emitcode ("xrl", "a,%s",
7079 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7080 aopPut (AOP (result), "a", offset);
7083 emitcode ("xrl", "%s,%s",
7084 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7085 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7089 if (AOP_TYPE (left) == AOP_ACC)
7090 emitcode ("xrl", "a,%s",
7091 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7094 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7095 if (IS_AOP_PREG (left))
7097 emitcode ("xrl", "a,%s",
7098 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7099 aopPut (AOP (result), "a", offset);
7102 emitcode ("xrl", "%s,a",
7103 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7110 // left & result in different registers
7111 if (AOP_TYPE (result) == AOP_CRY)
7114 // if(size), result in bit
7115 // if(!size && ifx), conditional oper: if(left ^ right)
7116 symbol *tlbl = newiTempLabel (NULL);
7117 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7120 emitcode ("setb", "c");
7123 if ((AOP_TYPE (right) == AOP_LIT) &&
7124 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7126 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7130 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7131 emitcode ("xrl", "a,%s",
7132 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7134 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7135 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7137 emitcode("mov", "b,a");
7141 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7142 emitcode ("xrl", "a,%s", rOp);
7145 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7151 emitcode ("", "!tlabeldef", tlbl->key + 100);
7155 jmpTrueOrFalse (ifx, tlbl);
7159 for (; (size--); offset++)
7162 // result = left & right
7163 if (AOP_TYPE (right) == AOP_LIT)
7165 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7167 aopPut (AOP (result),
7168 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7172 D (emitcode (";", "better literal XOR."););
7173 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7174 emitcode ("xrl", "a, %s",
7175 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7179 // faster than result <- left, anl result,right
7180 // and better if result is SFR
7181 if (AOP_TYPE (left) == AOP_ACC)
7183 emitcode ("xrl", "a,%s",
7184 aopGet (AOP (right), offset,
7185 FALSE, FALSE, DP2_RESULT_REG));
7189 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7190 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7192 emitcode("mov", "b,a");
7196 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7197 emitcode ("xrl", "a,%s", rOp);
7200 aopPut (AOP (result), "a", offset);
7207 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7208 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7209 freeAsmop (result, NULL, ic, TRUE);
7212 /*-----------------------------------------------------------------*/
7213 /* genInline - write the inline code out */
7214 /*-----------------------------------------------------------------*/
7216 genInline (iCode * ic)
7218 char *buffer, *bp, *bp1;
7220 D (emitcode (";", "genInline "); );
7222 _G.inLine += (!options.asmpeep);
7224 buffer = Safe_strdup(IC_INLINE(ic));
7228 /* emit each line as a code */
7253 /* emitcode("",buffer); */
7254 _G.inLine -= (!options.asmpeep);
7257 /*-----------------------------------------------------------------*/
7258 /* genRRC - rotate right with carry */
7259 /*-----------------------------------------------------------------*/
7263 operand *left, *result;
7266 D (emitcode (";", "genRRC "););
7268 /* rotate right with carry */
7269 left = IC_LEFT (ic);
7270 result = IC_RESULT (ic);
7271 aopOp (left, ic, FALSE, FALSE);
7272 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7274 /* move it to the result */
7275 size = AOP_SIZE (result);
7279 _startLazyDPSEvaluation ();
7282 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7283 emitcode ("rrc", "a");
7284 if (AOP_SIZE (result) > 1)
7285 aopPut (AOP (result), "a", offset--);
7287 _endLazyDPSEvaluation ();
7289 /* now we need to put the carry into the
7290 highest order byte of the result */
7291 if (AOP_SIZE (result) > 1)
7293 MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7295 emitcode ("mov", "acc.7,c");
7296 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7297 freeAsmop (left, NULL, ic, TRUE);
7298 freeAsmop (result, NULL, ic, TRUE);
7301 /*-----------------------------------------------------------------*/
7302 /* genRLC - generate code for rotate left with carry */
7303 /*-----------------------------------------------------------------*/
7307 operand *left, *result;
7311 D (emitcode (";", "genRLC "););
7313 /* rotate right with carry */
7314 left = IC_LEFT (ic);
7315 result = IC_RESULT (ic);
7316 aopOp (left, ic, FALSE, FALSE);
7317 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7319 /* move it to the result */
7320 size = AOP_SIZE (result);
7324 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7326 emitcode ("add", "a,acc");
7327 if (AOP_SIZE (result) > 1)
7329 aopPut (AOP (result), "a", offset++);
7332 _startLazyDPSEvaluation ();
7335 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7337 emitcode ("rlc", "a");
7338 if (AOP_SIZE (result) > 1)
7339 aopPut (AOP (result), "a", offset++);
7341 _endLazyDPSEvaluation ();
7343 /* now we need to put the carry into the
7344 highest order byte of the result */
7345 if (AOP_SIZE (result) > 1)
7347 l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7350 emitcode ("mov", "acc.0,c");
7351 aopPut (AOP (result), "a", 0);
7352 freeAsmop (left, NULL, ic, TRUE);
7353 freeAsmop (result, NULL, ic, TRUE);
7356 /*-----------------------------------------------------------------*/
7357 /* genGetHbit - generates code get highest order bit */
7358 /*-----------------------------------------------------------------*/
7360 genGetHbit (iCode * ic)
7362 operand *left, *result;
7363 left = IC_LEFT (ic);
7364 result = IC_RESULT (ic);
7365 aopOp (left, ic, FALSE, FALSE);
7366 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7368 D (emitcode (";", "genGetHbit "););
7370 /* get the highest order byte into a */
7371 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7372 if (AOP_TYPE (result) == AOP_CRY)
7374 emitcode ("rlc", "a");
7379 emitcode ("rl", "a");
7380 emitcode ("anl", "a,#1");
7385 freeAsmop (left, NULL, ic, TRUE);
7386 freeAsmop (result, NULL, ic, TRUE);
7389 /*-----------------------------------------------------------------*/
7390 /* genSwap - generates code to swap nibbles or bytes */
7391 /*-----------------------------------------------------------------*/
7393 genSwap (iCode * ic)
7395 operand *left, *result;
7397 D(emitcode ("; genSwap",""));
7399 left = IC_LEFT (ic);
7400 result = IC_RESULT (ic);
7401 aopOp (left, ic, FALSE, FALSE);
7402 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7404 _startLazyDPSEvaluation ();
7405 switch (AOP_SIZE (left))
7407 case 1: /* swap nibbles in byte */
7408 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7409 emitcode ("swap", "a");
7410 aopPut (AOP (result), "a", 0);
7412 case 2: /* swap bytes in word */
7413 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7415 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7416 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7417 aopPut (AOP (result), "a", 1);
7419 else if (operandsEqu (left, result))
7422 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7423 if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
7425 emitcode ("mov", "b,a");
7429 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7430 aopPut (AOP (result), reg, 1);
7435 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7436 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE, NULL), 1);
7440 wassertl(FALSE, "unsupported SWAP operand size");
7442 _endLazyDPSEvaluation ();
7444 freeAsmop (left, NULL, ic, TRUE);
7445 freeAsmop (result, NULL, ic, TRUE);
7448 /*-----------------------------------------------------------------*/
7449 /* AccRol - rotate left accumulator by known count */
7450 /*-----------------------------------------------------------------*/
7452 AccRol (int shCount)
7454 shCount &= 0x0007; // shCount : 0..7
7461 emitcode ("rl", "a");
7464 emitcode ("rl", "a");
7465 emitcode ("rl", "a");
7468 emitcode ("swap", "a");
7469 emitcode ("rr", "a");
7472 emitcode ("swap", "a");
7475 emitcode ("swap", "a");
7476 emitcode ("rl", "a");
7479 emitcode ("rr", "a");
7480 emitcode ("rr", "a");
7483 emitcode ("rr", "a");
7488 /*-----------------------------------------------------------------*/
7489 /* AccLsh - left shift accumulator by known count */
7490 /*-----------------------------------------------------------------*/
7492 AccLsh (int shCount)
7497 emitcode ("add", "a,acc");
7498 else if (shCount == 2)
7500 emitcode ("add", "a,acc");
7501 emitcode ("add", "a,acc");
7505 /* rotate left accumulator */
7507 /* and kill the lower order bits */
7508 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7513 /*-----------------------------------------------------------------*/
7514 /* AccRsh - right shift accumulator by known count */
7515 /*-----------------------------------------------------------------*/
7517 AccRsh (int shCount)
7524 emitcode ("rrc", "a");
7528 /* rotate right accumulator */
7529 AccRol (8 - shCount);
7530 /* and kill the higher order bits */
7531 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7536 #ifdef BETTER_LITERAL_SHIFT
7537 /*-----------------------------------------------------------------*/
7538 /* AccSRsh - signed right shift accumulator by known count */
7539 /*-----------------------------------------------------------------*/
7541 AccSRsh (int shCount)
7548 emitcode ("mov", "c,acc.7");
7549 emitcode ("rrc", "a");
7551 else if (shCount == 2)
7553 emitcode ("mov", "c,acc.7");
7554 emitcode ("rrc", "a");
7555 emitcode ("mov", "c,acc.7");
7556 emitcode ("rrc", "a");
7560 tlbl = newiTempLabel (NULL);
7561 /* rotate right accumulator */
7562 AccRol (8 - shCount);
7563 /* and kill the higher order bits */
7564 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7565 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7566 emitcode ("orl", "a,#!constbyte",
7567 (unsigned char) ~SRMask[shCount]);
7568 emitcode ("", "!tlabeldef", tlbl->key + 100);
7574 #ifdef BETTER_LITERAL_SHIFT
7575 /*-----------------------------------------------------------------*/
7576 /* shiftR1Left2Result - shift right one byte from left to result */
7577 /*-----------------------------------------------------------------*/
7579 shiftR1Left2Result (operand * left, int offl,
7580 operand * result, int offr,
7581 int shCount, int sign)
7583 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7584 /* shift right accumulator */
7589 aopPut (AOP (result), "a", offr);
7593 #ifdef BETTER_LITERAL_SHIFT
7594 /*-----------------------------------------------------------------*/
7595 /* shiftL1Left2Result - shift left one byte from left to result */
7596 /*-----------------------------------------------------------------*/
7598 shiftL1Left2Result (operand * left, int offl,
7599 operand * result, int offr, int shCount)
7601 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7602 /* shift left accumulator */
7604 aopPut (AOP (result), "a", offr);
7608 #ifdef BETTER_LITERAL_SHIFT
7609 /*-----------------------------------------------------------------*/
7610 /* movLeft2Result - move byte from left to result */
7611 /*-----------------------------------------------------------------*/
7613 movLeft2Result (operand * left, int offl,
7614 operand * result, int offr, int sign)
7617 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7619 l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7621 if (*l == '@' && (IS_AOP_PREG (result)))
7623 emitcode ("mov", "a,%s", l);
7624 aopPut (AOP (result), "a", offr);
7630 aopPut (AOP (result), l, offr);
7634 /* MSB sign in acc.7 ! */
7635 if (getDataSize (left) == offl + 1)
7637 emitcode ("mov", "a,%s", l);
7638 aopPut (AOP (result), "a", offr);
7646 #ifdef BETTER_LITERAL_SHIFT
7647 /*-----------------------------------------------------------------*/
7648 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7649 /*-----------------------------------------------------------------*/
7653 emitcode ("rrc", "a");
7654 emitcode ("xch", "a,%s", x);
7655 emitcode ("rrc", "a");
7656 emitcode ("xch", "a,%s", x);
7660 #ifdef BETTER_LITERAL_SHIFT
7662 /*-----------------------------------------------------------------*/
7663 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7664 /*-----------------------------------------------------------------*/
7668 emitcode ("xch", "a,%s", x);
7669 emitcode ("rlc", "a");
7670 emitcode ("xch", "a,%s", x);
7671 emitcode ("rlc", "a");
7675 #ifdef BETTER_LITERAL_SHIFT
7676 /*-----------------------------------------------------------------*/
7677 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7678 /*-----------------------------------------------------------------*/
7682 emitcode ("xch", "a,%s", x);
7683 emitcode ("add", "a,acc");
7684 emitcode ("xch", "a,%s", x);
7685 emitcode ("rlc", "a");
7689 #ifdef BETTER_LITERAL_SHIFT
7690 /*-----------------------------------------------------------------*/
7691 /* AccAXLsh - left shift a:x by known count (0..7) */
7692 /*-----------------------------------------------------------------*/
7694 AccAXLsh (char *x, int shCount)
7709 case 5: // AAAAABBB:CCCCCDDD
7711 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7713 emitcode ("anl", "a,#!constbyte",
7714 SLMask[shCount]); // BBB00000:CCCCCDDD
7716 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7718 AccRol (shCount); // DDDCCCCC:BBB00000
7720 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7722 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7724 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7726 emitcode ("anl", "a,#!constbyte",
7727 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7729 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7731 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7734 case 6: // AAAAAABB:CCCCCCDD
7735 emitcode ("anl", "a,#!constbyte",
7736 SRMask[shCount]); // 000000BB:CCCCCCDD
7737 emitcode ("mov", "c,acc.0"); // c = B
7738 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7740 AccAXRrl1 (x); // BCCCCCCD:D000000B
7741 AccAXRrl1 (x); // BBCCCCCC:DD000000
7743 emitcode("rrc","a");
7744 emitcode("xch","a,%s", x);
7745 emitcode("rrc","a");
7746 emitcode("mov","c,acc.0"); //<< get correct bit
7747 emitcode("xch","a,%s", x);
7749 emitcode("rrc","a");
7750 emitcode("xch","a,%s", x);
7751 emitcode("rrc","a");
7752 emitcode("xch","a,%s", x);
7755 case 7: // a:x <<= 7
7757 emitcode ("anl", "a,#!constbyte",
7758 SRMask[shCount]); // 0000000B:CCCCCCCD
7760 emitcode ("mov", "c,acc.0"); // c = B
7762 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7764 AccAXRrl1 (x); // BCCCCCCC:D0000000
7773 #ifdef BETTER_LITERAL_SHIFT
7775 /*-----------------------------------------------------------------*/
7776 /* AccAXRsh - right shift a:x known count (0..7) */
7777 /*-----------------------------------------------------------------*/
7779 AccAXRsh (char *x, int shCount)
7787 AccAXRrl1 (x); // 0->a:x
7792 AccAXRrl1 (x); // 0->a:x
7795 AccAXRrl1 (x); // 0->a:x
7800 case 5: // AAAAABBB:CCCCCDDD = a:x
7802 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7804 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7806 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7808 emitcode ("anl", "a,#!constbyte",
7809 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7811 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7813 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7815 emitcode ("anl", "a,#!constbyte",
7816 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7818 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7820 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7822 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7825 case 6: // AABBBBBB:CCDDDDDD
7827 emitcode ("mov", "c,acc.7");
7828 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7830 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7832 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7834 emitcode ("anl", "a,#!constbyte",
7835 SRMask[shCount]); // 000000AA:BBBBBBCC
7838 case 7: // ABBBBBBB:CDDDDDDD
7840 emitcode ("mov", "c,acc.7"); // c = A
7842 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7844 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7846 emitcode ("anl", "a,#!constbyte",
7847 SRMask[shCount]); // 0000000A:BBBBBBBC
7856 #ifdef BETTER_LITERAL_SHIFT
7857 /*-----------------------------------------------------------------*/
7858 /* AccAXRshS - right shift signed a:x known count (0..7) */
7859 /*-----------------------------------------------------------------*/
7861 AccAXRshS (char *x, int shCount)
7869 emitcode ("mov", "c,acc.7");
7870 AccAXRrl1 (x); // s->a:x
7874 emitcode ("mov", "c,acc.7");
7875 AccAXRrl1 (x); // s->a:x
7877 emitcode ("mov", "c,acc.7");
7878 AccAXRrl1 (x); // s->a:x
7883 case 5: // AAAAABBB:CCCCCDDD = a:x
7885 tlbl = newiTempLabel (NULL);
7886 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7888 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7890 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7892 emitcode ("anl", "a,#!constbyte",
7893 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7895 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7897 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7899 emitcode ("anl", "a,#!constbyte",
7900 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7902 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7904 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7906 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7908 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7909 emitcode ("orl", "a,#!constbyte",
7910 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7912 emitcode ("", "!tlabeldef", tlbl->key + 100);
7913 break; // SSSSAAAA:BBBCCCCC
7915 case 6: // AABBBBBB:CCDDDDDD
7917 tlbl = newiTempLabel (NULL);
7918 emitcode ("mov", "c,acc.7");
7919 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7921 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7923 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7925 emitcode ("anl", "a,#!constbyte",
7926 SRMask[shCount]); // 000000AA:BBBBBBCC
7928 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7929 emitcode ("orl", "a,#!constbyte",
7930 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7932 emitcode ("", "!tlabeldef", tlbl->key + 100);
7934 case 7: // ABBBBBBB:CDDDDDDD
7936 tlbl = newiTempLabel (NULL);
7937 emitcode ("mov", "c,acc.7"); // c = A
7939 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7941 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7943 emitcode ("anl", "a,#!constbyte",
7944 SRMask[shCount]); // 0000000A:BBBBBBBC
7946 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7947 emitcode ("orl", "a,#!constbyte",
7948 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7950 emitcode ("", "!tlabeldef", tlbl->key + 100);
7958 #ifdef BETTER_LITERAL_SHIFT
7960 _loadLeftIntoAx(char **lsb,
7966 // Get the initial value from left into a pair of registers.
7967 // MSB must be in A, LSB can be any register.
7969 // If the result is held in registers, it is an optimization
7970 // if the LSB can be held in the register which will hold the,
7971 // result LSB since this saves us from having to copy it into
7972 // the result following AccAXLsh.
7974 // If the result is addressed indirectly, this is not a gain.
7975 if (AOP_NEEDSACC(result))
7979 _startLazyDPSEvaluation();
7980 if (AOP_TYPE(left) == AOP_DPTR2)
7983 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7984 // get LSB in DP2_RESULT_REG.
7985 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7986 assert(!strcmp(leftByte, DP2_RESULT_REG));
7990 // get LSB into DP2_RESULT_REG
7991 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7992 if (strcmp(leftByte, DP2_RESULT_REG))
7995 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7998 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7999 assert(strcmp(leftByte, DP2_RESULT_REG));
8002 _endLazyDPSEvaluation();
8003 *lsb = DP2_RESULT_REG;
8007 if (sameRegs (AOP (result), AOP (left)) &&
8008 ((offl + MSB16) == offr))
8010 /* don't crash result[offr] */
8011 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
8012 emitcode ("xch", "a,%s",
8013 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
8017 movLeft2Result (left, offl, result, offr, 0);
8018 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
8020 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
8021 assert(strcmp(*lsb,"a"));
8026 _storeAxResults(char *lsb,
8030 _startLazyDPSEvaluation();
8031 if (AOP_NEEDSACC(result))
8033 /* We have to explicitly update the result LSB.
8035 emitcode("xch","a,%s", lsb);
8036 aopPut(AOP(result), "a", offr);
8037 emitcode("mov","a,%s", lsb);
8039 if (getDataSize (result) > 1)
8041 aopPut (AOP (result), "a", offr + MSB16);
8043 _endLazyDPSEvaluation();
8046 /*-----------------------------------------------------------------*/
8047 /* shiftL2Left2Result - shift left two bytes from left to result */
8048 /*-----------------------------------------------------------------*/
8050 shiftL2Left2Result (operand * left, int offl,
8051 operand * result, int offr, int shCount)
8055 _loadLeftIntoAx(&lsb, left, result, offl, offr);
8057 AccAXLsh (lsb, shCount);
8059 _storeAxResults(lsb, result, offr);
8063 #ifdef BETTER_LITERAL_SHIFT
8064 /*-----------------------------------------------------------------*/
8065 /* shiftR2Left2Result - shift right two bytes from left to result */
8066 /*-----------------------------------------------------------------*/
8068 shiftR2Left2Result (operand * left, int offl,
8069 operand * result, int offr,
8070 int shCount, int sign)
8074 _loadLeftIntoAx(&lsb, left, result, offl, offr);
8076 /* a:x >> shCount (x = lsb(result)) */
8079 AccAXRshS(lsb, shCount);
8083 AccAXRsh(lsb, shCount);
8086 _storeAxResults(lsb, result, offr);
8090 /*-----------------------------------------------------------------*/
8091 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8092 /*-----------------------------------------------------------------*/
8094 shiftLLeftOrResult (operand * left, int offl,
8095 operand * result, int offr, int shCount)
8097 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8098 /* shift left accumulator */
8100 /* or with result */
8101 emitcode ("orl", "a,%s",
8102 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8103 /* back to result */
8104 aopPut (AOP (result), "a", offr);
8109 /*-----------------------------------------------------------------*/
8110 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8111 /*-----------------------------------------------------------------*/
8113 shiftRLeftOrResult (operand * left, int offl,
8114 operand * result, int offr, int shCount)
8116 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8117 /* shift right accumulator */
8119 /* or with result */
8120 emitcode ("orl", "a,%s",
8121 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8122 /* back to result */
8123 aopPut (AOP (result), "a", offr);
8127 #ifdef BETTER_LITERAL_SHIFT
8128 /*-----------------------------------------------------------------*/
8129 /* genlshOne - left shift a one byte quantity by known count */
8130 /*-----------------------------------------------------------------*/
8132 genlshOne (operand * result, operand * left, int shCount)
8134 D (emitcode (";", "genlshOne "););
8135 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8139 #ifdef BETTER_LITERAL_SHIFT
8140 /*-----------------------------------------------------------------*/
8141 /* genlshTwo - left shift two bytes by known amount != 0 */
8142 /*-----------------------------------------------------------------*/
8144 genlshTwo (operand * result, operand * left, int shCount)
8148 D (emitcode (";", "genlshTwo "););
8150 size = getDataSize (result);
8152 /* if shCount >= 8 */
8157 _startLazyDPSEvaluation();
8163 _endLazyDPSEvaluation();
8164 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8165 aopPut (AOP (result), zero, LSB);
8169 movLeft2Result (left, LSB, result, MSB16, 0);
8170 aopPut (AOP (result), zero, LSB);
8171 _endLazyDPSEvaluation();
8176 aopPut (AOP (result), zero, LSB);
8177 _endLazyDPSEvaluation();
8181 /* 1 <= shCount <= 7 */
8186 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8190 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8198 /*-----------------------------------------------------------------*/
8199 /* shiftLLong - shift left one long from left to result */
8200 /* offl = LSB or MSB16 */
8201 /*-----------------------------------------------------------------*/
8203 shiftLLong (operand * left, operand * result, int offr)
8206 int size = AOP_SIZE (result);
8208 if (size >= LSB + offr)
8210 l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8212 emitcode ("add", "a,acc");
8213 if (sameRegs (AOP (left), AOP (result)) &&
8214 size >= MSB16 + offr && offr != LSB)
8215 emitcode ("xch", "a,%s",
8216 aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8218 aopPut (AOP (result), "a", LSB + offr);
8221 if (size >= MSB16 + offr)
8223 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8225 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8227 emitcode ("rlc", "a");
8228 if (sameRegs (AOP (left), AOP (result)) &&
8229 size >= MSB24 + offr && offr != LSB)
8230 emitcode ("xch", "a,%s",
8231 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8233 aopPut (AOP (result), "a", MSB16 + offr);
8236 if (size >= MSB24 + offr)
8238 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8240 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8242 emitcode ("rlc", "a");
8243 if (sameRegs (AOP (left), AOP (result)) &&
8244 size >= MSB32 + offr && offr != LSB)
8245 emitcode ("xch", "a,%s",
8246 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8248 aopPut (AOP (result), "a", MSB24 + offr);
8251 if (size > MSB32 + offr)
8253 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8255 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8257 emitcode ("rlc", "a");
8258 aopPut (AOP (result), "a", MSB32 + offr);
8261 aopPut (AOP (result), zero, LSB);
8267 /*-----------------------------------------------------------------*/
8268 /* genlshFour - shift four byte by a known amount != 0 */
8269 /*-----------------------------------------------------------------*/
8271 genlshFour (operand * result, operand * left, int shCount)
8275 D (emitcode (";", "genlshFour ");
8278 size = AOP_SIZE (result);
8280 /* if shifting more that 3 bytes */
8285 /* lowest order of left goes to the highest
8286 order of the destination */
8287 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8289 movLeft2Result (left, LSB, result, MSB32, 0);
8290 aopPut (AOP (result), zero, LSB);
8291 aopPut (AOP (result), zero, MSB16);
8292 aopPut (AOP (result), zero, MSB24);
8296 /* more than two bytes */
8297 else if (shCount >= 16)
8299 /* lower order two bytes goes to higher order two bytes */
8301 /* if some more remaining */
8303 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8306 movLeft2Result (left, MSB16, result, MSB32, 0);
8307 movLeft2Result (left, LSB, result, MSB24, 0);
8309 aopPut (AOP (result), zero, MSB16);
8310 aopPut (AOP (result), zero, LSB);
8314 /* if more than 1 byte */
8315 else if (shCount >= 8)
8317 /* lower order three bytes goes to higher order three bytes */
8322 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8324 movLeft2Result (left, LSB, result, MSB16, 0);
8330 movLeft2Result (left, MSB24, result, MSB32, 0);
8331 movLeft2Result (left, MSB16, result, MSB24, 0);
8332 movLeft2Result (left, LSB, result, MSB16, 0);
8333 aopPut (AOP (result), zero, LSB);
8335 else if (shCount == 1)
8336 shiftLLong (left, result, MSB16);
8339 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8340 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8341 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8342 aopPut (AOP (result), zero, LSB);
8347 /* 1 <= shCount <= 7 */
8348 else if (shCount <= 2)
8350 shiftLLong (left, result, LSB);
8352 shiftLLong (result, result, LSB);
8354 /* 3 <= shCount <= 7, optimize */
8357 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8358 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8359 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8364 #ifdef BETTER_LITERAL_SHIFT
8365 /*-----------------------------------------------------------------*/
8366 /* genLeftShiftLiteral - left shifting by known count */
8367 /*-----------------------------------------------------------------*/
8369 genLeftShiftLiteral (operand * left,
8374 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8377 size = getSize (operandType (result));
8379 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8381 /* We only handle certain easy cases so far. */
8383 && (shCount < (size * 8))
8387 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8391 freeAsmop (right, NULL, ic, TRUE);
8393 aopOp(left, ic, FALSE, FALSE);
8394 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8397 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8399 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8400 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8402 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8405 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8407 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8408 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8410 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8416 emitcode ("; shift left ", "result %d, left %d", size,
8420 /* I suppose that the left size >= result size */
8423 _startLazyDPSEvaluation();
8426 movLeft2Result (left, size, result, size, 0);
8428 _endLazyDPSEvaluation();
8430 else if (shCount >= (size * 8))
8432 _startLazyDPSEvaluation();
8435 aopPut (AOP (result), zero, size);
8437 _endLazyDPSEvaluation();
8444 genlshOne (result, left, shCount);
8448 genlshTwo (result, left, shCount);
8452 genlshFour (result, left, shCount);
8456 fprintf(stderr, "*** ack! mystery literal shift!\n");
8460 freeAsmop (left, NULL, ic, TRUE);
8461 freeAsmop (result, NULL, ic, TRUE);
8466 /*-----------------------------------------------------------------*/
8467 /* genLeftShift - generates code for left shifting */
8468 /*-----------------------------------------------------------------*/
8470 genLeftShift (iCode * ic)
8472 operand *left, *right, *result;
8475 symbol *tlbl, *tlbl1;
8477 D (emitcode (";", "genLeftShift "););
8479 right = IC_RIGHT (ic);
8480 left = IC_LEFT (ic);
8481 result = IC_RESULT (ic);
8483 aopOp (right, ic, FALSE, FALSE);
8486 #ifdef BETTER_LITERAL_SHIFT
8487 /* if the shift count is known then do it
8488 as efficiently as possible */
8489 if (AOP_TYPE (right) == AOP_LIT)
8491 if (genLeftShiftLiteral (left, right, result, ic))
8498 /* shift count is unknown then we have to form
8499 a loop get the loop count in B : Note: we take
8500 only the lower order byte since shifting
8501 more that 32 bits make no sense anyway, ( the
8502 largest size of an object can be only 32 bits ) */
8504 if (AOP_TYPE (right) == AOP_LIT)
8506 /* Really should be handled by genLeftShiftLiteral,
8507 * but since I'm too lazy to fix that today, at least we can make
8508 * some small improvement.
8510 emitcode("mov", "b,#!constbyte",
8511 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8515 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8516 emitcode ("inc", "b");
8518 freeAsmop (right, NULL, ic, TRUE);
8519 aopOp (left, ic, FALSE, FALSE);
8520 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8522 /* now move the left to the result if they are not the
8524 if (!sameRegs (AOP (left), AOP (result)) &&
8525 AOP_SIZE (result) > 1)
8528 size = AOP_SIZE (result);
8530 _startLazyDPSEvaluation ();
8533 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8534 if (*l == '@' && (IS_AOP_PREG (result)))
8537 emitcode ("mov", "a,%s", l);
8538 aopPut (AOP (result), "a", offset);
8541 aopPut (AOP (result), l, offset);
8544 _endLazyDPSEvaluation ();
8547 tlbl = newiTempLabel (NULL);
8548 size = AOP_SIZE (result);
8550 tlbl1 = newiTempLabel (NULL);
8552 /* if it is only one byte then */
8555 symbol *tlbl1 = newiTempLabel (NULL);
8557 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8558 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8559 emitcode ("", "!tlabeldef", tlbl->key + 100);
8560 emitcode ("add", "a,acc");
8561 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8562 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8563 aopPut (AOP (result), "a", 0);
8567 reAdjustPreg (AOP (result));
8569 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8570 emitcode ("", "!tlabeldef", tlbl->key + 100);
8571 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8572 emitcode ("add", "a,acc");
8573 aopPut (AOP (result), "a", offset++);
8574 _startLazyDPSEvaluation ();
8577 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8578 emitcode ("rlc", "a");
8579 aopPut (AOP (result), "a", offset++);
8581 _endLazyDPSEvaluation ();
8582 reAdjustPreg (AOP (result));
8584 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8585 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8587 freeAsmop (left, NULL, ic, TRUE);
8588 freeAsmop (result, NULL, ic, TRUE);
8591 #ifdef BETTER_LITERAL_SHIFT
8592 /*-----------------------------------------------------------------*/
8593 /* genrshOne - right shift a one byte quantity by known count */
8594 /*-----------------------------------------------------------------*/
8596 genrshOne (operand * result, operand * left,
8597 int shCount, int sign)
8599 D (emitcode (";", "genrshOne"););
8600 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8604 #ifdef BETTER_LITERAL_SHIFT
8605 /*-----------------------------------------------------------------*/
8606 /* genrshTwo - right shift two bytes by known amount != 0 */
8607 /*-----------------------------------------------------------------*/
8609 genrshTwo (operand * result, operand * left,
8610 int shCount, int sign)
8612 D (emitcode (";", "genrshTwo"););
8614 /* if shCount >= 8 */
8618 _startLazyDPSEvaluation();
8621 shiftR1Left2Result (left, MSB16, result, LSB,
8626 movLeft2Result (left, MSB16, result, LSB, sign);
8628 addSign (result, MSB16, sign);
8629 _endLazyDPSEvaluation();
8632 /* 1 <= shCount <= 7 */
8635 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8640 /*-----------------------------------------------------------------*/
8641 /* shiftRLong - shift right one long from left to result */
8642 /* offl = LSB or MSB16 */
8643 /*-----------------------------------------------------------------*/
8645 shiftRLong (operand * left, int offl,
8646 operand * result, int sign)
8648 int isSameRegs=sameRegs(AOP(left),AOP(result));
8650 if (isSameRegs && offl>1) {
8651 // we are in big trouble, but this shouldn't happen
8652 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8655 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8660 emitcode ("rlc", "a");
8661 emitcode ("subb", "a,acc");
8662 emitcode ("xch", "a,%s",
8663 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
8665 aopPut (AOP(result), zero, MSB32);
8670 emitcode ("clr", "c");
8672 emitcode ("mov", "c,acc.7");
8675 emitcode ("rrc", "a");
8677 if (isSameRegs && offl==MSB16) {
8679 "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
8681 aopPut (AOP (result), "a", MSB32);
8682 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8685 emitcode ("rrc", "a");
8686 if (isSameRegs && offl==1) {
8687 emitcode ("xch", "a,%s",
8688 aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
8690 aopPut (AOP (result), "a", MSB24);
8691 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
8693 emitcode ("rrc", "a");
8694 aopPut (AOP (result), "a", MSB16 - offl);
8698 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
8699 emitcode ("rrc", "a");
8700 aopPut (AOP (result), "a", LSB);
8704 /*-----------------------------------------------------------------*/
8705 /* genrshFour - shift four byte by a known amount != 0 */
8706 /*-----------------------------------------------------------------*/
8708 genrshFour (operand * result, operand * left,
8709 int shCount, int sign)
8711 D (emitcode (";", "genrshFour"););
8713 /* if shifting more that 3 bytes */
8717 _startLazyDPSEvaluation();
8719 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8721 movLeft2Result (left, MSB32, result, LSB, sign);
8722 addSign (result, MSB16, sign);
8723 _endLazyDPSEvaluation();
8725 else if (shCount >= 16)
8728 _startLazyDPSEvaluation();
8730 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8733 movLeft2Result (left, MSB24, result, LSB, 0);
8734 movLeft2Result (left, MSB32, result, MSB16, sign);
8736 addSign (result, MSB24, sign);
8737 _endLazyDPSEvaluation();
8739 else if (shCount >= 8)
8742 _startLazyDPSEvaluation();
8745 shiftRLong (left, MSB16, result, sign);
8747 else if (shCount == 0)
8749 movLeft2Result (left, MSB16, result, LSB, 0);
8750 movLeft2Result (left, MSB24, result, MSB16, 0);
8751 movLeft2Result (left, MSB32, result, MSB24, sign);
8752 addSign (result, MSB32, sign);
8756 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8757 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8758 /* the last shift is signed */
8759 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8760 addSign (result, MSB32, sign);
8762 _endLazyDPSEvaluation();
8766 /* 1 <= shCount <= 7 */
8769 shiftRLong (left, LSB, result, sign);
8771 shiftRLong (result, LSB, result, sign);
8775 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8776 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8777 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8782 #ifdef BETTER_LITERAL_SHIFT
8783 /*-----------------------------------------------------------------*/
8784 /* genRightShiftLiteral - right shifting by known count */
8785 /*-----------------------------------------------------------------*/
8787 genRightShiftLiteral (operand * left,
8793 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8796 size = getSize (operandType (result));
8798 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8800 /* We only handle certain easy cases so far. */
8802 && (shCount < (size * 8))
8807 D(emitcode (";", "genRightShiftLiteral wimping out"););
8811 freeAsmop (right, NULL, ic, TRUE);
8813 aopOp (left, ic, FALSE, FALSE);
8814 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8817 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8821 /* test the LEFT size !!! */
8823 /* I suppose that the left size >= result size */
8826 size = getDataSize (result);
8827 _startLazyDPSEvaluation();
8830 movLeft2Result (left, size, result, size, 0);
8832 _endLazyDPSEvaluation();
8834 else if (shCount >= (size * 8))
8838 /* get sign in acc.7 */
8839 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8841 addSign (result, LSB, sign);
8848 genrshOne (result, left, shCount, sign);
8852 genrshTwo (result, left, shCount, sign);
8856 genrshFour (result, left, shCount, sign);
8863 freeAsmop (left, NULL, ic, TRUE);
8864 freeAsmop (result, NULL, ic, TRUE);
8870 /*-----------------------------------------------------------------*/
8871 /* genSignedRightShift - right shift of signed number */
8872 /*-----------------------------------------------------------------*/
8874 genSignedRightShift (iCode * ic)
8876 operand *right, *left, *result;
8879 symbol *tlbl, *tlbl1;
8881 D (emitcode (";", "genSignedRightShift "););
8883 /* we do it the hard way put the shift count in b
8884 and loop thru preserving the sign */
8886 right = IC_RIGHT (ic);
8887 left = IC_LEFT (ic);
8888 result = IC_RESULT (ic);
8890 aopOp (right, ic, FALSE, FALSE);
8892 #ifdef BETTER_LITERAL_SHIFT
8893 if (AOP_TYPE (right) == AOP_LIT)
8895 if (genRightShiftLiteral (left, right, result, ic, 1))
8901 /* shift count is unknown then we have to form
8902 a loop get the loop count in B : Note: we take
8903 only the lower order byte since shifting
8904 more that 32 bits make no sense anyway, ( the
8905 largest size of an object can be only 32 bits ) */
8907 if (AOP_TYPE (right) == AOP_LIT)
8909 /* Really should be handled by genRightShiftLiteral,
8910 * but since I'm too lazy to fix that today, at least we can make
8911 * some small improvement.
8913 emitcode("mov", "b,#!constbyte",
8914 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8918 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8919 emitcode ("inc", "b");
8921 freeAsmop (right, NULL, ic, TRUE);
8922 aopOp (left, ic, FALSE, FALSE);
8923 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8925 /* now move the left to the result if they are not the
8927 if (!sameRegs (AOP (left), AOP (result)) &&
8928 AOP_SIZE (result) > 1)
8931 size = AOP_SIZE (result);
8933 _startLazyDPSEvaluation ();
8936 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8937 if (*l == '@' && IS_AOP_PREG (result))
8940 emitcode ("mov", "a,%s", l);
8941 aopPut (AOP (result), "a", offset);
8944 aopPut (AOP (result), l, offset);
8947 _endLazyDPSEvaluation ();
8950 /* mov the highest order bit to OVR */
8951 tlbl = newiTempLabel (NULL);
8952 tlbl1 = newiTempLabel (NULL);
8954 size = AOP_SIZE (result);
8956 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8957 emitcode ("rlc", "a");
8958 emitcode ("mov", "ov,c");
8959 /* if it is only one byte then */
8962 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8963 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8964 emitcode ("", "!tlabeldef", tlbl->key + 100);
8965 emitcode ("mov", "c,ov");
8966 emitcode ("rrc", "a");
8967 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8968 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8969 aopPut (AOP (result), "a", 0);
8973 reAdjustPreg (AOP (result));
8974 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8975 emitcode ("", "!tlabeldef", tlbl->key + 100);
8976 emitcode ("mov", "c,ov");
8977 _startLazyDPSEvaluation ();
8980 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8981 emitcode ("rrc", "a");
8982 aopPut (AOP (result), "a", offset--);
8984 _endLazyDPSEvaluation ();
8985 reAdjustPreg (AOP (result));
8986 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8987 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8990 freeAsmop (left, NULL, ic, TRUE);
8991 freeAsmop (result, NULL, ic, TRUE);
8994 /*-----------------------------------------------------------------*/
8995 /* genRightShift - generate code for right shifting */
8996 /*-----------------------------------------------------------------*/
8998 genRightShift (iCode * ic)
9000 operand *right, *left, *result;
9004 symbol *tlbl, *tlbl1;
9006 D (emitcode (";", "genRightShift "););
9008 /* if signed then we do it the hard way preserve the
9009 sign bit moving it inwards */
9010 letype = getSpec (operandType (IC_LEFT (ic)));
9012 if (!SPEC_USIGN (letype))
9014 genSignedRightShift (ic);
9018 /* signed & unsigned types are treated the same : i.e. the
9019 signed is NOT propagated inwards : quoting from the
9020 ANSI - standard : "for E1 >> E2, is equivalent to division
9021 by 2**E2 if unsigned or if it has a non-negative value,
9022 otherwise the result is implementation defined ", MY definition
9023 is that the sign does not get propagated */
9025 right = IC_RIGHT (ic);
9026 left = IC_LEFT (ic);
9027 result = IC_RESULT (ic);
9029 aopOp (right, ic, FALSE, FALSE);
9031 #ifdef BETTER_LITERAL_SHIFT
9032 /* if the shift count is known then do it
9033 as efficiently as possible */
9034 if (AOP_TYPE (right) == AOP_LIT)
9036 if (genRightShiftLiteral (left, right, result, ic, 0))
9043 /* shift count is unknown then we have to form
9044 a loop get the loop count in B : Note: we take
9045 only the lower order byte since shifting
9046 more that 32 bits make no sense anyway, ( the
9047 largest size of an object can be only 32 bits ) */
9049 if (AOP_TYPE (right) == AOP_LIT)
9051 /* Really should be handled by genRightShiftLiteral,
9052 * but since I'm too lazy to fix that today, at least we can make
9053 * some small improvement.
9055 emitcode("mov", "b,#!constbyte",
9056 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9060 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9061 emitcode ("inc", "b");
9063 freeAsmop (right, NULL, ic, TRUE);
9064 aopOp (left, ic, FALSE, FALSE);
9065 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9067 /* now move the left to the result if they are not the
9069 if (!sameRegs (AOP (left), AOP (result)) &&
9070 AOP_SIZE (result) > 1)
9073 size = AOP_SIZE (result);
9075 _startLazyDPSEvaluation ();
9078 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9079 if (*l == '@' && IS_AOP_PREG (result))
9082 emitcode ("mov", "a,%s", l);
9083 aopPut (AOP (result), "a", offset);
9086 aopPut (AOP (result), l, offset);
9089 _endLazyDPSEvaluation ();
9092 tlbl = newiTempLabel (NULL);
9093 tlbl1 = newiTempLabel (NULL);
9094 size = AOP_SIZE (result);
9097 /* if it is only one byte then */
9100 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9101 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9102 emitcode ("", "!tlabeldef", tlbl->key + 100);
9104 emitcode ("rrc", "a");
9105 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9106 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9107 aopPut (AOP (result), "a", 0);
9111 reAdjustPreg (AOP (result));
9112 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9113 emitcode ("", "!tlabeldef", tlbl->key + 100);
9115 _startLazyDPSEvaluation ();
9118 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9119 emitcode ("rrc", "a");
9120 aopPut (AOP (result), "a", offset--);
9122 _endLazyDPSEvaluation ();
9123 reAdjustPreg (AOP (result));
9125 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9126 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9129 freeAsmop (left, NULL, ic, TRUE);
9130 freeAsmop (result, NULL, ic, TRUE);
9134 /*-----------------------------------------------------------------*/
9135 /* emitPtrByteGet - emits code to get a byte into A through a */
9136 /* pointer register (R0, R1, or DPTR). The */
9137 /* original value of A can be preserved in B. */
9138 /*-----------------------------------------------------------------*/
9140 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9147 emitcode ("mov", "b,a");
9148 emitcode ("mov", "a,@%s", rname);
9153 emitcode ("mov", "b,a");
9154 emitcode ("movx", "a,@%s", rname);
9159 emitcode ("mov", "b,a");
9160 emitcode ("movx", "a,@dptr");
9165 emitcode ("mov", "b,a");
9166 emitcode ("clr", "a");
9167 emitcode ("movc", "a,@a+dptr");
9173 emitcode ("push", "b");
9174 emitcode ("push", "acc");
9176 emitcode ("lcall", "__gptrget");
9178 emitcode ("pop", "b");
9183 /*-----------------------------------------------------------------*/
9184 /* emitPtrByteSet - emits code to set a byte from src through a */
9185 /* pointer register (R0, R1, or DPTR). */
9186 /*-----------------------------------------------------------------*/
9188 emitPtrByteSet (char *rname, int p_type, char *src)
9197 emitcode ("mov", "@%s,a", rname);
9200 emitcode ("mov", "@%s,%s", rname, src);
9205 emitcode ("movx", "@%s,a", rname);
9210 emitcode ("movx", "@dptr,a");
9215 emitcode ("lcall", "__gptrput");
9220 /*-----------------------------------------------------------------*/
9221 /* genUnpackBits - generates code for unpacking bits */
9222 /*-----------------------------------------------------------------*/
9224 genUnpackBits (operand * result, char *rname, int ptype)
9226 int offset = 0; /* result byte offset */
9227 int rsize; /* result size */
9228 int rlen = 0; /* remaining bitfield length */
9229 sym_link *etype; /* bitfield type information */
9230 int blen; /* bitfield length */
9231 int bstr; /* bitfield starting bit within byte */
9233 D(emitcode ("; genUnpackBits",""));
9235 etype = getSpec (operandType (result));
9236 rsize = getSize (operandType (result));
9237 blen = SPEC_BLEN (etype);
9238 bstr = SPEC_BSTR (etype);
9240 /* If the bitfield length is less than a byte */
9243 emitPtrByteGet (rname, ptype, FALSE);
9245 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9246 aopPut (AOP (result), "a", offset++);
9250 /* Bit field did not fit in a byte. Copy all
9251 but the partial byte at the end. */
9252 for (rlen=blen;rlen>=8;rlen-=8)
9254 emitPtrByteGet (rname, ptype, FALSE);
9255 aopPut (AOP (result), "a", offset++);
9257 emitcode ("inc", "%s", rname);
9260 /* Handle the partial byte at the end */
9263 emitPtrByteGet (rname, ptype, FALSE);
9264 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9265 aopPut (AOP (result), "a", offset++);
9273 aopPut (AOP (result), zero, offset++);
9278 /*-----------------------------------------------------------------*/
9279 /* genDataPointerGet - generates code when ptr offset is known */
9280 /*-----------------------------------------------------------------*/
9282 genDataPointerGet (operand * left,
9288 int size, offset = 0;
9289 aopOp (result, ic, TRUE, FALSE);
9291 /* get the string representation of the name */
9292 l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9293 size = AOP_SIZE (result);
9294 _startLazyDPSEvaluation ();
9299 SNPRINTF (buff, sizeof(buff),
9300 "(%s + %d)", l + 1, offset);
9304 SNPRINTF (buff, sizeof(buff),
9307 aopPut (AOP (result), buff, offset++);
9309 _endLazyDPSEvaluation ();
9311 freeAsmop (left, NULL, ic, TRUE);
9312 freeAsmop (result, NULL, ic, TRUE);
9315 /*-----------------------------------------------------------------*/
9316 /* genNearPointerGet - emitcode for near pointer fetch */
9317 /*-----------------------------------------------------------------*/
9319 genNearPointerGet (operand * left,
9327 sym_link *rtype, *retype, *letype;
9328 sym_link *ltype = operandType (left);
9331 rtype = operandType (result);
9332 retype = getSpec (rtype);
9333 letype = getSpec (ltype);
9335 aopOp (left, ic, FALSE, FALSE);
9337 /* if left is rematerialisable and
9338 result is not bit variable type and
9339 the left is pointer to data space i.e
9340 lower 128 bytes of space */
9341 if (AOP_TYPE (left) == AOP_IMMD &&
9342 !IS_BITVAR (retype) &&
9343 !IS_BITVAR (letype) &&
9344 DCL_TYPE (ltype) == POINTER)
9346 genDataPointerGet (left, result, ic);
9350 /* if the value is already in a pointer register
9351 then don't need anything more */
9352 if (!AOP_INPREG (AOP (left)))
9354 /* otherwise get a free pointer register */
9356 preg = getFreePtr (ic, &aop, FALSE);
9357 emitcode ("mov", "%s,%s",
9359 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9363 rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9365 freeAsmop (left, NULL, ic, TRUE);
9366 aopOp (result, ic, FALSE, FALSE);
9368 /* if bitfield then unpack the bits */
9369 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9370 genUnpackBits (result, rname, POINTER);
9373 /* we have can just get the values */
9374 int size = AOP_SIZE (result);
9379 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9382 emitcode ("mov", "a,@%s", rname);
9383 aopPut (AOP (result), "a", offset);
9387 SNPRINTF (buff, sizeof(buff), "@%s", rname);
9388 aopPut (AOP (result), buff, offset);
9393 emitcode ("inc", "%s", rname);
9398 /* now some housekeeping stuff */
9401 /* we had to allocate for this iCode */
9402 if (pi) { /* post increment present */
9403 aopPut(AOP ( left ),rname,0);
9405 freeAsmop (NULL, aop, ic, TRUE);
9409 /* we did not allocate which means left
9410 already in a pointer register, then
9411 if size > 0 && this could be used again
9412 we have to point it back to where it
9414 if (AOP_SIZE (result) > 1 &&
9415 !OP_SYMBOL (left)->remat &&
9416 (OP_SYMBOL (left)->liveTo > ic->seq ||
9420 int size = AOP_SIZE (result) - 1;
9422 emitcode ("dec", "%s", rname);
9427 freeAsmop (result, NULL, ic, TRUE);
9428 if (pi) pi->generated = 1;
9431 /*-----------------------------------------------------------------*/
9432 /* genPagedPointerGet - emitcode for paged pointer fetch */
9433 /*-----------------------------------------------------------------*/
9435 genPagedPointerGet (operand * left,
9443 sym_link *rtype, *retype, *letype;
9445 rtype = operandType (result);
9446 retype = getSpec (rtype);
9447 letype = getSpec (operandType (left));
9448 aopOp (left, ic, FALSE, FALSE);
9450 /* if the value is already in a pointer register
9451 then don't need anything more */
9452 if (!AOP_INPREG (AOP (left)))
9454 /* otherwise get a free pointer register */
9456 preg = getFreePtr (ic, &aop, FALSE);
9457 emitcode ("mov", "%s,%s",
9459 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9463 rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9465 freeAsmop (left, NULL, ic, TRUE);
9466 aopOp (result, ic, FALSE, FALSE);
9468 /* if bitfield then unpack the bits */
9469 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9470 genUnpackBits (result, rname, PPOINTER);
9473 /* we have can just get the values */
9474 int size = AOP_SIZE (result);
9480 emitcode ("movx", "a,@%s", rname);
9481 aopPut (AOP (result), "a", offset);
9486 emitcode ("inc", "%s", rname);
9490 /* now some housekeeping stuff */
9493 /* we had to allocate for this iCode */
9494 if (pi) aopPut ( AOP (left), rname, 0);
9495 freeAsmop (NULL, aop, ic, TRUE);
9499 /* we did not allocate which means left
9500 already in a pointer register, then
9501 if size > 0 && this could be used again
9502 we have to point it back to where it
9504 if (AOP_SIZE (result) > 1 &&
9505 !OP_SYMBOL (left)->remat &&
9506 (OP_SYMBOL (left)->liveTo > ic->seq ||
9510 int size = AOP_SIZE (result) - 1;
9512 emitcode ("dec", "%s", rname);
9517 freeAsmop (result, NULL, ic, TRUE);
9518 if (pi) pi->generated = 1;
9521 /*-----------------------------------------------------------------*/
9522 /* genFarPointerGet - gget value from far space */
9523 /*-----------------------------------------------------------------*/
9525 genFarPointerGet (operand * left,
9526 operand * result, iCode * ic, iCode *pi)
9528 int size, offset, dopi=1;
9529 sym_link *retype = getSpec (operandType (result));
9530 sym_link *letype = getSpec (operandType (left));
9531 D (emitcode (";", "genFarPointerGet"););
9533 aopOp (left, ic, FALSE, FALSE);
9535 /* if the operand is already in dptr
9536 then we do nothing else we move the value to dptr */
9537 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9539 /* if this is remateriazable */
9540 if (AOP_TYPE (left) == AOP_IMMD)
9542 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9546 /* we need to get it byte by byte */
9547 _startLazyDPSEvaluation ();
9548 if (AOP_TYPE (left) != AOP_DPTR)
9550 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9551 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9552 if (options.model == MODEL_FLAT24)
9553 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9557 /* We need to generate a load to DPTR indirect through DPTR. */
9558 D (emitcode (";", "genFarPointerGet -- indirection special case."););
9559 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9560 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9561 if (options.model == MODEL_FLAT24)
9562 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9563 emitcode ("pop", "dph");
9564 emitcode ("pop", "dpl");
9567 _endLazyDPSEvaluation ();
9570 /* so dptr know contains the address */
9571 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9573 /* if bit then unpack */
9574 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9575 if (AOP_INDPTRn(left)) {
9576 genSetDPTR(AOP(left)->aopu.dptr);
9578 genUnpackBits (result, "dptr", FPOINTER);
9579 if (AOP_INDPTRn(left)) {
9584 size = AOP_SIZE (result);
9587 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9589 genSetDPTR(AOP(left)->aopu.dptr);
9590 emitcode ("movx", "a,@dptr");
9591 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9592 emitcode ("inc", "dptr");
9594 aopPut (AOP (result), "a", offset++);
9597 _startLazyDPSEvaluation ();
9599 if (AOP_INDPTRn(left)) {
9600 genSetDPTR(AOP(left)->aopu.dptr);
9606 emitcode ("movx", "a,@dptr");
9607 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9608 emitcode ("inc", "dptr");
9610 aopPut (AOP (result), "a", offset++);
9612 _endLazyDPSEvaluation ();
9615 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9616 if (!AOP_INDPTRn(left)) {
9617 _startLazyDPSEvaluation ();
9618 aopPut ( AOP (left), "dpl", 0);
9619 aopPut ( AOP (left), "dph", 1);
9620 if (options.model == MODEL_FLAT24)
9621 aopPut ( AOP (left), "dpx", 2);
9622 _endLazyDPSEvaluation ();
9625 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
9626 AOP_SIZE(result) > 1 &&
9628 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9630 size = AOP_SIZE (result) - 1;
9631 if (AOP_INDPTRn(left)) {
9632 genSetDPTR(AOP(left)->aopu.dptr);
9634 while (size--) emitcode ("lcall","__decdptr");
9635 if (AOP_INDPTRn(left)) {
9640 freeAsmop (left, NULL, ic, TRUE);
9641 freeAsmop (result, NULL, ic, TRUE);
9644 /*-----------------------------------------------------------------*/
9645 /* genCodePointerGet - get value from code space */
9646 /*-----------------------------------------------------------------*/
9648 genCodePointerGet (operand * left,
9649 operand * result, iCode * ic, iCode *pi)
9651 int size, offset, dopi=1;
9652 sym_link *retype = getSpec (operandType (result));
9654 aopOp (left, ic, FALSE, FALSE);
9656 /* if the operand is already in dptr
9657 then we do nothing else we move the value to dptr */
9658 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9660 /* if this is remateriazable */
9661 if (AOP_TYPE (left) == AOP_IMMD)
9663 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9666 { /* we need to get it byte by byte */
9667 _startLazyDPSEvaluation ();
9668 if (AOP_TYPE (left) != AOP_DPTR)
9670 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9671 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9672 if (options.model == MODEL_FLAT24)
9673 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9677 /* We need to generate a load to DPTR indirect through DPTR. */
9678 D (emitcode (";", "gencodePointerGet -- indirection special case."););
9679 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9680 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9681 if (options.model == MODEL_FLAT24)
9682 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9683 emitcode ("pop", "dph");
9684 emitcode ("pop", "dpl");
9687 _endLazyDPSEvaluation ();
9690 /* so dptr know contains the address */
9691 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9693 /* if bit then unpack */
9694 if (IS_BITVAR (retype)) {
9695 if (AOP_INDPTRn(left)) {
9696 genSetDPTR(AOP(left)->aopu.dptr);
9698 genUnpackBits (result, "dptr", CPOINTER);
9699 if (AOP_INDPTRn(left)) {
9704 size = AOP_SIZE (result);
9706 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9708 genSetDPTR(AOP(left)->aopu.dptr);
9709 emitcode ("clr", "a");
9710 emitcode ("movc", "a,@a+dptr");
9711 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9712 emitcode ("inc", "dptr");
9714 aopPut (AOP (result), "a", offset++);
9717 _startLazyDPSEvaluation ();
9720 if (AOP_INDPTRn(left)) {
9721 genSetDPTR(AOP(left)->aopu.dptr);
9727 emitcode ("clr", "a");
9728 emitcode ("movc", "a,@a+dptr");
9729 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9730 emitcode ("inc", "dptr");
9731 aopPut (AOP (result), "a", offset++);
9733 _endLazyDPSEvaluation ();
9736 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9737 if (!AOP_INDPTRn(left)) {
9738 _startLazyDPSEvaluation ();
9740 aopPut ( AOP (left), "dpl", 0);
9741 aopPut ( AOP (left), "dph", 1);
9742 if (options.model == MODEL_FLAT24)
9743 aopPut ( AOP (left), "dpx", 2);
9745 _endLazyDPSEvaluation ();
9748 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9749 AOP_SIZE(result) > 1 &&
9750 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9752 size = AOP_SIZE (result) - 1;
9753 if (AOP_INDPTRn(left)) {
9754 genSetDPTR(AOP(left)->aopu.dptr);
9756 while (size--) emitcode ("lcall","__decdptr");
9757 if (AOP_INDPTRn(left)) {
9762 freeAsmop (left, NULL, ic, TRUE);
9763 freeAsmop (result, NULL, ic, TRUE);
9766 /*-----------------------------------------------------------------*/
9767 /* genGenPointerGet - gget value from generic pointer space */
9768 /*-----------------------------------------------------------------*/
9770 genGenPointerGet (operand * left,
9771 operand * result, iCode * ic, iCode * pi)
9774 sym_link *retype = getSpec (operandType (result));
9775 sym_link *letype = getSpec (operandType (left));
9777 D (emitcode (";", "genGenPointerGet "); );
9779 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9781 /* if the operand is already in dptr
9782 then we do nothing else we move the value to dptr */
9783 if (AOP_TYPE (left) != AOP_STR)
9785 /* if this is remateriazable */
9786 if (AOP_TYPE (left) == AOP_IMMD)
9788 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9789 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9791 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9795 emitcode ("mov", "b,#%d", pointerCode (retype));
9799 { /* we need to get it byte by byte */
9800 _startLazyDPSEvaluation ();
9801 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9802 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9803 if (options.model == MODEL_FLAT24) {
9804 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9805 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9807 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9809 _endLazyDPSEvaluation ();
9813 /* so dptr-b now contains the address */
9815 aopOp (result, ic, FALSE, TRUE);
9818 /* if bit then unpack */
9819 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9821 genUnpackBits (result, "dptr", GPOINTER);
9825 size = AOP_SIZE (result);
9832 // Get two bytes at a time, results in _AP & A.
9833 // dptr will be incremented ONCE by __gptrgetWord.
9835 // Note: any change here must be coordinated
9836 // with the implementation of __gptrgetWord
9837 // in device/lib/_gptrget.c
9838 emitcode ("lcall", "__gptrgetWord");
9839 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9840 aopPut (AOP (result), "a", offset++);
9845 // Only one byte to get.
9846 emitcode ("lcall", "__gptrget");
9847 aopPut (AOP (result), "a", offset++);
9850 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9852 emitcode ("inc", "dptr");
9857 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9858 _startLazyDPSEvaluation ();
9860 aopPut ( AOP (left), "dpl", 0);
9861 aopPut ( AOP (left), "dph", 1);
9862 if (options.model == MODEL_FLAT24) {
9863 aopPut ( AOP (left), "dpx", 2);
9864 aopPut ( AOP (left), "b", 3);
9865 } else aopPut ( AOP (left), "b", 2);
9867 _endLazyDPSEvaluation ();
9870 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9871 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9873 size = AOP_SIZE (result) - 1;
9874 while (size--) emitcode ("lcall","__decdptr");
9877 freeAsmop (left, NULL, ic, TRUE);
9878 freeAsmop (result, NULL, ic, TRUE);
9881 /*-----------------------------------------------------------------*/
9882 /* genPointerGet - generate code for pointer get */
9883 /*-----------------------------------------------------------------*/
9885 genPointerGet (iCode * ic, iCode *pi)
9887 operand *left, *result;
9888 sym_link *type, *etype;
9891 D (emitcode (";", "genPointerGet ");
9894 left = IC_LEFT (ic);
9895 result = IC_RESULT (ic);
9897 /* depending on the type of pointer we need to
9898 move it to the correct pointer register */
9899 type = operandType (left);
9900 etype = getSpec (type);
9901 /* if left is of type of pointer then it is simple */
9902 if (IS_PTR (type) && !IS_FUNC (type->next))
9903 p_type = DCL_TYPE (type);
9906 /* we have to go by the storage class */
9907 p_type = PTR_TYPE (SPEC_OCLS (etype));
9909 /* special case when cast remat */
9910 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9911 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9912 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9913 type = operandType (left);
9914 p_type = DCL_TYPE (type);
9916 /* now that we have the pointer type we assign
9917 the pointer values */
9923 genNearPointerGet (left, result, ic, pi);
9927 genPagedPointerGet (left, result, ic, pi);
9931 genFarPointerGet (left, result, ic, pi);
9935 genCodePointerGet (left, result, ic, pi);
9939 genGenPointerGet (left, result, ic, pi);
9945 /*-----------------------------------------------------------------*/
9946 /* genPackBits - generates code for packed bit storage */
9947 /*-----------------------------------------------------------------*/
9949 genPackBits (sym_link * etype,
9951 char *rname, int p_type)
9953 int offset = 0; /* source byte offset */
9954 int rlen = 0; /* remaining bitfield length */
9955 int blen; /* bitfield length */
9956 int bstr; /* bitfield starting bit within byte */
9957 int litval; /* source literal value (if AOP_LIT) */
9958 unsigned char mask; /* bitmask within current byte */
9960 D(emitcode ("; genPackBits",""));
9962 blen = SPEC_BLEN (etype);
9963 bstr = SPEC_BSTR (etype);
9965 /* If the bitfield length is less than a byte */
9968 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9969 (unsigned char) (0xFF >> (8 - bstr)));
9971 if (AOP_TYPE (right) == AOP_LIT)
9973 /* Case with a bitfield length <8 and literal source
9975 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9977 litval &= (~mask) & 0xff;
9978 emitPtrByteGet (rname, p_type, FALSE);
9979 if ((mask|litval)!=0xff)
9980 emitcode ("anl","a,#!constbyte", mask);
9982 emitcode ("orl","a,#!constbyte", litval);
9986 if ((blen==1) && (p_type!=GPOINTER))
9988 /* Case with a bitfield length == 1 and no generic pointer
9990 if (AOP_TYPE (right) == AOP_CRY)
9991 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9994 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9995 emitcode ("rrc","a");
9997 emitPtrByteGet (rname, p_type, FALSE);
9998 emitcode ("mov","acc.%d,c",bstr);
10002 /* Case with a bitfield length < 8 and arbitrary source
10004 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10005 /* shift and mask source value */
10007 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10009 /* transfer A to B and get next byte */
10010 emitPtrByteGet (rname, p_type, TRUE);
10012 emitcode ("anl", "a,#!constbyte", mask);
10013 emitcode ("orl", "a,b");
10014 if (p_type == GPOINTER)
10015 emitcode ("pop", "b");
10019 emitPtrByteSet (rname, p_type, "a");
10023 /* Bit length is greater than 7 bits. In this case, copy */
10024 /* all except the partial byte at the end */
10025 for (rlen=blen;rlen>=8;rlen-=8)
10027 emitPtrByteSet (rname, p_type,
10028 aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
10030 emitcode ("inc", "%s", rname);
10033 /* If there was a partial byte at the end */
10036 mask = (((unsigned char) -1 << rlen) & 0xff);
10038 if (AOP_TYPE (right) == AOP_LIT)
10040 /* Case with partial byte and literal source
10042 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10043 litval >>= (blen-rlen);
10044 litval &= (~mask) & 0xff;
10045 emitPtrByteGet (rname, p_type, FALSE);
10046 if ((mask|litval)!=0xff)
10047 emitcode ("anl","a,#!constbyte", mask);
10049 emitcode ("orl","a,#!constbyte", litval);
10053 /* Case with partial byte and arbitrary source
10055 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10056 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10058 /* transfer A to B and get next byte */
10059 emitPtrByteGet (rname, p_type, TRUE);
10061 emitcode ("anl", "a,#!constbyte", mask);
10062 emitcode ("orl", "a,b");
10063 if (p_type == GPOINTER)
10064 emitcode ("pop", "b");
10066 emitPtrByteSet (rname, p_type, "a");
10072 /*-----------------------------------------------------------------*/
10073 /* genDataPointerSet - remat pointer to data space */
10074 /*-----------------------------------------------------------------*/
10076 genDataPointerSet (operand * right,
10080 int size, offset = 0;
10081 char *l, buff[256];
10083 aopOp (right, ic, FALSE, FALSE);
10085 l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
10086 size = AOP_SIZE (right);
10091 SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
10095 SNPRINTF (buff, sizeof(buff), "%s", l + 1);
10098 emitcode ("mov", "%s,%s", buff,
10099 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10102 freeAsmop (right, NULL, ic, TRUE);
10103 freeAsmop (result, NULL, ic, TRUE);
10106 /*-----------------------------------------------------------------*/
10107 /* genNearPointerSet - emitcode for near pointer put */
10108 /*-----------------------------------------------------------------*/
10110 genNearPointerSet (operand * right,
10117 sym_link *retype, *letype;
10118 sym_link *ptype = operandType (result);
10120 retype = getSpec (operandType (right));
10121 letype = getSpec (ptype);
10123 aopOp (result, ic, FALSE, FALSE);
10125 /* if the result is rematerializable &
10126 in data space & not a bit variable */
10127 if (AOP_TYPE (result) == AOP_IMMD &&
10128 DCL_TYPE (ptype) == POINTER &&
10129 !IS_BITVAR (retype) &&
10130 !IS_BITVAR (letype))
10132 genDataPointerSet (right, result, ic);
10136 /* if the value is already in a pointer register
10137 then don't need anything more */
10138 if (!AOP_INPREG (AOP (result)))
10140 /* otherwise get a free pointer register */
10143 aop = newAsmop (0);
10144 preg = getFreePtr (ic, &aop, FALSE);
10145 emitcode ("mov", "%s,%s",
10147 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10148 rname = preg->name;
10151 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10153 aopOp (right, ic, FALSE, FALSE);
10155 /* if bitfield then unpack the bits */
10156 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10157 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
10160 /* we have can just get the values */
10161 int size = AOP_SIZE (right);
10166 l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10170 emitcode ("mov", "@%s,a", rname);
10173 emitcode ("mov", "@%s,%s", rname, l);
10175 emitcode ("inc", "%s", rname);
10180 /* now some housekeeping stuff */
10183 /* we had to allocate for this iCode */
10184 if (pi) aopPut (AOP (result),rname,0);
10185 freeAsmop (NULL, aop, ic, TRUE);
10189 /* we did not allocate which means left
10190 already in a pointer register, then
10191 if size > 0 && this could be used again
10192 we have to point it back to where it
10194 if (AOP_SIZE (right) > 1 &&
10195 !OP_SYMBOL (result)->remat &&
10196 (OP_SYMBOL (result)->liveTo > ic->seq ||
10200 int size = AOP_SIZE (right) - 1;
10202 emitcode ("dec", "%s", rname);
10207 if (pi) pi->generated = 1;
10208 freeAsmop (result, NULL, ic, TRUE);
10209 freeAsmop (right, NULL, ic, TRUE);
10214 /*-----------------------------------------------------------------*/
10215 /* genPagedPointerSet - emitcode for Paged pointer put */
10216 /*-----------------------------------------------------------------*/
10218 genPagedPointerSet (operand * right,
10225 sym_link *retype, *letype;
10227 retype = getSpec (operandType (right));
10228 letype = getSpec (operandType (result));
10230 aopOp (result, ic, FALSE, FALSE);
10232 /* if the value is already in a pointer register
10233 then don't need anything more */
10234 if (!AOP_INPREG (AOP (result)))
10236 /* otherwise get a free pointer register */
10239 aop = newAsmop (0);
10240 preg = getFreePtr (ic, &aop, FALSE);
10241 emitcode ("mov", "%s,%s",
10243 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10244 rname = preg->name;
10247 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10249 aopOp (right, ic, FALSE, FALSE);
10251 /* if bitfield then unpack the bits */
10252 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10253 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10256 /* we have can just get the values */
10257 int size = AOP_SIZE (right);
10262 MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10264 emitcode ("movx", "@%s,a", rname);
10267 emitcode ("inc", "%s", rname);
10273 /* now some housekeeping stuff */
10276 if (pi) aopPut (AOP (result),rname,0);
10277 /* we had to allocate for this iCode */
10278 freeAsmop (NULL, aop, ic, TRUE);
10282 /* we did not allocate which means left
10283 already in a pointer register, then
10284 if size > 0 && this could be used again
10285 we have to point it back to where it
10287 if (AOP_SIZE (right) > 1 &&
10288 !OP_SYMBOL (result)->remat &&
10289 (OP_SYMBOL (result)->liveTo > ic->seq ||
10293 int size = AOP_SIZE (right) - 1;
10295 emitcode ("dec", "%s", rname);
10300 if (pi) pi->generated = 1;
10301 freeAsmop (result, NULL, ic, TRUE);
10302 freeAsmop (right, NULL, ic, TRUE);
10307 /*-----------------------------------------------------------------*/
10308 /* genFarPointerSet - set value from far space */
10309 /*-----------------------------------------------------------------*/
10311 genFarPointerSet (operand * right,
10312 operand * result, iCode * ic, iCode *pi)
10314 int size, offset, dopi=1;
10315 sym_link *retype = getSpec (operandType (right));
10316 sym_link *letype = getSpec (operandType (result));
10318 aopOp (result, ic, FALSE, FALSE);
10320 /* if the operand is already in dptr
10321 then we do nothing else we move the value to dptr */
10322 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10324 /* if this is remateriazable */
10325 if (AOP_TYPE (result) == AOP_IMMD)
10326 emitcode ("mov", "dptr,%s",
10327 aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10330 /* we need to get it byte by byte */
10331 _startLazyDPSEvaluation ();
10332 if (AOP_TYPE (result) != AOP_DPTR)
10334 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10335 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10336 if (options.model == MODEL_FLAT24)
10337 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10341 /* We need to generate a load to DPTR indirect through DPTR. */
10342 D (emitcode (";", "genFarPointerSet -- indirection special case."););
10344 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10345 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10346 if (options.model == MODEL_FLAT24)
10347 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10348 emitcode ("pop", "dph");
10349 emitcode ("pop", "dpl");
10352 _endLazyDPSEvaluation ();
10355 /* so dptr know contains the address */
10356 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10358 /* if bit then unpack */
10359 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10360 if (AOP_INDPTRn(result)) {
10361 genSetDPTR(AOP(result)->aopu.dptr);
10363 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10364 if (AOP_INDPTRn(result)) {
10368 size = AOP_SIZE (right);
10370 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10372 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10374 genSetDPTR(AOP(result)->aopu.dptr);
10375 emitcode ("movx", "@dptr,a");
10376 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10377 emitcode ("inc", "dptr");
10381 _startLazyDPSEvaluation ();
10383 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10385 if (AOP_INDPTRn(result)) {
10386 genSetDPTR(AOP(result)->aopu.dptr);
10392 emitcode ("movx", "@dptr,a");
10393 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10394 emitcode ("inc", "dptr");
10396 _endLazyDPSEvaluation ();
10400 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10401 if (!AOP_INDPTRn(result)) {
10402 _startLazyDPSEvaluation ();
10404 aopPut (AOP(result),"dpl",0);
10405 aopPut (AOP(result),"dph",1);
10406 if (options.model == MODEL_FLAT24)
10407 aopPut (AOP(result),"dpx",2);
10409 _endLazyDPSEvaluation ();
10412 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10413 AOP_SIZE(right) > 1 &&
10414 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10416 size = AOP_SIZE (right) - 1;
10417 if (AOP_INDPTRn(result)) {
10418 genSetDPTR(AOP(result)->aopu.dptr);
10420 while (size--) emitcode ("lcall","__decdptr");
10421 if (AOP_INDPTRn(result)) {
10425 freeAsmop (result, NULL, ic, TRUE);
10426 freeAsmop (right, NULL, ic, TRUE);
10429 /*-----------------------------------------------------------------*/
10430 /* genGenPointerSet - set value from generic pointer space */
10431 /*-----------------------------------------------------------------*/
10433 genGenPointerSet (operand * right,
10434 operand * result, iCode * ic, iCode *pi)
10437 sym_link *retype = getSpec (operandType (right));
10438 sym_link *letype = getSpec (operandType (result));
10440 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10442 /* if the operand is already in dptr
10443 then we do nothing else we move the value to dptr */
10444 if (AOP_TYPE (result) != AOP_STR)
10446 _startLazyDPSEvaluation ();
10447 /* if this is remateriazable */
10448 if (AOP_TYPE (result) == AOP_IMMD)
10450 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10451 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10453 MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10458 "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10462 { /* we need to get it byte by byte */
10463 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10464 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10465 if (options.model == MODEL_FLAT24) {
10466 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10467 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10469 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10472 _endLazyDPSEvaluation ();
10474 /* so dptr + b now contains the address */
10476 aopOp (right, ic, FALSE, TRUE);
10480 /* if bit then unpack */
10481 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10483 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10487 size = AOP_SIZE (right);
10490 _startLazyDPSEvaluation ();
10495 // Set two bytes at a time, passed in _AP & A.
10496 // dptr will be incremented ONCE by __gptrputWord.
10498 // Note: any change here must be coordinated
10499 // with the implementation of __gptrputWord
10500 // in device/lib/_gptrput.c
10501 emitcode("mov", "_ap, %s",
10502 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10503 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10507 emitcode ("lcall", "__gptrputWord");
10512 // Only one byte to put.
10513 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10517 emitcode ("lcall", "__gptrput");
10520 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10522 emitcode ("inc", "dptr");
10525 _endLazyDPSEvaluation ();
10528 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10529 _startLazyDPSEvaluation ();
10531 aopPut (AOP(result),"dpl",0);
10532 aopPut (AOP(result),"dph",1);
10533 if (options.model == MODEL_FLAT24) {
10534 aopPut (AOP(result),"dpx",2);
10535 aopPut (AOP(result),"b",3);
10537 aopPut (AOP(result),"b",2);
10539 _endLazyDPSEvaluation ();
10542 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10543 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10545 size = AOP_SIZE (right) - 1;
10546 while (size--) emitcode ("lcall","__decdptr");
10548 freeAsmop (result, NULL, ic, TRUE);
10549 freeAsmop (right, NULL, ic, TRUE);
10552 /*-----------------------------------------------------------------*/
10553 /* genPointerSet - stores the value into a pointer location */
10554 /*-----------------------------------------------------------------*/
10556 genPointerSet (iCode * ic, iCode *pi)
10558 operand *right, *result;
10559 sym_link *type, *etype;
10562 D (emitcode (";", "genPointerSet "););
10564 right = IC_RIGHT (ic);
10565 result = IC_RESULT (ic);
10567 /* depending on the type of pointer we need to
10568 move it to the correct pointer register */
10569 type = operandType (result);
10570 etype = getSpec (type);
10571 /* if left is of type of pointer then it is simple */
10572 if (IS_PTR (type) && !IS_FUNC (type->next))
10574 p_type = DCL_TYPE (type);
10578 /* we have to go by the storage class */
10579 p_type = PTR_TYPE (SPEC_OCLS (etype));
10581 /* special case when cast remat */
10582 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10583 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10584 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10585 type = operandType (result);
10586 p_type = DCL_TYPE (type);
10589 /* now that we have the pointer type we assign
10590 the pointer values */
10596 genNearPointerSet (right, result, ic, pi);
10600 genPagedPointerSet (right, result, ic, pi);
10604 genFarPointerSet (right, result, ic, pi);
10608 genGenPointerSet (right, result, ic, pi);
10612 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10613 "genPointerSet: illegal pointer type");
10618 /*-----------------------------------------------------------------*/
10619 /* genIfx - generate code for Ifx statement */
10620 /*-----------------------------------------------------------------*/
10622 genIfx (iCode * ic, iCode * popIc)
10624 operand *cond = IC_COND (ic);
10627 D (emitcode (";", "genIfx "););
10629 aopOp (cond, ic, FALSE, FALSE);
10631 /* get the value into acc */
10632 if (AOP_TYPE (cond) != AOP_CRY)
10641 /* the result is now in the accumulator */
10642 freeAsmop (cond, NULL, ic, TRUE);
10644 /* if there was something to be popped then do it */
10648 /* if the condition is a bit variable */
10649 if (isbit && IS_ITEMP (cond) &&
10652 genIfxJump (ic, SPIL_LOC (cond)->rname);
10654 else if (isbit && !IS_ITEMP (cond))
10656 genIfxJump (ic, OP_SYMBOL (cond)->rname);
10660 genIfxJump (ic, "a");
10666 /*-----------------------------------------------------------------*/
10667 /* genAddrOf - generates code for address of */
10668 /*-----------------------------------------------------------------*/
10670 genAddrOf (iCode * ic)
10672 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10675 D (emitcode (";", "genAddrOf ");
10678 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10680 /* if the operand is on the stack then we
10681 need to get the stack offset of this
10683 if (sym->onStack) {
10685 /* if 10 bit stack */
10686 if (options.stack10bit) {
10690 tsprintf(buff, sizeof(buff),
10691 "#!constbyte",(options.stack_loc >> 16) & 0xff);
10692 /* if it has an offset then we need to compute it */
10693 /* emitcode ("subb", "a,#!constbyte", */
10694 /* -((sym->stack < 0) ? */
10695 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10696 /* ((short) sym->stack)) & 0xff); */
10697 /* emitcode ("mov","b,a"); */
10698 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10699 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10700 /* ((short) sym->stack)) >> 8) & 0xff); */
10702 emitcode ("mov", "a,_bpx");
10703 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
10704 ((char) (sym->stack - _G.nRegsSaved)) :
10705 ((char) sym->stack )) & 0xff);
10706 emitcode ("mov", "b,a");
10707 emitcode ("mov", "a,_bpx+1");
10709 offset = (((sym->stack < 0) ?
10710 ((short) (sym->stack - _G.nRegsSaved)) :
10711 ((short) sym->stack )) >> 8) & 0xff;
10713 emitcode ("addc","a,#!constbyte", offset);
10715 aopPut (AOP (IC_RESULT (ic)), "b", 0);
10716 aopPut (AOP (IC_RESULT (ic)), "a", 1);
10717 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10719 /* we can just move _bp */
10720 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10721 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10722 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10725 /* if it has an offset then we need to compute it */
10727 emitcode ("mov", "a,_bp");
10728 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10729 aopPut (AOP (IC_RESULT (ic)), "a", 0);
10731 /* we can just move _bp */
10732 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10734 /* fill the result with zero */
10735 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10738 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10740 "*** warning: pointer to stack var truncated.\n");
10745 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10751 /* object not on stack then we need the name */
10752 size = AOP_SIZE (IC_RESULT (ic));
10757 char s[SDCC_NAME_MAX];
10761 tsprintf(s, sizeof(s), "#!his",sym->rname);
10764 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
10767 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
10769 default: /* should not need this (just in case) */
10770 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10777 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10780 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10784 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10788 #if 0 // obsolete, and buggy for != xdata
10789 /*-----------------------------------------------------------------*/
10790 /* genArrayInit - generates code for address of */
10791 /*-----------------------------------------------------------------*/
10793 genArrayInit (iCode * ic)
10795 literalList *iLoop;
10797 int elementSize = 0, eIndex;
10798 unsigned val, lastVal;
10800 operand *left=IC_LEFT(ic);
10802 D (emitcode (";", "genArrayInit "););
10804 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10806 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10808 // Load immediate value into DPTR.
10809 emitcode("mov", "dptr, %s",
10810 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10812 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10815 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10816 "Unexpected operand to genArrayInit.\n");
10819 // a regression because of SDCCcse.c:1.52
10820 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10821 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10822 if (options.model == MODEL_FLAT24)
10823 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10827 type = operandType(IC_LEFT(ic));
10829 if (type && type->next)
10831 elementSize = getSize(type->next);
10835 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10836 "can't determine element size in genArrayInit.\n");
10840 iLoop = IC_ARRAYILIST(ic);
10845 bool firstpass = TRUE;
10847 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10848 iLoop->count, (int)iLoop->literalValue, elementSize);
10854 symbol *tlbl = NULL;
10856 count = ix > 256 ? 256 : ix;
10860 tlbl = newiTempLabel (NULL);
10861 if (firstpass || (count & 0xff))
10863 emitcode("mov", "b, #!constbyte", count & 0xff);
10866 emitcode ("", "!tlabeldef", tlbl->key + 100);
10871 for (eIndex = 0; eIndex < elementSize; eIndex++)
10873 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10874 if (val != lastVal)
10876 emitcode("mov", "a, #!constbyte", val);
10880 emitcode("movx", "@dptr, a");
10881 emitcode("inc", "dptr");
10886 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10892 iLoop = iLoop->next;
10895 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10899 /*-----------------------------------------------------------------*/
10900 /* genFarFarAssign - assignment when both are in far space */
10901 /*-----------------------------------------------------------------*/
10903 genFarFarAssign (operand * result, operand * right, iCode * ic)
10905 int size = AOP_SIZE (right);
10907 symbol *rSym = NULL;
10911 /* quick & easy case. */
10912 D(emitcode(";","genFarFarAssign (1 byte case)"););
10913 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10914 freeAsmop (right, NULL, ic, FALSE);
10915 /* now assign DPTR to result */
10917 aopOp(result, ic, FALSE, FALSE);
10919 aopPut(AOP(result), "a", 0);
10920 freeAsmop(result, NULL, ic, FALSE);
10924 /* See if we've got an underlying symbol to abuse. */
10925 if (IS_SYMOP(result) && OP_SYMBOL(result))
10927 if (IS_TRUE_SYMOP(result))
10929 rSym = OP_SYMBOL(result);
10931 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10933 rSym = OP_SYMBOL(result)->usl.spillLoc;
10937 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10939 /* We can use the '390 auto-toggle feature to good effect here. */
10941 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10942 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10943 emitcode ("mov", "dptr,#%s", rSym->rname);
10944 /* DP2 = result, DP1 = right, DP1 is current. */
10947 emitcode("movx", "a,@dptr");
10948 emitcode("movx", "@dptr,a");
10951 emitcode("inc", "dptr");
10952 emitcode("inc", "dptr");
10955 emitcode("mov", "dps,#0");
10956 freeAsmop (right, NULL, ic, FALSE);
10958 some alternative code for processors without auto-toggle
10959 no time to test now, so later well put in...kpb
10960 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10961 emitcode("mov", "dps,#1"); /* Select DPTR2. */
10962 emitcode ("mov", "dptr,#%s", rSym->rname);
10963 /* DP2 = result, DP1 = right, DP1 is current. */
10967 emitcode("movx", "a,@dptr");
10969 emitcode("inc", "dptr");
10970 emitcode("inc", "dps");
10971 emitcode("movx", "@dptr,a");
10973 emitcode("inc", "dptr");
10974 emitcode("inc", "dps");
10976 emitcode("mov", "dps,#0");
10977 freeAsmop (right, NULL, ic, FALSE);
10982 D (emitcode (";", "genFarFarAssign"););
10983 aopOp (result, ic, TRUE, TRUE);
10985 _startLazyDPSEvaluation ();
10989 aopPut (AOP (result),
10990 aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10993 _endLazyDPSEvaluation ();
10994 freeAsmop (result, NULL, ic, FALSE);
10995 freeAsmop (right, NULL, ic, FALSE);
10999 /*-----------------------------------------------------------------*/
11000 /* genAssign - generate code for assignment */
11001 /*-----------------------------------------------------------------*/
11003 genAssign (iCode * ic)
11005 operand *result, *right;
11007 unsigned long lit = 0L;
11009 D (emitcode (";", "genAssign ");
11012 result = IC_RESULT (ic);
11013 right = IC_RIGHT (ic);
11015 /* if they are the same */
11016 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11019 aopOp (right, ic, FALSE, FALSE);
11021 emitcode (";", "genAssign: resultIsFar = %s",
11022 isOperandInFarSpace (result) ?
11025 /* special case both in far space */
11026 if ((AOP_TYPE (right) == AOP_DPTR ||
11027 AOP_TYPE (right) == AOP_DPTR2) &&
11028 /* IS_TRUE_SYMOP(result) && */
11029 isOperandInFarSpace (result))
11031 genFarFarAssign (result, right, ic);
11035 aopOp (result, ic, TRUE, FALSE);
11037 /* if they are the same registers */
11038 if (sameRegs (AOP (right), AOP (result)))
11041 /* if the result is a bit */
11042 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
11044 /* if the right size is a literal then
11045 we know what the value is */
11046 if (AOP_TYPE (right) == AOP_LIT)
11048 if (((int) operandLitValue (right)))
11049 aopPut (AOP (result), one, 0);
11051 aopPut (AOP (result), zero, 0);
11055 /* the right is also a bit variable */
11056 if (AOP_TYPE (right) == AOP_CRY)
11058 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11059 aopPut (AOP (result), "c", 0);
11063 /* we need to or */
11065 aopPut (AOP (result), "a", 0);
11069 /* bit variables done */
11071 size = AOP_SIZE (result);
11073 if (AOP_TYPE (right) == AOP_LIT)
11074 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11077 (AOP_TYPE (result) != AOP_REG) &&
11078 (AOP_TYPE (right) == AOP_LIT) &&
11079 !IS_FLOAT (operandType (right)))
11081 _startLazyDPSEvaluation ();
11082 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
11084 aopPut (AOP (result),
11085 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11090 /* And now fill the rest with zeros. */
11093 emitcode ("clr", "a");
11097 aopPut (AOP (result), "a", offset++);
11099 _endLazyDPSEvaluation ();
11103 _startLazyDPSEvaluation ();
11106 aopPut (AOP (result),
11107 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11111 _endLazyDPSEvaluation ();
11115 freeAsmop (right, NULL, ic, FALSE);
11116 freeAsmop (result, NULL, ic, TRUE);
11119 /*-----------------------------------------------------------------*/
11120 /* genJumpTab - generates code for jump table */
11121 /*-----------------------------------------------------------------*/
11123 genJumpTab (iCode * ic)
11128 D (emitcode (";", "genJumpTab ");
11131 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11132 /* get the condition into accumulator */
11133 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11135 /* multiply by four! */
11136 emitcode ("add", "a,acc");
11137 emitcode ("add", "a,acc");
11138 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11140 jtab = newiTempLabel (NULL);
11141 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11142 emitcode ("jmp", "@a+dptr");
11143 emitcode ("", "!tlabeldef", jtab->key + 100);
11144 /* now generate the jump labels */
11145 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11146 jtab = setNextItem (IC_JTLABELS (ic)))
11147 emitcode ("ljmp", "!tlabel", jtab->key + 100);
11151 /*-----------------------------------------------------------------*/
11152 /* genCast - gen code for casting */
11153 /*-----------------------------------------------------------------*/
11155 genCast (iCode * ic)
11157 operand *result = IC_RESULT (ic);
11158 sym_link *ctype = operandType (IC_LEFT (ic));
11159 sym_link *rtype = operandType (IC_RIGHT (ic));
11160 operand *right = IC_RIGHT (ic);
11163 D (emitcode (";", "genCast "););
11165 /* if they are equivalent then do nothing */
11166 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11169 aopOp (right, ic, FALSE, FALSE);
11170 aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
11172 /* if the result is a bit */
11173 if (IS_BITVAR (OP_SYMBOL (result)->type)
11174 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11176 /* if the right size is a literal then
11177 we know what the value is */
11178 if (AOP_TYPE (right) == AOP_LIT)
11180 if (((int) operandLitValue (right)))
11181 aopPut (AOP (result), one, 0);
11183 aopPut (AOP (result), zero, 0);
11188 /* the right is also a bit variable */
11189 if (AOP_TYPE (right) == AOP_CRY)
11191 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11192 aopPut (AOP (result), "c", 0);
11196 /* we need to or */
11198 aopPut (AOP (result), "a", 0);
11202 /* if they are the same size : or less */
11203 if (AOP_SIZE (result) <= AOP_SIZE (right))
11206 /* if they are in the same place */
11207 if (sameRegs (AOP (right), AOP (result)))
11210 /* if they in different places then copy */
11211 size = AOP_SIZE (result);
11213 _startLazyDPSEvaluation ();
11216 aopPut (AOP (result),
11217 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11221 _endLazyDPSEvaluation ();
11226 /* if the result is of type pointer */
11227 if (IS_PTR (ctype))
11231 sym_link *type = operandType (right);
11233 /* pointer to generic pointer */
11234 if (IS_GENPTR (ctype))
11238 p_type = DCL_TYPE (type);
11242 #if OLD_CAST_BEHAVIOR
11243 /* KV: we are converting a non-pointer type to
11244 * a generic pointer. This (ifdef'd out) code
11245 * says that the resulting generic pointer
11246 * should have the same class as the storage
11247 * location of the non-pointer variable.
11249 * For example, converting an int (which happens
11250 * to be stored in DATA space) to a pointer results
11251 * in a DATA generic pointer; if the original int
11252 * in XDATA space, so will be the resulting pointer.
11254 * I don't like that behavior, and thus this change:
11255 * all such conversions will be forced to XDATA and
11256 * throw a warning. If you want some non-XDATA
11257 * type, or you want to suppress the warning, you
11258 * must go through an intermediate cast, like so:
11260 * char _generic *gp = (char _xdata *)(intVar);
11262 sym_link *etype = getSpec (type);
11264 /* we have to go by the storage class */
11265 if (SPEC_OCLS (etype) != generic)
11267 p_type = PTR_TYPE (SPEC_OCLS (etype));
11272 /* Converting unknown class (i.e. register variable)
11273 * to generic pointer. This is not good, but
11274 * we'll make a guess (and throw a warning).
11277 werror (W_INT_TO_GEN_PTR_CAST);
11281 /* the first two bytes are known */
11282 size = GPTRSIZE - 1;
11284 _startLazyDPSEvaluation ();
11287 aopPut (AOP (result),
11288 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11292 _endLazyDPSEvaluation ();
11294 /* the last byte depending on type */
11296 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11301 // pointerTypeToGPByte will have bitched.
11305 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11306 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11311 /* just copy the pointers */
11312 size = AOP_SIZE (result);
11314 _startLazyDPSEvaluation ();
11317 aopPut (AOP (result),
11318 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11322 _endLazyDPSEvaluation ();
11326 /* so we now know that the size of destination is greater
11327 than the size of the source */
11328 /* we move to result for the size of source */
11329 size = AOP_SIZE (right);
11331 _startLazyDPSEvaluation ();
11334 aopPut (AOP (result),
11335 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11339 _endLazyDPSEvaluation ();
11341 /* now depending on the sign of the source && destination */
11342 size = AOP_SIZE (result) - AOP_SIZE (right);
11343 /* if unsigned or not an integral type */
11344 /* also, if the source is a bit, we don't need to sign extend, because
11345 * it can't possibly have set the sign bit.
11347 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11351 aopPut (AOP (result), zero, offset++);
11356 /* we need to extend the sign :{ */
11357 MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11358 FALSE, FALSE, NULL));
11359 emitcode ("rlc", "a");
11360 emitcode ("subb", "a,acc");
11362 aopPut (AOP (result), "a", offset++);
11365 /* we are done hurray !!!! */
11368 freeAsmop (right, NULL, ic, TRUE);
11369 freeAsmop (result, NULL, ic, TRUE);
11373 /*-----------------------------------------------------------------*/
11374 /* genDjnz - generate decrement & jump if not zero instrucion */
11375 /*-----------------------------------------------------------------*/
11377 genDjnz (iCode * ic, iCode * ifx)
11379 symbol *lbl, *lbl1;
11383 /* if the if condition has a false label
11384 then we cannot save */
11385 if (IC_FALSE (ifx))
11388 /* if the minus is not of the form
11390 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11391 !IS_OP_LITERAL (IC_RIGHT (ic)))
11394 if (operandLitValue (IC_RIGHT (ic)) != 1)
11397 /* if the size of this greater than one then no
11399 if (getSize (operandType (IC_RESULT (ic))) > 1)
11402 /* otherwise we can save BIG */
11403 D(emitcode(";", "genDjnz"););
11405 lbl = newiTempLabel (NULL);
11406 lbl1 = newiTempLabel (NULL);
11408 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11410 if (AOP_NEEDSACC(IC_RESULT(ic)))
11412 /* If the result is accessed indirectly via
11413 * the accumulator, we must explicitly write
11414 * it back after the decrement.
11416 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11418 if (strcmp(rByte, "a"))
11420 /* Something is hopelessly wrong */
11421 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11422 __FILE__, __LINE__);
11423 /* We can just give up; the generated code will be inefficient,
11424 * but what the hey.
11426 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11429 emitcode ("dec", "%s", rByte);
11430 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11431 emitcode ("jnz", "!tlabel", lbl->key + 100);
11433 else if (IS_AOP_PREG (IC_RESULT (ic)))
11435 emitcode ("dec", "%s",
11436 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11437 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11438 emitcode ("jnz", "!tlabel", lbl->key + 100);
11442 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11445 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11446 emitcode ("", "!tlabeldef", lbl->key + 100);
11447 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11448 emitcode ("", "!tlabeldef", lbl1->key + 100);
11450 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11451 ifx->generated = 1;
11455 /*-----------------------------------------------------------------*/
11456 /* genReceive - generate code for a receive iCode */
11457 /*-----------------------------------------------------------------*/
11459 genReceive (iCode * ic)
11461 int size = getSize (operandType (IC_RESULT (ic)));
11465 D (emitcode (";", "genReceive "););
11467 if (ic->argreg == 1)
11469 /* first parameter */
11470 if (AOP_IS_STR(IC_RESULT(ic)))
11472 /* Nothing to do: it's already in the proper place. */
11479 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11480 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11481 IS_TRUE_SYMOP (IC_RESULT (ic)));
11484 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11487 /* Sanity checking... */
11488 if (AOP_USESDPTR(IC_RESULT(ic)))
11490 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11491 "genReceive got unexpected DPTR.");
11493 assignResultValue (IC_RESULT (ic));
11498 /* second receive onwards */
11499 /* this gets a little tricky since unused recevies will be
11500 eliminated, we have saved the reg in the type field . and
11501 we use that to figure out which register to use */
11502 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11503 rb1off = ic->argreg;
11506 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11509 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11512 /*-----------------------------------------------------------------*/
11513 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11514 /*-----------------------------------------------------------------*/
11515 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11517 operand *from , *to , *count;
11522 /* we know it has to be 3 parameters */
11523 assert (nparms == 3);
11525 rsave = newBitVect(16);
11526 /* save DPTR if it needs to be saved */
11527 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11528 if (bitVectBitValue(ic->rMask,i))
11529 rsave = bitVectSetBit(rsave,i);
11531 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11532 ds390_rUmaskForOp (IC_RESULT(ic))));
11539 aopOp (from, ic->next, FALSE, FALSE);
11541 /* get from into DPTR1 */
11542 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11543 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11544 if (options.model == MODEL_FLAT24) {
11545 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11548 freeAsmop (from, NULL, ic, FALSE);
11549 aopOp (to, ic, FALSE, FALSE);
11550 /* get "to" into DPTR */
11551 /* if the operand is already in dptr
11552 then we do nothing else we move the value to dptr */
11553 if (AOP_TYPE (to) != AOP_STR) {
11554 /* if already in DPTR then we need to push */
11555 if (AOP_TYPE(to) == AOP_DPTR) {
11556 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11557 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11558 if (options.model == MODEL_FLAT24)
11559 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11560 emitcode ("pop", "dph");
11561 emitcode ("pop", "dpl");
11563 _startLazyDPSEvaluation ();
11564 /* if this is remateriazable */
11565 if (AOP_TYPE (to) == AOP_IMMD) {
11566 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11567 } else { /* we need to get it byte by byte */
11568 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11569 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11570 if (options.model == MODEL_FLAT24) {
11571 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11574 _endLazyDPSEvaluation ();
11577 freeAsmop (to, NULL, ic, FALSE);
11578 _G.dptrInUse = _G.dptr1InUse = 1;
11579 aopOp (count, ic->next->next, FALSE,FALSE);
11580 lbl =newiTempLabel(NULL);
11582 /* now for the actual copy */
11583 if (AOP_TYPE(count) == AOP_LIT &&
11584 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11585 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11587 emitcode ("lcall","__bi_memcpyc2x_s");
11589 emitcode ("lcall","__bi_memcpyx2x_s");
11591 freeAsmop (count, NULL, ic, FALSE);
11593 symbol *lbl1 = newiTempLabel(NULL);
11595 emitcode (";"," Auto increment but no djnz");
11596 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11597 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11598 freeAsmop (count, NULL, ic, FALSE);
11599 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11600 emitcode ("","!tlabeldef",lbl->key+100);
11602 emitcode ("clr","a");
11603 emitcode ("movc", "a,@a+dptr");
11605 emitcode ("movx", "a,@dptr");
11606 emitcode ("movx", "@dptr,a");
11607 emitcode ("inc", "dptr");
11608 emitcode ("inc", "dptr");
11609 emitcode ("mov","a,b");
11610 emitcode ("orl","a,_ap");
11611 emitcode ("jz","!tlabel",lbl1->key+100);
11612 emitcode ("mov","a,_ap");
11613 emitcode ("add","a,#!constbyte",0xFF);
11614 emitcode ("mov","_ap,a");
11615 emitcode ("mov","a,b");
11616 emitcode ("addc","a,#!constbyte",0xFF);
11617 emitcode ("mov","b,a");
11618 emitcode ("sjmp","!tlabel",lbl->key+100);
11619 emitcode ("","!tlabeldef",lbl1->key+100);
11621 emitcode ("mov", "dps,#0");
11622 _G.dptrInUse = _G.dptr1InUse = 0;
11623 unsavermask(rsave);
11627 /*-----------------------------------------------------------------*/
11628 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
11629 /*-----------------------------------------------------------------*/
11630 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11632 operand *from , *to , *count;
11637 /* we know it has to be 3 parameters */
11638 assert (nparms == 3);
11640 rsave = newBitVect(16);
11641 /* save DPTR if it needs to be saved */
11642 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11643 if (bitVectBitValue(ic->rMask,i))
11644 rsave = bitVectSetBit(rsave,i);
11646 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11647 ds390_rUmaskForOp (IC_RESULT(ic))));
11654 aopOp (from, ic->next, FALSE, FALSE);
11656 /* get from into DPTR1 */
11657 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11658 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11659 if (options.model == MODEL_FLAT24) {
11660 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11663 freeAsmop (from, NULL, ic, FALSE);
11664 aopOp (to, ic, FALSE, FALSE);
11665 /* get "to" into DPTR */
11666 /* if the operand is already in dptr
11667 then we do nothing else we move the value to dptr */
11668 if (AOP_TYPE (to) != AOP_STR) {
11669 /* if already in DPTR then we need to push */
11670 if (AOP_TYPE(to) == AOP_DPTR) {
11671 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11672 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11673 if (options.model == MODEL_FLAT24)
11674 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11675 emitcode ("pop", "dph");
11676 emitcode ("pop", "dpl");
11678 _startLazyDPSEvaluation ();
11679 /* if this is remateriazable */
11680 if (AOP_TYPE (to) == AOP_IMMD) {
11681 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11682 } else { /* we need to get it byte by byte */
11683 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11684 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11685 if (options.model == MODEL_FLAT24) {
11686 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11689 _endLazyDPSEvaluation ();
11692 freeAsmop (to, NULL, ic, FALSE);
11693 _G.dptrInUse = _G.dptr1InUse = 1;
11694 aopOp (count, ic->next->next, FALSE,FALSE);
11695 lbl =newiTempLabel(NULL);
11696 lbl2 =newiTempLabel(NULL);
11698 /* now for the actual compare */
11699 if (AOP_TYPE(count) == AOP_LIT &&
11700 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11701 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11703 emitcode("lcall","__bi_memcmpc2x_s");
11705 emitcode("lcall","__bi_memcmpx2x_s");
11706 freeAsmop (count, NULL, ic, FALSE);
11707 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11708 aopPut(AOP(IC_RESULT(ic)),"a",0);
11709 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11711 symbol *lbl1 = newiTempLabel(NULL);
11713 emitcode("push","ar0");
11714 emitcode (";"," Auto increment but no djnz");
11715 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11716 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11717 freeAsmop (count, NULL, ic, FALSE);
11718 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11719 emitcode ("","!tlabeldef",lbl->key+100);
11721 emitcode ("clr","a");
11722 emitcode ("movc", "a,@a+dptr");
11724 emitcode ("movx", "a,@dptr");
11725 emitcode ("mov","r0,a");
11726 emitcode ("movx", "a,@dptr");
11727 emitcode ("clr","c");
11728 emitcode ("subb","a,r0");
11729 emitcode ("jnz","!tlabel",lbl2->key+100);
11730 emitcode ("inc", "dptr");
11731 emitcode ("inc", "dptr");
11732 emitcode ("mov","a,b");
11733 emitcode ("orl","a,_ap");
11734 emitcode ("jz","!tlabel",lbl1->key+100);
11735 emitcode ("mov","a,_ap");
11736 emitcode ("add","a,#!constbyte",0xFF);
11737 emitcode ("mov","_ap,a");
11738 emitcode ("mov","a,b");
11739 emitcode ("addc","a,#!constbyte",0xFF);
11740 emitcode ("mov","b,a");
11741 emitcode ("sjmp","!tlabel",lbl->key+100);
11742 emitcode ("","!tlabeldef",lbl1->key+100);
11743 emitcode ("clr","a");
11744 emitcode ("","!tlabeldef",lbl2->key+100);
11745 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11746 aopPut(AOP(IC_RESULT(ic)),"a",0);
11747 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11748 emitcode("pop","ar0");
11749 emitcode ("mov", "dps,#0");
11751 _G.dptrInUse = _G.dptr1InUse = 0;
11752 unsavermask(rsave);
11756 /*-----------------------------------------------------------------*/
11757 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11758 /* port, first parameter output area second parameter pointer to */
11759 /* port third parameter count */
11760 /*-----------------------------------------------------------------*/
11761 static void genInp( iCode *ic, int nparms, operand **parms)
11763 operand *from , *to , *count;
11768 /* we know it has to be 3 parameters */
11769 assert (nparms == 3);
11771 rsave = newBitVect(16);
11772 /* save DPTR if it needs to be saved */
11773 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11774 if (bitVectBitValue(ic->rMask,i))
11775 rsave = bitVectSetBit(rsave,i);
11777 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11778 ds390_rUmaskForOp (IC_RESULT(ic))));
11785 aopOp (from, ic->next, FALSE, FALSE);
11787 /* get from into DPTR1 */
11788 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11789 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11790 if (options.model == MODEL_FLAT24) {
11791 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11794 freeAsmop (from, NULL, ic, FALSE);
11795 aopOp (to, ic, FALSE, FALSE);
11796 /* get "to" into DPTR */
11797 /* if the operand is already in dptr
11798 then we do nothing else we move the value to dptr */
11799 if (AOP_TYPE (to) != AOP_STR) {
11800 /* if already in DPTR then we need to push */
11801 if (AOP_TYPE(to) == AOP_DPTR) {
11802 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11803 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11804 if (options.model == MODEL_FLAT24)
11805 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11806 emitcode ("pop", "dph");
11807 emitcode ("pop", "dpl");
11809 _startLazyDPSEvaluation ();
11810 /* if this is remateriazable */
11811 if (AOP_TYPE (to) == AOP_IMMD) {
11812 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11813 } else { /* we need to get it byte by byte */
11814 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11815 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11816 if (options.model == MODEL_FLAT24) {
11817 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11820 _endLazyDPSEvaluation ();
11823 freeAsmop (to, NULL, ic, FALSE);
11825 _G.dptrInUse = _G.dptr1InUse = 1;
11826 aopOp (count, ic->next->next, FALSE,FALSE);
11827 lbl =newiTempLabel(NULL);
11829 /* now for the actual copy */
11830 if (AOP_TYPE(count) == AOP_LIT &&
11831 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11832 emitcode (";","OH JOY auto increment with djnz (very fast)");
11833 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11834 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11835 freeAsmop (count, NULL, ic, FALSE);
11836 emitcode ("","!tlabeldef",lbl->key+100);
11837 emitcode ("movx", "a,@dptr"); /* read data from port */
11838 emitcode ("dec","dps"); /* switch to DPTR */
11839 emitcode ("movx", "@dptr,a"); /* save into location */
11840 emitcode ("inc", "dptr"); /* point to next area */
11841 emitcode ("inc","dps"); /* switch to DPTR2 */
11842 emitcode ("djnz","b,!tlabel",lbl->key+100);
11844 symbol *lbl1 = newiTempLabel(NULL);
11846 emitcode (";"," Auto increment but no djnz");
11847 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11848 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11849 freeAsmop (count, NULL, ic, FALSE);
11850 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11851 emitcode ("","!tlabeldef",lbl->key+100);
11852 emitcode ("movx", "a,@dptr");
11853 emitcode ("dec","dps"); /* switch to DPTR */
11854 emitcode ("movx", "@dptr,a");
11855 emitcode ("inc", "dptr");
11856 emitcode ("inc","dps"); /* switch to DPTR2 */
11857 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
11858 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11859 emitcode ("mov","a,b");
11860 emitcode ("orl","a,_ap");
11861 emitcode ("jz","!tlabel",lbl1->key+100);
11862 emitcode ("mov","a,_ap");
11863 emitcode ("add","a,#!constbyte",0xFF);
11864 emitcode ("mov","_ap,a");
11865 emitcode ("mov","a,b");
11866 emitcode ("addc","a,#!constbyte",0xFF);
11867 emitcode ("mov","b,a");
11868 emitcode ("sjmp","!tlabel",lbl->key+100);
11869 emitcode ("","!tlabeldef",lbl1->key+100);
11871 emitcode ("mov", "dps,#0");
11872 _G.dptrInUse = _G.dptr1InUse = 0;
11873 unsavermask(rsave);
11877 /*-----------------------------------------------------------------*/
11878 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11879 /* port, first parameter output area second parameter pointer to */
11880 /* port third parameter count */
11881 /*-----------------------------------------------------------------*/
11882 static void genOutp( iCode *ic, int nparms, operand **parms)
11884 operand *from , *to , *count;
11889 /* we know it has to be 3 parameters */
11890 assert (nparms == 3);
11892 rsave = newBitVect(16);
11893 /* save DPTR if it needs to be saved */
11894 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11895 if (bitVectBitValue(ic->rMask,i))
11896 rsave = bitVectSetBit(rsave,i);
11898 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11899 ds390_rUmaskForOp (IC_RESULT(ic))));
11906 aopOp (from, ic->next, FALSE, FALSE);
11908 /* get from into DPTR1 */
11909 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11910 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11911 if (options.model == MODEL_FLAT24) {
11912 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11915 freeAsmop (from, NULL, ic, FALSE);
11916 aopOp (to, ic, FALSE, FALSE);
11917 /* get "to" into DPTR */
11918 /* if the operand is already in dptr
11919 then we do nothing else we move the value to dptr */
11920 if (AOP_TYPE (to) != AOP_STR) {
11921 /* if already in DPTR then we need to push */
11922 if (AOP_TYPE(to) == AOP_DPTR) {
11923 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11924 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11925 if (options.model == MODEL_FLAT24)
11926 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11927 emitcode ("pop", "dph");
11928 emitcode ("pop", "dpl");
11930 _startLazyDPSEvaluation ();
11931 /* if this is remateriazable */
11932 if (AOP_TYPE (to) == AOP_IMMD) {
11933 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11934 } else { /* we need to get it byte by byte */
11935 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11936 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11937 if (options.model == MODEL_FLAT24) {
11938 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11941 _endLazyDPSEvaluation ();
11944 freeAsmop (to, NULL, ic, FALSE);
11946 _G.dptrInUse = _G.dptr1InUse = 1;
11947 aopOp (count, ic->next->next, FALSE,FALSE);
11948 lbl =newiTempLabel(NULL);
11950 /* now for the actual copy */
11951 if (AOP_TYPE(count) == AOP_LIT &&
11952 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11953 emitcode (";","OH JOY auto increment with djnz (very fast)");
11954 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11955 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11956 emitcode ("","!tlabeldef",lbl->key+100);
11957 emitcode ("movx", "a,@dptr"); /* read data from port */
11958 emitcode ("inc","dps"); /* switch to DPTR2 */
11959 emitcode ("movx", "@dptr,a"); /* save into location */
11960 emitcode ("inc", "dptr"); /* point to next area */
11961 emitcode ("dec","dps"); /* switch to DPTR */
11962 emitcode ("djnz","b,!tlabel",lbl->key+100);
11963 freeAsmop (count, NULL, ic, FALSE);
11965 symbol *lbl1 = newiTempLabel(NULL);
11967 emitcode (";"," Auto increment but no djnz");
11968 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11969 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11970 freeAsmop (count, NULL, ic, FALSE);
11971 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11972 emitcode ("","!tlabeldef",lbl->key+100);
11973 emitcode ("movx", "a,@dptr");
11974 emitcode ("inc", "dptr");
11975 emitcode ("inc","dps"); /* switch to DPTR2 */
11976 emitcode ("movx", "@dptr,a");
11977 emitcode ("dec","dps"); /* switch to DPTR */
11978 emitcode ("mov","a,b");
11979 emitcode ("orl","a,_ap");
11980 emitcode ("jz","!tlabel",lbl1->key+100);
11981 emitcode ("mov","a,_ap");
11982 emitcode ("add","a,#!constbyte",0xFF);
11983 emitcode ("mov","_ap,a");
11984 emitcode ("mov","a,b");
11985 emitcode ("addc","a,#!constbyte",0xFF);
11986 emitcode ("mov","b,a");
11987 emitcode ("sjmp","!tlabel",lbl->key+100);
11988 emitcode ("","!tlabeldef",lbl1->key+100);
11990 emitcode ("mov", "dps,#0");
11991 _G.dptrInUse = _G.dptr1InUse = 0;
11992 unsavermask(rsave);
11996 /*-----------------------------------------------------------------*/
11997 /* genSwapW - swap lower & high order bytes */
11998 /*-----------------------------------------------------------------*/
11999 static void genSwapW(iCode *ic, int nparms, operand **parms)
12003 assert (nparms==1);
12006 dest=IC_RESULT(ic);
12008 assert(getSize(operandType(src))==2);
12010 aopOp (src, ic, FALSE, FALSE);
12011 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
12013 MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
12015 freeAsmop (src, NULL, ic, FALSE);
12017 aopOp (dest,ic, FALSE, FALSE);
12018 aopPut(AOP(dest),"b",0);
12019 aopPut(AOP(dest),"a",1);
12020 freeAsmop (dest, NULL, ic, FALSE);
12023 /*-----------------------------------------------------------------*/
12024 /* genMemsetX - gencode for memSetX data */
12025 /*-----------------------------------------------------------------*/
12026 static void genMemsetX(iCode *ic, int nparms, operand **parms)
12028 operand *to , *val , *count;
12034 /* we know it has to be 3 parameters */
12035 assert (nparms == 3);
12041 /* save DPTR if it needs to be saved */
12042 rsave = newBitVect(16);
12043 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12044 if (bitVectBitValue(ic->rMask,i))
12045 rsave = bitVectSetBit(rsave,i);
12047 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12048 ds390_rUmaskForOp (IC_RESULT(ic))));
12051 aopOp (to, ic, FALSE, FALSE);
12052 /* get "to" into DPTR */
12053 /* if the operand is already in dptr
12054 then we do nothing else we move the value to dptr */
12055 if (AOP_TYPE (to) != AOP_STR) {
12056 /* if already in DPTR then we need to push */
12057 if (AOP_TYPE(to) == AOP_DPTR) {
12058 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12059 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12060 if (options.model == MODEL_FLAT24)
12061 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12062 emitcode ("pop", "dph");
12063 emitcode ("pop", "dpl");
12065 _startLazyDPSEvaluation ();
12066 /* if this is remateriazable */
12067 if (AOP_TYPE (to) == AOP_IMMD) {
12068 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12069 } else { /* we need to get it byte by byte */
12070 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12071 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12072 if (options.model == MODEL_FLAT24) {
12073 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12076 _endLazyDPSEvaluation ();
12079 freeAsmop (to, NULL, ic, FALSE);
12081 aopOp (val, ic->next->next, FALSE,FALSE);
12082 aopOp (count, ic->next->next, FALSE,FALSE);
12083 lbl =newiTempLabel(NULL);
12084 /* now for the actual copy */
12085 if (AOP_TYPE(count) == AOP_LIT &&
12086 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12087 l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
12088 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12090 emitcode ("","!tlabeldef",lbl->key+100);
12091 emitcode ("movx", "@dptr,a");
12092 emitcode ("inc", "dptr");
12093 emitcode ("djnz","b,!tlabel",lbl->key+100);
12095 symbol *lbl1 = newiTempLabel(NULL);
12097 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12098 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12099 emitcode ("","!tlabeldef",lbl->key+100);
12100 MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
12101 emitcode ("movx", "@dptr,a");
12102 emitcode ("inc", "dptr");
12103 emitcode ("mov","a,b");
12104 emitcode ("orl","a,_ap");
12105 emitcode ("jz","!tlabel",lbl1->key+100);
12106 emitcode ("mov","a,_ap");
12107 emitcode ("add","a,#!constbyte",0xFF);
12108 emitcode ("mov","_ap,a");
12109 emitcode ("mov","a,b");
12110 emitcode ("addc","a,#!constbyte",0xFF);
12111 emitcode ("mov","b,a");
12112 emitcode ("sjmp","!tlabel",lbl->key+100);
12113 emitcode ("","!tlabeldef",lbl1->key+100);
12115 freeAsmop (count, NULL, ic, FALSE);
12116 unsavermask(rsave);
12119 /*-----------------------------------------------------------------*/
12120 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12121 /*-----------------------------------------------------------------*/
12122 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12125 operand *pnum, *result;
12128 assert (nparms==1);
12129 /* save registers that need to be saved */
12130 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12131 ds390_rUmaskForOp (IC_RESULT(ic))));
12134 aopOp (pnum, ic, FALSE, FALSE);
12135 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12136 freeAsmop (pnum, NULL, ic, FALSE);
12137 emitcode ("lcall","NatLib_LoadPrimitive");
12138 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12139 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
12140 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12141 for (i = (size-1) ; i >= 0 ; i-- ) {
12142 emitcode ("push","a%s",javaRet[i]);
12144 for (i=0; i < size ; i++ ) {
12145 emitcode ("pop","a%s",
12146 aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12149 for (i = 0 ; i < size ; i++ ) {
12150 aopPut(AOP(result),javaRet[i],i);
12153 freeAsmop (result, NULL, ic, FALSE);
12154 unsavermask(rsave);
12157 /*-----------------------------------------------------------------*/
12158 /* genNatLibLoadPointer - calls TINI api function to load pointer */
12159 /*-----------------------------------------------------------------*/
12160 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12163 operand *pnum, *result;
12167 assert (nparms==1);
12168 /* save registers that need to be saved */
12169 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12170 ds390_rUmaskForOp (IC_RESULT(ic))));
12173 aopOp (pnum, ic, FALSE, FALSE);
12174 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12175 freeAsmop (pnum, NULL, ic, FALSE);
12176 emitcode ("lcall","NatLib_LoadPointer");
12177 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12178 if (AOP_TYPE(result)!=AOP_STR) {
12179 for (i = 0 ; i < size ; i++ ) {
12180 aopPut(AOP(result),fReturn[i],i);
12183 freeAsmop (result, NULL, ic, FALSE);
12184 unsavermask(rsave);
12187 /*-----------------------------------------------------------------*/
12188 /* genNatLibInstallStateBlock - */
12189 /*-----------------------------------------------------------------*/
12190 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
12191 operand **parms, const char *name)
12194 operand *psb, *handle;
12195 assert (nparms==2);
12197 /* save registers that need to be saved */
12198 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12199 ds390_rUmaskForOp (IC_RESULT(ic))));
12203 /* put pointer to state block into DPTR1 */
12204 aopOp (psb, ic, FALSE, FALSE);
12205 if (AOP_TYPE (psb) == AOP_IMMD) {
12206 emitcode ("mov","dps,#1");
12207 emitcode ("mov", "dptr,%s",
12208 aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12209 emitcode ("mov","dps,#0");
12211 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12212 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12213 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12215 freeAsmop (psb, NULL, ic, FALSE);
12217 /* put libraryID into DPTR */
12218 emitcode ("mov","dptr,#LibraryID");
12220 /* put handle into r3:r2 */
12221 aopOp (handle, ic, FALSE, FALSE);
12222 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12223 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12224 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12225 emitcode ("pop","ar3");
12226 emitcode ("pop","ar2");
12228 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12229 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12231 freeAsmop (psb, NULL, ic, FALSE);
12233 /* make the call */
12234 emitcode ("lcall","NatLib_Install%sStateBlock",name);
12236 /* put return value into place*/
12238 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12240 aopPut(AOP(IC_RESULT(ic)),"a",0);
12241 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12242 unsavermask(rsave);
12245 /*-----------------------------------------------------------------*/
12246 /* genNatLibRemoveStateBlock - */
12247 /*-----------------------------------------------------------------*/
12248 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12254 /* save registers that need to be saved */
12255 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12256 ds390_rUmaskForOp (IC_RESULT(ic))));
12258 /* put libraryID into DPTR */
12259 emitcode ("mov","dptr,#LibraryID");
12260 /* make the call */
12261 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12262 unsavermask(rsave);
12265 /*-----------------------------------------------------------------*/
12266 /* genNatLibGetStateBlock - */
12267 /*-----------------------------------------------------------------*/
12268 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12269 operand **parms,const char *name)
12272 symbol *lbl = newiTempLabel(NULL);
12275 /* save registers that need to be saved */
12276 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12277 ds390_rUmaskForOp (IC_RESULT(ic))));
12279 /* put libraryID into DPTR */
12280 emitcode ("mov","dptr,#LibraryID");
12281 /* make the call */
12282 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12283 emitcode ("jnz","!tlabel",lbl->key+100);
12285 /* put return value into place */
12286 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12287 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12288 emitcode ("push","ar3");
12289 emitcode ("push","ar2");
12290 emitcode ("pop","%s",
12291 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12292 emitcode ("pop","%s",
12293 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12295 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12296 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12298 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12299 emitcode ("","!tlabeldef",lbl->key+100);
12300 unsavermask(rsave);
12303 /*-----------------------------------------------------------------*/
12304 /* genMMMalloc - */
12305 /*-----------------------------------------------------------------*/
12306 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12307 int size, const char *name)
12312 symbol *lbl = newiTempLabel(NULL);
12314 assert (nparms == 1);
12315 /* save registers that need to be saved */
12316 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12317 ds390_rUmaskForOp (IC_RESULT(ic))));
12320 aopOp (bsize,ic,FALSE,FALSE);
12322 /* put the size in R4-R2 */
12323 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12324 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12325 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12327 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12328 emitcode("pop","ar4");
12330 emitcode("pop","ar3");
12331 emitcode("pop","ar2");
12333 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12334 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12336 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12339 freeAsmop (bsize, NULL, ic, FALSE);
12341 /* make the call */
12342 emitcode ("lcall","MM_%s",name);
12343 emitcode ("jz","!tlabel",lbl->key+100);
12344 emitcode ("mov","r2,#!constbyte",0xff);
12345 emitcode ("mov","r3,#!constbyte",0xff);
12346 emitcode ("","!tlabeldef",lbl->key+100);
12347 /* we don't care about the pointer : we just save the handle */
12348 rsym = OP_SYMBOL(IC_RESULT(ic));
12349 if (rsym->liveFrom != rsym->liveTo) {
12350 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12351 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12352 emitcode ("push","ar3");
12353 emitcode ("push","ar2");
12354 emitcode ("pop","%s",
12355 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12356 emitcode ("pop","%s",
12357 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12359 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12360 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12362 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12364 unsavermask(rsave);
12367 /*-----------------------------------------------------------------*/
12369 /*-----------------------------------------------------------------*/
12370 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12375 assert (nparms == 1);
12376 /* save registers that need to be saved */
12377 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12378 ds390_rUmaskForOp (IC_RESULT(ic))));
12381 aopOp (handle,ic,FALSE,FALSE);
12383 /* put the size in R4-R2 */
12384 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12385 emitcode("push","%s",
12386 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12387 emitcode("push","%s",
12388 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12389 emitcode("pop","ar3");
12390 emitcode("pop","ar2");
12392 emitcode ("mov","r2,%s",
12393 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12394 emitcode ("mov","r3,%s",
12395 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12397 freeAsmop (handle, NULL, ic, FALSE);
12399 /* make the call */
12400 emitcode ("lcall","MM_Deref");
12403 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12404 if (rsym->liveFrom != rsym->liveTo) {
12405 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12406 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12407 _startLazyDPSEvaluation ();
12409 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12410 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12411 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12413 _endLazyDPSEvaluation ();
12418 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12419 unsavermask(rsave);
12422 /*-----------------------------------------------------------------*/
12423 /* genMMUnrestrictedPersist - */
12424 /*-----------------------------------------------------------------*/
12425 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12430 assert (nparms == 1);
12431 /* save registers that need to be saved */
12432 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12433 ds390_rUmaskForOp (IC_RESULT(ic))));
12436 aopOp (handle,ic,FALSE,FALSE);
12438 /* put the size in R3-R2 */
12439 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12440 emitcode("push","%s",
12441 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12442 emitcode("push","%s",
12443 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12444 emitcode("pop","ar3");
12445 emitcode("pop","ar2");
12447 emitcode ("mov","r2,%s",
12448 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12449 emitcode ("mov","r3,%s",
12450 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12452 freeAsmop (handle, NULL, ic, FALSE);
12454 /* make the call */
12455 emitcode ("lcall","MM_UnrestrictedPersist");
12458 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12459 if (rsym->liveFrom != rsym->liveTo) {
12460 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12461 aopPut(AOP(IC_RESULT(ic)),"a",0);
12462 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12465 unsavermask(rsave);
12468 /*-----------------------------------------------------------------*/
12469 /* genSystemExecJavaProcess - */
12470 /*-----------------------------------------------------------------*/
12471 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12474 operand *handle, *pp;
12476 assert (nparms==2);
12477 /* save registers that need to be saved */
12478 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12479 ds390_rUmaskForOp (IC_RESULT(ic))));
12484 /* put the handle in R3-R2 */
12485 aopOp (handle,ic,FALSE,FALSE);
12486 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12487 emitcode("push","%s",
12488 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12489 emitcode("push","%s",
12490 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12491 emitcode("pop","ar3");
12492 emitcode("pop","ar2");
12494 emitcode ("mov","r2,%s",
12495 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12496 emitcode ("mov","r3,%s",
12497 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12499 freeAsmop (handle, NULL, ic, FALSE);
12501 /* put pointer in DPTR */
12502 aopOp (pp,ic,FALSE,FALSE);
12503 if (AOP_TYPE(pp) == AOP_IMMD) {
12504 emitcode ("mov", "dptr,%s",
12505 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12506 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12507 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12508 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12509 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12511 freeAsmop (handle, NULL, ic, FALSE);
12513 /* make the call */
12514 emitcode ("lcall","System_ExecJavaProcess");
12516 /* put result in place */
12518 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12519 if (rsym->liveFrom != rsym->liveTo) {
12520 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12521 aopPut(AOP(IC_RESULT(ic)),"a",0);
12522 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12526 unsavermask(rsave);
12529 /*-----------------------------------------------------------------*/
12530 /* genSystemRTCRegisters - */
12531 /*-----------------------------------------------------------------*/
12532 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12538 assert (nparms==1);
12539 /* save registers that need to be saved */
12540 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12541 ds390_rUmaskForOp (IC_RESULT(ic))));
12544 /* put pointer in DPTR */
12545 aopOp (pp,ic,FALSE,FALSE);
12546 if (AOP_TYPE (pp) == AOP_IMMD) {
12547 emitcode ("mov","dps,#1");
12548 emitcode ("mov", "dptr,%s",
12549 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12550 emitcode ("mov","dps,#0");
12552 emitcode ("mov","dpl1,%s",
12553 aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12554 emitcode ("mov","dph1,%s",
12555 aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12556 emitcode ("mov","dpx1,%s",
12557 aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12559 freeAsmop (pp, NULL, ic, FALSE);
12561 /* make the call */
12562 emitcode ("lcall","System_%sRTCRegisters",name);
12564 unsavermask(rsave);
12567 /*-----------------------------------------------------------------*/
12568 /* genSystemThreadSleep - */
12569 /*-----------------------------------------------------------------*/
12570 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12575 assert (nparms==1);
12576 /* save registers that need to be saved */
12577 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12578 ds390_rUmaskForOp (IC_RESULT(ic))));
12581 aopOp(to,ic,FALSE,FALSE);
12582 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12583 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12584 emitcode ("push","%s",
12585 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12586 emitcode ("push","%s",
12587 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12588 emitcode ("push","%s",
12589 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12590 emitcode ("push","%s",
12591 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12592 emitcode ("pop","ar3");
12593 emitcode ("pop","ar2");
12594 emitcode ("pop","ar1");
12595 emitcode ("pop","ar0");
12597 emitcode ("mov","r0,%s",
12598 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12599 emitcode ("mov","r1,%s",
12600 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12601 emitcode ("mov","r2,%s",
12602 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12603 emitcode ("mov","r3,%s",
12604 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12606 freeAsmop (to, NULL, ic, FALSE);
12608 /* suspend in acc */
12610 aopOp(s,ic,FALSE,FALSE);
12611 emitcode ("mov","a,%s",
12612 aopGet(AOP(s),0,FALSE,TRUE,NULL));
12613 freeAsmop (s, NULL, ic, FALSE);
12615 /* make the call */
12616 emitcode ("lcall","System_%s",name);
12618 unsavermask(rsave);
12621 /*-----------------------------------------------------------------*/
12622 /* genSystemThreadResume - */
12623 /*-----------------------------------------------------------------*/
12624 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12629 assert (nparms==2);
12630 /* save registers that need to be saved */
12631 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12632 ds390_rUmaskForOp (IC_RESULT(ic))));
12638 aopOp(pid,ic,FALSE,FALSE);
12639 emitcode ("mov","r0,%s",
12640 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12641 freeAsmop (pid, NULL, ic, FALSE);
12644 aopOp(tid,ic,FALSE,FALSE);
12645 emitcode ("mov","a,%s",
12646 aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12647 freeAsmop (tid, NULL, ic, FALSE);
12649 emitcode ("lcall","System_ThreadResume");
12651 /* put result into place */
12653 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12654 if (rsym->liveFrom != rsym->liveTo) {
12655 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12656 aopPut(AOP(IC_RESULT(ic)),"a",0);
12657 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12660 unsavermask(rsave);
12663 /*-----------------------------------------------------------------*/
12664 /* genSystemProcessResume - */
12665 /*-----------------------------------------------------------------*/
12666 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12671 assert (nparms==1);
12672 /* save registers that need to be saved */
12673 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12674 ds390_rUmaskForOp (IC_RESULT(ic))));
12679 aopOp(pid,ic,FALSE,FALSE);
12680 emitcode ("mov","a,%s",
12681 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12682 freeAsmop (pid, NULL, ic, FALSE);
12684 emitcode ("lcall","System_ProcessResume");
12686 unsavermask(rsave);
12689 /*-----------------------------------------------------------------*/
12691 /*-----------------------------------------------------------------*/
12692 static void genSystem (iCode *ic,int nparms,char *name)
12694 assert(nparms == 0);
12696 emitcode ("lcall","System_%s",name);
12699 /*-----------------------------------------------------------------*/
12700 /* genSystemPoll - */
12701 /*-----------------------------------------------------------------*/
12702 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12707 assert (nparms==1);
12708 /* save registers that need to be saved */
12709 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12710 ds390_rUmaskForOp (IC_RESULT(ic))));
12713 aopOp (fp,ic,FALSE,FALSE);
12714 if (AOP_TYPE (fp) == AOP_IMMD) {
12715 emitcode ("mov", "dptr,%s",
12716 aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12717 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12718 emitcode ("mov","dpl,%s",
12719 aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12720 emitcode ("mov","dph,%s",
12721 aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12722 emitcode ("mov","dpx,%s",
12723 aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12725 freeAsmop (fp, NULL, ic, FALSE);
12727 emitcode ("lcall","System_%sPoll",name);
12729 /* put result into place */
12731 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12732 if (rsym->liveFrom != rsym->liveTo) {
12733 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12734 aopPut(AOP(IC_RESULT(ic)),"a",0);
12735 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12738 unsavermask(rsave);
12741 /*-----------------------------------------------------------------*/
12742 /* genSystemGetCurrentID - */
12743 /*-----------------------------------------------------------------*/
12744 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12746 assert (nparms==0);
12748 emitcode ("lcall","System_GetCurrent%sId",name);
12749 /* put result into place */
12751 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12752 if (rsym->liveFrom != rsym->liveTo) {
12753 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12754 aopPut(AOP(IC_RESULT(ic)),"a",0);
12755 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12760 /*-----------------------------------------------------------------*/
12761 /* genDummyRead - generate code for dummy read of volatiles */
12762 /*-----------------------------------------------------------------*/
12764 genDummyRead (iCode * ic)
12769 D(emitcode("; genDummyRead",""));
12771 op = IC_RIGHT (ic);
12772 if (op && IS_SYMOP (op))
12774 aopOp (op, ic, FALSE, FALSE);
12776 /* if the result is a bit */
12777 if (AOP_TYPE (op) == AOP_CRY)
12778 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
12781 /* bit variables done */
12783 size = AOP_SIZE (op);
12787 MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
12792 freeAsmop (op, NULL, ic, TRUE);
12796 if (op && IS_SYMOP (op))
12798 aopOp (op, ic, FALSE, FALSE);
12800 /* if the result is a bit */
12801 if (AOP_TYPE (op) == AOP_CRY)
12802 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
12805 /* bit variables done */
12807 size = AOP_SIZE (op);
12811 MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
12816 freeAsmop (op, NULL, ic, TRUE);
12821 /*-----------------------------------------------------------------*/
12822 /* genCritical - generate code for start of a critical sequence */
12823 /*-----------------------------------------------------------------*/
12825 genCritical (iCode *ic)
12827 symbol *tlbl = newiTempLabel (NULL);
12829 D(emitcode("; genCritical",""));
12831 if (IC_RESULT (ic))
12832 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
12834 emitcode ("setb", "c");
12835 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
12836 emitcode ("clr", "c");
12837 emitcode ("", "%05d$:", (tlbl->key + 100));
12839 if (IC_RESULT (ic))
12840 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
12842 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
12844 if (IC_RESULT (ic))
12845 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
12848 /*-----------------------------------------------------------------*/
12849 /* genEndCritical - generate code for end of a critical sequence */
12850 /*-----------------------------------------------------------------*/
12852 genEndCritical (iCode *ic)
12854 D(emitcode("; genEndCritical",""));
12858 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
12859 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
12861 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
12862 emitcode ("mov", "ea,c");
12866 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE));
12867 emitcode ("rrc", "a");
12868 emitcode ("mov", "ea,c");
12870 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
12874 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
12875 emitcode ("mov", "ea,c");
12881 /*-----------------------------------------------------------------*/
12882 /* genBuiltIn - calls the appropriate function to generating code */
12883 /* for a built in function */
12884 /*-----------------------------------------------------------------*/
12885 static void genBuiltIn (iCode *ic)
12887 operand *bi_parms[MAX_BUILTIN_ARGS];
12892 /* get all the arguments for a built in function */
12893 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12895 /* which function is it */
12896 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12897 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12898 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12899 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12900 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12901 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12902 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12903 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12904 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12905 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12906 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12907 } else if (strcmp(bif->name,"__builtin_inp")==0) {
12908 genInp(bi_iCode,nbi_parms,bi_parms);
12909 } else if (strcmp(bif->name,"__builtin_outp")==0) {
12910 genOutp(bi_iCode,nbi_parms,bi_parms);
12911 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12912 genSwapW(bi_iCode,nbi_parms,bi_parms);
12913 /* JavaNative builtIns */
12914 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12915 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12916 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12917 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12918 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12919 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12920 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12921 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12922 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12923 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12924 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12925 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12926 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12927 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12928 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12929 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12930 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12931 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12932 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12933 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12934 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12935 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12936 } else if (strcmp(bif->name,"MM_Malloc")==0) {
12937 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12938 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12939 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12940 } else if (strcmp(bif->name,"MM_Free")==0) {
12941 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12942 } else if (strcmp(bif->name,"MM_Deref")==0) {
12943 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12944 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12945 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12946 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12947 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12948 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12949 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12950 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12951 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12952 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12953 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12954 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12955 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12956 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12957 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12958 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12959 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12960 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12961 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12962 } else if (strcmp(bif->name,"System_SaveThread")==0) {
12963 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12964 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12965 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12966 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12967 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12968 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12969 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12970 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12971 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12972 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12973 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12974 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12975 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12976 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12977 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12978 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12979 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12980 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12981 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12982 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12983 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12985 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12991 /*-----------------------------------------------------------------*/
12992 /* gen390Code - generate code for Dallas 390 based controllers */
12993 /*-----------------------------------------------------------------*/
12995 gen390Code (iCode * lic)
13000 lineHead = lineCurr = NULL;
13001 dptrn[1][0] = "dpl1";
13002 dptrn[1][1] = "dph1";
13003 dptrn[1][2] = "dpx1";
13005 if (options.model == MODEL_FLAT24) {
13006 fReturnSizeDS390 = 5;
13007 fReturn = fReturn24;
13009 fReturnSizeDS390 = 4;
13010 fReturn = fReturn16;
13011 options.stack10bit=0;
13014 /* print the allocation information */
13015 if (allocInfo && currFunc)
13016 printAllocInfo (currFunc, codeOutFile);
13018 /* if debug information required */
13019 if (options.debug && currFunc)
13021 debugFile->writeFunction(currFunc);
13023 if (IS_STATIC (currFunc->etype))
13024 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
13026 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
13029 /* stack pointer name */
13030 if (options.useXstack)
13036 for (ic = lic; ic; ic = ic->next)
13039 if (ic->lineno && cln != ic->lineno)
13044 emitcode ("", "C$%s$%d$%d$%d ==.",
13045 FileBaseName (ic->filename), ic->lineno,
13046 ic->level, ic->block);
13049 if (!options.noCcodeInAsm) {
13050 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
13051 printCLine(ic->filename, ic->lineno));
13055 if (options.iCodeInAsm) {
13056 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
13058 /* if the result is marked as
13059 spilt and rematerializable or code for
13060 this has already been generated then
13062 if (resultRemat (ic) || ic->generated)
13065 /* depending on the operation */
13085 /* IPOP happens only when trying to restore a
13086 spilt live range, if there is an ifx statement
13087 following this pop then the if statement might
13088 be using some of the registers being popped which
13089 would destory the contents of the register so
13090 we need to check for this condition and handle it */
13092 ic->next->op == IFX &&
13093 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
13094 genIfx (ic->next, ic);
13112 genEndFunction (ic);
13132 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
13149 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
13153 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
13160 /* note these two are xlated by algebraic equivalence
13161 during parsing SDCC.y */
13162 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13163 "got '>=' or '<=' shouldn't have come here");
13167 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
13179 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
13183 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
13187 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
13211 genRightShift (ic);
13214 case GET_VALUE_AT_ADDRESS:
13215 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13219 if (POINTER_SET (ic))
13220 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13246 if (ic->builtinSEND) genBuiltIn(ic);
13247 else addSet (&_G.sendSet, ic);
13250 case DUMMY_READ_VOLATILE:
13259 genEndCritical (ic);
13266 #if 0 // obsolete, and buggy for != xdata
13278 /* now we are ready to call the
13279 peep hole optimizer */
13280 if (!options.nopeep)
13281 peepHole (&lineHead);
13283 /* now do the actual printing */
13284 printLine (lineHead, codeOutFile);