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)) ||
3958 isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3960 // D(emitcode(";", "aopOp3: (left | right) & result equal"););
3961 aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3965 // Operands may be equivalent (but not equal) if they share a spill location. If
3966 // so, use the same DPTR or DPTR2.
3967 if (operandsEqu (IC_LEFT(ic), IC_RESULT(ic)))
3969 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
3972 if (operandsEqu (IC_RIGHT(ic), IC_RESULT(ic)))
3974 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
3978 // Note which dptrs are currently in use.
3979 dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3980 dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3982 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
3984 if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3989 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3990 if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3995 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
3996 if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
4001 aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
4003 // Some sanity checking...
4004 if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
4007 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
4008 __FILE__, __LINE__, ic->filename, ic->lineno);
4009 emitcode(";", ">>> unexpected DPTR here.");
4012 if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
4015 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
4016 __FILE__, __LINE__, ic->filename, ic->lineno);
4017 emitcode(";", ">>> unexpected DPTR2 here.");
4023 // Macro to aopOp all three operands of an ic. If this cannot be done,
4024 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
4025 // will be set TRUE. The caller must then handle the case specially, noting
4026 // that the IC_RESULT operand is not aopOp'd.
4028 #define AOP_OP_3_NOFATAL(ic, rc) \
4029 do { rc = !aopOp3(ic); } while (0)
4031 // aopOp the left & right operands of an ic.
4032 #define AOP_OP_2(ic) \
4033 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
4034 aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
4036 // convienience macro.
4037 #define AOP_SET_LOCALS(ic) \
4038 left = IC_LEFT(ic); \
4039 right = IC_RIGHT(ic); \
4040 result = IC_RESULT(ic);
4043 // Given an integer value of pushedSize bytes on the stack,
4044 // adjust it to be resultSize bytes, either by discarding
4045 // the most significant bytes or by zero-padding.
4047 // On exit from this macro, pushedSize will have been adjusted to
4048 // equal resultSize, and ACC may be trashed.
4049 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
4050 /* If the pushed data is bigger than the result, \
4051 * simply discard unused bytes. Icky, but works. \
4053 while (pushedSize > resultSize) \
4055 D (emitcode (";", "discarding unused result byte."););\
4056 emitcode ("pop", "acc"); \
4059 if (pushedSize < resultSize) \
4061 emitcode ("clr", "a"); \
4062 /* Conversly, we haven't pushed enough here. \
4063 * just zero-pad, and all is well. \
4065 while (pushedSize < resultSize) \
4067 emitcode("push", "acc"); \
4071 assert(pushedSize == resultSize);
4073 /*-----------------------------------------------------------------*/
4074 /* genPlus - generates code for addition */
4075 /*-----------------------------------------------------------------*/
4077 genPlus (iCode * ic)
4079 int size, offset = 0;
4083 D (emitcode (";", "genPlus "););
4085 /* special cases :- */
4086 if ( AOP_IS_STR(IC_LEFT(ic)) &&
4087 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4088 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4089 size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4091 while (size--) emitcode ("inc","dptr");
4093 emitcode ("mov","a,dpl");
4094 emitcode ("add","a,#!constbyte",size & 0xff);
4095 emitcode ("mov","dpl,a");
4096 emitcode ("mov","a,dph");
4097 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4098 emitcode ("mov","dph,a");
4099 emitcode ("mov","a,dpx");
4100 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4101 emitcode ("mov","dpx,a");
4103 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4106 if ( IS_SYMOP(IC_LEFT(ic)) &&
4107 OP_SYMBOL(IC_LEFT(ic))->remat &&
4108 isOperandInFarSpace(IC_RIGHT(ic))) {
4109 operand *op = IC_RIGHT(ic);
4110 IC_RIGHT(ic) = IC_LEFT(ic);
4114 AOP_OP_3_NOFATAL (ic, pushResult);
4118 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4123 /* if literal, literal on the right or
4124 if left requires ACC or right is already
4126 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4127 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4128 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4130 operand *t = IC_RIGHT (ic);
4131 IC_RIGHT (ic) = IC_LEFT (ic);
4133 emitcode (";", "Swapped plus args.");
4136 /* if both left & right are in bit
4138 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4139 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4145 /* if left in bit space & right literal */
4146 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4147 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4149 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4150 /* if result in bit space */
4151 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4153 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4154 emitcode ("cpl", "c");
4155 outBitC (IC_RESULT (ic));
4159 size = getDataSize (IC_RESULT (ic));
4160 _startLazyDPSEvaluation ();
4163 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4164 emitcode ("addc", "a,#0");
4165 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4167 _endLazyDPSEvaluation ();
4172 /* if I can do an increment instead
4173 of add then GOOD for ME */
4174 if (genPlusIncr (ic) == TRUE)
4176 emitcode (";", "did genPlusIncr");
4181 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4183 _startLazyDPSEvaluation ();
4186 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4188 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4190 emitcode ("add", "a,%s",
4191 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4193 emitcode ("addc", "a,%s",
4194 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4198 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4200 /* right is going to use ACC or we would have taken the
4203 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4205 D(emitcode(";", "+ AOP_ACC special case."););
4206 emitcode("xch", "a, %s", DP2_RESULT_REG);
4208 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4211 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4214 emitcode("add", "a, %s", DP2_RESULT_REG);
4218 emitcode ("add", "a,%s",
4219 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4225 emitcode ("addc", "a,%s",
4226 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4232 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4236 emitcode ("push", "acc");
4240 _endLazyDPSEvaluation ();
4244 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4246 size = getDataSize (IC_LEFT (ic));
4247 rSize = getDataSize (IC_RESULT (ic));
4249 ADJUST_PUSHED_RESULT(size, rSize);
4251 _startLazyDPSEvaluation ();
4254 emitcode ("pop", "acc");
4255 aopPut (AOP (IC_RESULT (ic)), "a", size);
4257 _endLazyDPSEvaluation ();
4260 adjustArithmeticResult (ic);
4263 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4264 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4265 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4268 /*-----------------------------------------------------------------*/
4269 /* genMinusDec :- does subtraction with deccrement if possible */
4270 /*-----------------------------------------------------------------*/
4272 genMinusDec (iCode * ic)
4274 unsigned int icount;
4275 unsigned int size = getDataSize (IC_RESULT (ic));
4277 /* will try to generate an increment */
4278 /* if the right side is not a literal
4280 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4283 /* if the literal value of the right hand side
4284 is greater than 4 then it is not worth it */
4285 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4288 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4289 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4291 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4295 /* if decrement 16 bits in register */
4296 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4297 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4298 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4307 /* If the next instruction is a goto and the goto target
4308 * is <= 5 instructions previous to this, we can generate
4309 * jumps straight to that target.
4311 if (ic->next && ic->next->op == GOTO
4312 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4315 emitcode (";", "tail decrement optimized (range %d)", labelRange);
4316 tlbl = IC_LABEL (ic->next);
4321 tlbl = newiTempLabel (NULL);
4325 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4326 emitcode ("dec", "%s", l);
4328 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4329 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4330 IS_AOP_PREG (IC_RESULT (ic)))
4332 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4336 emitcode ("mov", "a,#!constbyte",0xff);
4337 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4339 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4340 emitcode ("dec", "%s", l);
4343 if (!strcmp(l, "acc"))
4345 emitcode("jnz", "!tlabel", tlbl->key + 100);
4347 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4348 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4349 IS_AOP_PREG (IC_RESULT (ic)))
4351 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4355 emitcode ("mov", "a,#!constbyte",0xff);
4356 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4358 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4359 emitcode ("dec", "%s", l);
4363 if (!strcmp(l, "acc"))
4365 emitcode("jnz", "!tlabel", tlbl->key + 100);
4367 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4368 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4369 IS_AOP_PREG (IC_RESULT (ic)))
4371 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4375 emitcode ("mov", "a,#!constbyte",0xff);
4376 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4378 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4379 emitcode ("dec", "%s", l);
4383 emitcode ("", "!tlabeldef", tlbl->key + 100);
4388 /* if the sizes are greater than 1 then we cannot */
4389 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4390 AOP_SIZE (IC_LEFT (ic)) > 1)
4393 /* we can if the aops of the left & result match or
4394 if they are in registers and the registers are the
4397 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4398 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4399 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4402 _startLazyDPSEvaluation ();
4405 emitcode ("dec", "%s",
4406 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4408 _endLazyDPSEvaluation ();
4416 /*-----------------------------------------------------------------*/
4417 /* addSign - complete with sign */
4418 /*-----------------------------------------------------------------*/
4420 addSign (operand * result, int offset, int sign)
4422 int size = (getDataSize (result) - offset);
4425 _startLazyDPSEvaluation();
4428 emitcode ("rlc", "a");
4429 emitcode ("subb", "a,acc");
4432 aopPut (AOP (result), "a", offset++);
4439 aopPut (AOP (result), zero, offset++);
4442 _endLazyDPSEvaluation();
4446 /*-----------------------------------------------------------------*/
4447 /* genMinusBits - generates code for subtraction of two bits */
4448 /*-----------------------------------------------------------------*/
4450 genMinusBits (iCode * ic)
4452 symbol *lbl = newiTempLabel (NULL);
4454 D (emitcode (";", "genMinusBits "););
4456 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4458 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4459 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4460 emitcode ("cpl", "c");
4461 emitcode ("", "!tlabeldef", (lbl->key + 100));
4462 outBitC (IC_RESULT (ic));
4466 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4467 emitcode ("subb", "a,acc");
4468 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4469 emitcode ("inc", "a");
4470 emitcode ("", "!tlabeldef", (lbl->key + 100));
4471 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4472 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4476 /*-----------------------------------------------------------------*/
4477 /* genMinus - generates code for subtraction */
4478 /*-----------------------------------------------------------------*/
4480 genMinus (iCode * ic)
4482 int size, offset = 0;
4487 D (emitcode (";", "genMinus "););
4489 AOP_OP_3_NOFATAL(ic, pushResult);
4493 /* special cases :- */
4494 /* if both left & right are in bit space */
4495 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4496 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4502 /* if I can do an decrement instead
4503 of subtract then GOOD for ME */
4504 if (genMinusDec (ic) == TRUE)
4509 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4511 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4517 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4522 /* if literal, add a,#-lit, else normal subb */
4523 _startLazyDPSEvaluation ();
4525 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4526 if (AOP_USESDPTR(IC_RIGHT(ic))) {
4527 emitcode ("mov","b,%s",
4528 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4529 MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4530 emitcode ("subb","a,b");
4532 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4533 emitcode ("subb", "a,%s",
4534 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE,
4538 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4539 /* first add without previous c */
4541 if (!size && lit==-1) {
4542 emitcode ("dec", "a");
4544 emitcode ("add", "a,#!constbyte",
4545 (unsigned int) (lit & 0x0FFL));
4548 emitcode ("addc", "a,#!constbyte",
4549 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4554 emitcode ("push", "acc");
4556 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4560 _endLazyDPSEvaluation ();
4564 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4566 size = getDataSize (IC_LEFT (ic));
4567 rSize = getDataSize (IC_RESULT (ic));
4569 ADJUST_PUSHED_RESULT(size, rSize);
4571 _startLazyDPSEvaluation ();
4574 emitcode ("pop", "acc");
4575 aopPut (AOP (IC_RESULT (ic)), "a", size);
4577 _endLazyDPSEvaluation ();
4580 adjustArithmeticResult (ic);
4583 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4584 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4585 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4589 /*-----------------------------------------------------------------*/
4590 /* genMultbits :- multiplication of bits */
4591 /*-----------------------------------------------------------------*/
4593 genMultbits (operand * left,
4598 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4599 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4600 aopOp(result, ic, TRUE, FALSE);
4605 /*-----------------------------------------------------------------*/
4606 /* genMultOneByte : 8*8=8/16 bit multiplication */
4607 /*-----------------------------------------------------------------*/
4609 genMultOneByte (operand * left,
4614 sym_link *opetype = operandType (result);
4618 /* (if two literals: the value is computed before) */
4619 /* if one literal, literal on the right */
4620 if (AOP_TYPE (left) == AOP_LIT)
4625 emitcode (";", "swapped left and right");
4628 if (SPEC_USIGN(opetype)
4629 // ignore the sign of left and right, what else can we do?
4630 || (SPEC_USIGN(operandType(left)) &&
4631 SPEC_USIGN(operandType(right)))) {
4632 // just an unsigned 8*8=8/16 multiply
4633 //emitcode (";","unsigned");
4634 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4635 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4636 emitcode ("mul", "ab");
4638 _G.accInUse++; _G.bInUse++;
4639 aopOp(result, ic, TRUE, FALSE);
4641 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4643 // this should never happen
4644 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4645 AOP_SIZE(result), __FILE__, lineno);
4649 aopPut (AOP (result), "a", 0);
4650 _G.accInUse--; _G.bInUse--;
4651 if (AOP_SIZE(result)==2)
4653 aopPut (AOP (result), "b", 1);
4658 // we have to do a signed multiply
4660 emitcode (";", "signed");
4661 emitcode ("clr", "F0"); // reset sign flag
4662 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4664 lbl=newiTempLabel(NULL);
4665 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4666 // left side is negative, 8-bit two's complement, this fails for -128
4667 emitcode ("setb", "F0"); // set sign flag
4668 emitcode ("cpl", "a");
4669 emitcode ("inc", "a");
4671 emitcode ("", "!tlabeldef", lbl->key+100);
4674 if (AOP_TYPE(right)==AOP_LIT) {
4675 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
4676 /* AND literal negative */
4677 if ((int) val < 0) {
4678 emitcode ("cpl", "F0"); // complement sign flag
4679 emitcode ("mov", "b,#!constbyte", -val);
4681 emitcode ("mov", "b,#!constbyte", val);
4684 lbl=newiTempLabel(NULL);
4685 emitcode ("mov", "b,a");
4686 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4687 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4688 // right side is negative, 8-bit two's complement
4689 emitcode ("cpl", "F0"); // complement sign flag
4690 emitcode ("cpl", "a");
4691 emitcode ("inc", "a");
4692 emitcode ("", "!tlabeldef", lbl->key+100);
4694 emitcode ("mul", "ab");
4696 _G.accInUse++;_G.bInUse++;
4697 aopOp(result, ic, TRUE, FALSE);
4699 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4701 // this should never happen
4702 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4703 AOP_SIZE(result), __FILE__, lineno);
4707 lbl=newiTempLabel(NULL);
4708 emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4709 // only ONE op was negative, we have to do a 8/16-bit two's complement
4710 emitcode ("cpl", "a"); // lsb
4711 if (AOP_SIZE(result)==1) {
4712 emitcode ("inc", "a");
4714 emitcode ("add", "a,#1");
4715 emitcode ("xch", "a,b");
4716 emitcode ("cpl", "a"); // msb
4717 emitcode ("addc", "a,#0");
4718 emitcode ("xch", "a,b");
4721 emitcode ("", "!tlabeldef", lbl->key+100);
4722 aopPut (AOP (result), "a", 0);
4723 _G.accInUse--;_G.bInUse--;
4724 if (AOP_SIZE(result)==2) {
4725 aopPut (AOP (result), "b", 1);
4729 /*-----------------------------------------------------------------*/
4730 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4731 /*-----------------------------------------------------------------*/
4732 static void genMultTwoByte (operand *left, operand *right,
4733 operand *result, iCode *ic)
4735 sym_link *retype = getSpec(operandType(right));
4736 sym_link *letype = getSpec(operandType(left));
4737 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4740 if (AOP_TYPE (left) == AOP_LIT) {
4745 /* save EA bit in F1 */
4746 lbl = newiTempLabel(NULL);
4747 emitcode ("setb","F1");
4748 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4749 emitcode ("clr","F1");
4750 emitcode("","!tlabeldef",lbl->key+100);
4752 /* load up MB with right */
4754 emitcode("clr","F0");
4755 if (AOP_TYPE(right) == AOP_LIT) {
4756 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4758 emitcode("setb","F0");
4761 emitcode ("mov","mb,#!constbyte",val & 0xff);
4762 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4764 lbl = newiTempLabel(NULL);
4765 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4766 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4767 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4768 emitcode ("xch", "a,b");
4769 emitcode ("cpl","a");
4770 emitcode ("add", "a,#1");
4771 emitcode ("xch", "a,b");
4772 emitcode ("cpl", "a"); // msb
4773 emitcode ("addc", "a,#0");
4774 emitcode ("setb","F0");
4775 emitcode ("","!tlabeldef",lbl->key+100);
4776 emitcode ("mov","mb,b");
4777 emitcode ("mov","mb,a");
4780 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4781 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4783 /* load up MA with left */
4785 lbl = newiTempLabel(NULL);
4786 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4787 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4788 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4789 emitcode ("xch", "a,b");
4790 emitcode ("cpl","a");
4791 emitcode ("add", "a,#1");
4792 emitcode ("xch", "a,b");
4793 emitcode ("cpl", "a"); // msb
4794 emitcode ("addc","a,#0");
4795 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4796 emitcode ("setb","F0");
4797 emitcode ("","!tlabeldef",lbl->key+100);
4798 emitcode ("mov","ma,b");
4799 emitcode ("mov","ma,a");
4801 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4802 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4804 /* wait for multiplication to finish */
4805 lbl = newiTempLabel(NULL);
4806 emitcode("","!tlabeldef", lbl->key+100);
4807 emitcode("mov","a,mcnt1");
4808 emitcode("anl","a,#!constbyte",0x80);
4809 emitcode("jnz","!tlabel",lbl->key+100);
4811 freeAsmop (left, NULL, ic, TRUE);
4812 freeAsmop (right, NULL, ic,TRUE);
4813 aopOp(result, ic, TRUE, FALSE);
4815 /* if unsigned then simple */
4817 emitcode ("mov","a,ma");
4818 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4819 emitcode ("mov","a,ma");
4820 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4821 aopPut(AOP(result),"ma",1);
4822 aopPut(AOP(result),"ma",0);
4824 emitcode("push","ma");
4825 emitcode("push","ma");
4826 emitcode("push","ma");
4828 /* negate result if needed */
4829 lbl = newiTempLabel(NULL);
4830 emitcode("jnb","F0,!tlabel",lbl->key+100);
4831 emitcode("cpl","a");
4832 emitcode("add","a,#1");
4833 emitcode("","!tlabeldef", lbl->key+100);
4834 if (AOP_TYPE(result) == AOP_ACC)
4836 D(emitcode(";", "ACC special case."););
4837 /* We know result is the only live aop, and
4838 * it's obviously not a DPTR2, so AP is available.
4840 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4844 aopPut(AOP(result),"a",0);
4847 emitcode("pop","acc");
4848 lbl = newiTempLabel(NULL);
4849 emitcode("jnb","F0,!tlabel",lbl->key+100);
4850 emitcode("cpl","a");
4851 emitcode("addc","a,#0");
4852 emitcode("","!tlabeldef", lbl->key+100);
4853 aopPut(AOP(result),"a",1);
4854 emitcode("pop","acc");
4855 if (AOP_SIZE(result) >= 3) {
4856 lbl = newiTempLabel(NULL);
4857 emitcode("jnb","F0,!tlabel",lbl->key+100);
4858 emitcode("cpl","a");
4859 emitcode("addc","a,#0");
4860 emitcode("","!tlabeldef", lbl->key+100);
4861 aopPut(AOP(result),"a",2);
4863 emitcode("pop","acc");
4864 if (AOP_SIZE(result) >= 4) {
4865 lbl = newiTempLabel(NULL);
4866 emitcode("jnb","F0,!tlabel",lbl->key+100);
4867 emitcode("cpl","a");
4868 emitcode("addc","a,#0");
4869 emitcode("","!tlabeldef", lbl->key+100);
4870 aopPut(AOP(result),"a",3);
4872 if (AOP_TYPE(result) == AOP_ACC)
4874 /* We stashed the result away above. */
4875 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4879 freeAsmop (result, NULL, ic, TRUE);
4881 /* restore EA bit in F1 */
4882 lbl = newiTempLabel(NULL);
4883 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4884 emitcode ("setb","EA");
4885 emitcode("","!tlabeldef",lbl->key+100);
4889 /*-----------------------------------------------------------------*/
4890 /* genMult - generates code for multiplication */
4891 /*-----------------------------------------------------------------*/
4893 genMult (iCode * ic)
4895 operand *left = IC_LEFT (ic);
4896 operand *right = IC_RIGHT (ic);
4897 operand *result = IC_RESULT (ic);
4899 D (emitcode (";", "genMult "););
4901 /* assign the amsops */
4904 /* special cases first */
4906 if (AOP_TYPE (left) == AOP_CRY &&
4907 AOP_TYPE (right) == AOP_CRY)
4909 genMultbits (left, right, result, ic);
4913 /* if both are of size == 1 */
4914 if (AOP_SIZE (left) == 1 &&
4915 AOP_SIZE (right) == 1)
4917 genMultOneByte (left, right, result, ic);
4921 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4922 /* use the ds390 ARITHMETIC accel UNIT */
4923 genMultTwoByte (left, right, result, ic);
4926 /* should have been converted to function call */
4930 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4931 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4932 freeAsmop (result, NULL, ic, TRUE);
4935 /*-----------------------------------------------------------------*/
4936 /* genDivbits :- division of bits */
4937 /*-----------------------------------------------------------------*/
4939 genDivbits (operand * left,
4947 /* the result must be bit */
4948 LOAD_AB_FOR_DIV (left, right, l);
4949 emitcode ("div", "ab");
4950 emitcode ("rrc", "a");
4951 aopOp(result, ic, TRUE, FALSE);
4953 aopPut (AOP (result), "c", 0);
4956 /*-----------------------------------------------------------------*/
4957 /* genDivOneByte : 8 bit division */
4958 /*-----------------------------------------------------------------*/
4960 genDivOneByte (operand * left,
4965 sym_link *opetype = operandType (result);
4971 /* signed or unsigned */
4972 if (SPEC_USIGN (opetype))
4974 /* unsigned is easy */
4975 LOAD_AB_FOR_DIV (left, right, l);
4976 emitcode ("div", "ab");
4979 aopOp(result, ic, TRUE, FALSE);
4980 aopPut (AOP (result), "a", 0);
4983 size = AOP_SIZE (result) - 1;
4987 aopPut (AOP (result), zero, offset++);
4992 /* signed is a little bit more difficult */
4994 /* save the signs of the operands */
4995 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4996 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4997 emitcode ("push", "acc"); /* save it on the stack */
4999 /* now sign adjust for both left & right */
5000 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5001 lbl = newiTempLabel (NULL);
5002 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5003 emitcode ("cpl", "a");
5004 emitcode ("inc", "a");
5005 emitcode ("", "!tlabeldef", (lbl->key + 100));
5006 emitcode ("mov", "b,a");
5008 /* sign adjust left side */
5009 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5011 lbl = newiTempLabel (NULL);
5012 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5013 emitcode ("cpl", "a");
5014 emitcode ("inc", "a");
5015 emitcode ("", "!tlabeldef", (lbl->key + 100));
5017 /* now the division */
5018 emitcode ("nop", "; workaround for DS80C390 div bug.");
5019 emitcode ("div", "ab");
5020 /* we are interested in the lower order
5022 emitcode ("mov", "b,a");
5023 lbl = newiTempLabel (NULL);
5024 emitcode ("pop", "acc");
5025 /* if there was an over flow we don't
5026 adjust the sign of the result */
5027 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5028 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5030 emitcode ("clr", "a");
5031 emitcode ("subb", "a,b");
5032 emitcode ("mov", "b,a");
5033 emitcode ("", "!tlabeldef", (lbl->key + 100));
5035 /* now we are done */
5036 _G.accInUse++; _G.bInUse++;
5037 aopOp(result, ic, TRUE, FALSE);
5039 aopPut (AOP (result), "b", 0);
5041 size = AOP_SIZE (result) - 1;
5045 emitcode ("mov", "c,b.7");
5046 emitcode ("subb", "a,acc");
5050 aopPut (AOP (result), "a", offset++);
5052 _G.accInUse--; _G.bInUse--;
5056 /*-----------------------------------------------------------------*/
5057 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
5058 /*-----------------------------------------------------------------*/
5059 static void genDivTwoByte (operand *left, operand *right,
5060 operand *result, iCode *ic)
5062 sym_link *retype = getSpec(operandType(right));
5063 sym_link *letype = getSpec(operandType(left));
5064 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5067 /* save EA bit in F1 */
5068 lbl = newiTempLabel(NULL);
5069 emitcode ("setb","F1");
5070 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5071 emitcode ("clr","F1");
5072 emitcode("","!tlabeldef",lbl->key+100);
5074 /* load up MA with left */
5076 emitcode("clr","F0");
5077 lbl = newiTempLabel(NULL);
5078 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5079 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5080 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5081 emitcode ("xch", "a,b");
5082 emitcode ("cpl","a");
5083 emitcode ("add", "a,#1");
5084 emitcode ("xch", "a,b");
5085 emitcode ("cpl", "a"); // msb
5086 emitcode ("addc","a,#0");
5087 emitcode ("setb","F0");
5088 emitcode ("","!tlabeldef",lbl->key+100);
5089 emitcode ("mov","ma,b");
5090 emitcode ("mov","ma,a");
5092 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5093 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5096 /* load up MB with right */
5098 if (AOP_TYPE(right) == AOP_LIT) {
5099 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5101 lbl = newiTempLabel(NULL);
5102 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5103 emitcode("setb","F0");
5104 emitcode ("","!tlabeldef",lbl->key+100);
5107 emitcode ("mov","mb,#!constbyte",val & 0xff);
5108 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5110 lbl = newiTempLabel(NULL);
5111 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5112 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5113 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5114 emitcode ("xch", "a,b");
5115 emitcode ("cpl","a");
5116 emitcode ("add", "a,#1");
5117 emitcode ("xch", "a,b");
5118 emitcode ("cpl", "a"); // msb
5119 emitcode ("addc", "a,#0");
5120 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5121 emitcode ("setb","F0");
5122 emitcode ("","!tlabeldef",lbl->key+100);
5123 emitcode ("mov","mb,b");
5124 emitcode ("mov","mb,a");
5127 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5128 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5131 /* wait for multiplication to finish */
5132 lbl = newiTempLabel(NULL);
5133 emitcode("","!tlabeldef", lbl->key+100);
5134 emitcode("mov","a,mcnt1");
5135 emitcode("anl","a,#!constbyte",0x80);
5136 emitcode("jnz","!tlabel",lbl->key+100);
5138 freeAsmop (left, NULL, ic, TRUE);
5139 freeAsmop (right, NULL, ic,TRUE);
5140 aopOp(result, ic, TRUE, FALSE);
5142 /* if unsigned then simple */
5144 aopPut(AOP(result),"ma",1);
5145 aopPut(AOP(result),"ma",0);
5147 emitcode("push","ma");
5149 /* negate result if needed */
5150 lbl = newiTempLabel(NULL);
5151 emitcode("jnb","F0,!tlabel",lbl->key+100);
5152 emitcode("cpl","a");
5153 emitcode("add","a,#1");
5154 emitcode("","!tlabeldef", lbl->key+100);
5155 aopPut(AOP(result),"a",0);
5156 emitcode("pop","acc");
5157 lbl = newiTempLabel(NULL);
5158 emitcode("jnb","F0,!tlabel",lbl->key+100);
5159 emitcode("cpl","a");
5160 emitcode("addc","a,#0");
5161 emitcode("","!tlabeldef", lbl->key+100);
5162 aopPut(AOP(result),"a",1);
5164 freeAsmop (result, NULL, ic, TRUE);
5165 /* restore EA bit in F1 */
5166 lbl = newiTempLabel(NULL);
5167 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5168 emitcode ("setb","EA");
5169 emitcode("","!tlabeldef",lbl->key+100);
5173 /*-----------------------------------------------------------------*/
5174 /* genDiv - generates code for division */
5175 /*-----------------------------------------------------------------*/
5179 operand *left = IC_LEFT (ic);
5180 operand *right = IC_RIGHT (ic);
5181 operand *result = IC_RESULT (ic);
5183 D (emitcode (";", "genDiv "););
5185 /* assign the amsops */
5188 /* special cases first */
5190 if (AOP_TYPE (left) == AOP_CRY &&
5191 AOP_TYPE (right) == AOP_CRY)
5193 genDivbits (left, right, result, ic);
5197 /* if both are of size == 1 */
5198 if (AOP_SIZE (left) == 1 &&
5199 AOP_SIZE (right) == 1)
5201 genDivOneByte (left, right, result, ic);
5205 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5206 /* use the ds390 ARITHMETIC accel UNIT */
5207 genDivTwoByte (left, right, result, ic);
5210 /* should have been converted to function call */
5213 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5214 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5215 freeAsmop (result, NULL, ic, TRUE);
5218 /*-----------------------------------------------------------------*/
5219 /* genModbits :- modulus of bits */
5220 /*-----------------------------------------------------------------*/
5222 genModbits (operand * left,
5230 /* the result must be bit */
5231 LOAD_AB_FOR_DIV (left, right, l);
5232 emitcode ("div", "ab");
5233 emitcode ("mov", "a,b");
5234 emitcode ("rrc", "a");
5235 aopOp(result, ic, TRUE, FALSE);
5236 aopPut (AOP (result), "c", 0);
5239 /*-----------------------------------------------------------------*/
5240 /* genModOneByte : 8 bit modulus */
5241 /*-----------------------------------------------------------------*/
5243 genModOneByte (operand * left,
5248 sym_link *opetype = operandType (result);
5252 /* signed or unsigned */
5253 if (SPEC_USIGN (opetype))
5255 /* unsigned is easy */
5256 LOAD_AB_FOR_DIV (left, right, l);
5257 emitcode ("div", "ab");
5258 aopOp(result, ic, TRUE, FALSE);
5259 aopPut (AOP (result), "b", 0);
5263 /* signed is a little bit more difficult */
5265 /* save the signs of the operands */
5266 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5268 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5269 emitcode ("push", "acc"); /* save it on the stack */
5271 /* now sign adjust for both left & right */
5272 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5274 lbl = newiTempLabel (NULL);
5275 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5276 emitcode ("cpl", "a");
5277 emitcode ("inc", "a");
5278 emitcode ("", "!tlabeldef", (lbl->key + 100));
5279 emitcode ("mov", "b,a");
5281 /* sign adjust left side */
5282 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5284 lbl = newiTempLabel (NULL);
5285 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5286 emitcode ("cpl", "a");
5287 emitcode ("inc", "a");
5288 emitcode ("", "!tlabeldef", (lbl->key + 100));
5290 /* now the multiplication */
5291 emitcode ("nop", "; workaround for DS80C390 div bug.");
5292 emitcode ("div", "ab");
5293 /* we are interested in the lower order
5295 lbl = newiTempLabel (NULL);
5296 emitcode ("pop", "acc");
5297 /* if there was an over flow we don't
5298 adjust the sign of the result */
5299 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5300 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5302 emitcode ("clr", "a");
5303 emitcode ("subb", "a,b");
5304 emitcode ("mov", "b,a");
5305 emitcode ("", "!tlabeldef", (lbl->key + 100));
5308 /* now we are done */
5309 aopOp(result, ic, TRUE, FALSE);
5310 aopPut (AOP (result), "b", 0);
5315 /*-----------------------------------------------------------------*/
5316 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
5317 /*-----------------------------------------------------------------*/
5318 static void genModTwoByte (operand *left, operand *right,
5319 operand *result, iCode *ic)
5321 sym_link *retype = getSpec(operandType(right));
5322 sym_link *letype = getSpec(operandType(left));
5323 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5326 /* load up MA with left */
5327 /* save EA bit in F1 */
5328 lbl = newiTempLabel(NULL);
5329 emitcode ("setb","F1");
5330 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5331 emitcode ("clr","F1");
5332 emitcode("","!tlabeldef",lbl->key+100);
5335 lbl = newiTempLabel(NULL);
5336 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5337 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5338 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5339 emitcode ("xch", "a,b");
5340 emitcode ("cpl","a");
5341 emitcode ("add", "a,#1");
5342 emitcode ("xch", "a,b");
5343 emitcode ("cpl", "a"); // msb
5344 emitcode ("addc","a,#0");
5345 emitcode ("","!tlabeldef",lbl->key+100);
5346 emitcode ("mov","ma,b");
5347 emitcode ("mov","ma,a");
5349 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5350 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5353 /* load up MB with right */
5355 if (AOP_TYPE(right) == AOP_LIT) {
5356 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5360 emitcode ("mov","mb,#!constbyte",val & 0xff);
5361 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5363 lbl = newiTempLabel(NULL);
5364 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5365 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5366 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5367 emitcode ("xch", "a,b");
5368 emitcode ("cpl","a");
5369 emitcode ("add", "a,#1");
5370 emitcode ("xch", "a,b");
5371 emitcode ("cpl", "a"); // msb
5372 emitcode ("addc", "a,#0");
5373 emitcode ("","!tlabeldef",lbl->key+100);
5374 emitcode ("mov","mb,b");
5375 emitcode ("mov","mb,a");
5378 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5379 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5382 /* wait for multiplication to finish */
5383 lbl = newiTempLabel(NULL);
5384 emitcode("","!tlabeldef", lbl->key+100);
5385 emitcode("mov","a,mcnt1");
5386 emitcode("anl","a,#!constbyte",0x80);
5387 emitcode("jnz","!tlabel",lbl->key+100);
5389 freeAsmop (left, NULL, ic, TRUE);
5390 freeAsmop (right, NULL, ic,TRUE);
5391 aopOp(result, ic, TRUE, FALSE);
5393 aopPut(AOP(result),"mb",1);
5394 aopPut(AOP(result),"mb",0);
5395 freeAsmop (result, NULL, ic, TRUE);
5397 /* restore EA bit in F1 */
5398 lbl = newiTempLabel(NULL);
5399 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5400 emitcode ("setb","EA");
5401 emitcode("","!tlabeldef",lbl->key+100);
5405 /*-----------------------------------------------------------------*/
5406 /* genMod - generates code for division */
5407 /*-----------------------------------------------------------------*/
5411 operand *left = IC_LEFT (ic);
5412 operand *right = IC_RIGHT (ic);
5413 operand *result = IC_RESULT (ic);
5415 D (emitcode (";", "genMod "); );
5417 /* assign the amsops */
5420 /* special cases first */
5422 if (AOP_TYPE (left) == AOP_CRY &&
5423 AOP_TYPE (right) == AOP_CRY)
5425 genModbits (left, right, result, ic);
5429 /* if both are of size == 1 */
5430 if (AOP_SIZE (left) == 1 &&
5431 AOP_SIZE (right) == 1)
5433 genModOneByte (left, right, result, ic);
5437 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5438 /* use the ds390 ARITHMETIC accel UNIT */
5439 genModTwoByte (left, right, result, ic);
5443 /* should have been converted to function call */
5447 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5448 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5449 freeAsmop (result, NULL, ic, TRUE);
5452 /*-----------------------------------------------------------------*/
5453 /* genIfxJump :- will create a jump depending on the ifx */
5454 /*-----------------------------------------------------------------*/
5456 genIfxJump (iCode * ic, char *jval)
5459 symbol *tlbl = newiTempLabel (NULL);
5462 D (emitcode (";", "genIfxJump"););
5464 /* if true label then we jump if condition
5468 jlbl = IC_TRUE (ic);
5469 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5470 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5474 /* false label is present */
5475 jlbl = IC_FALSE (ic);
5476 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5477 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5479 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5480 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5482 emitcode (inst, "!tlabel", tlbl->key + 100);
5483 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5484 emitcode ("", "!tlabeldef", tlbl->key + 100);
5486 /* mark the icode as generated */
5490 /*-----------------------------------------------------------------*/
5491 /* genCmp :- greater or less than comparison */
5492 /*-----------------------------------------------------------------*/
5494 genCmp (operand * left, operand * right,
5495 iCode * ic, iCode * ifx, int sign)
5497 int size, offset = 0;
5498 unsigned long lit = 0L;
5501 D (emitcode (";", "genCmp"););
5503 result = IC_RESULT (ic);
5505 /* if left & right are bit variables */
5506 if (AOP_TYPE (left) == AOP_CRY &&
5507 AOP_TYPE (right) == AOP_CRY)
5509 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5510 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5514 /* subtract right from left if at the
5515 end the carry flag is set then we know that
5516 left is greater than right */
5517 size = max (AOP_SIZE (left), AOP_SIZE (right));
5519 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5520 if ((size == 1) && !sign
5521 && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5523 symbol *lbl = newiTempLabel (NULL);
5524 emitcode ("cjne", "%s,%s,!tlabel",
5525 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5526 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5528 emitcode ("", "!tlabeldef", lbl->key + 100);
5532 if (AOP_TYPE (right) == AOP_LIT)
5534 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5535 /* optimize if(x < 0) or if(x >= 0) */
5544 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5546 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5547 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5549 aopOp (result, ic, FALSE, FALSE);
5551 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5553 freeAsmop (result, NULL, ic, TRUE);
5554 genIfxJump (ifx, "acc.7");
5559 emitcode ("rlc", "a");
5561 goto release_freedLR;
5569 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5570 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5571 // emitcode (";", "genCmp #2");
5572 if (sign && (size == 0))
5574 // emitcode (";", "genCmp #3");
5575 emitcode ("xrl", "a,#!constbyte",0x80);
5576 if (AOP_TYPE (right) == AOP_LIT)
5578 unsigned long lit = (unsigned long)
5579 floatFromVal (AOP (right)->aopu.aop_lit);
5580 // emitcode (";", "genCmp #3.1");
5581 emitcode ("subb", "a,#!constbyte",
5582 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5586 // emitcode (";", "genCmp #3.2");
5588 MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5589 saveAccWarn = DEFAULT_ACC_WARNING;
5590 emitcode ("xrl", "b,#!constbyte",0x80);
5591 emitcode ("subb", "a,b");
5598 // emitcode (";", "genCmp #4");
5600 s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5601 saveAccWarn = DEFAULT_ACC_WARNING;
5603 emitcode ("subb", "a,%s", s);
5610 /* Don't need the left & right operands any more; do need the result. */
5611 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5612 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5614 aopOp (result, ic, FALSE, FALSE);
5618 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5624 /* if the result is used in the next
5625 ifx conditional branch then generate
5626 code a little differently */
5629 genIfxJump (ifx, "c");
5635 /* leave the result in acc */
5637 freeAsmop (result, NULL, ic, TRUE);
5640 /*-----------------------------------------------------------------*/
5641 /* genCmpGt :- greater than comparison */
5642 /*-----------------------------------------------------------------*/
5644 genCmpGt (iCode * ic, iCode * ifx)
5646 operand *left, *right;
5647 sym_link *letype, *retype;
5650 D (emitcode (";", "genCmpGt ");
5653 left = IC_LEFT (ic);
5654 right = IC_RIGHT (ic);
5656 letype = getSpec (operandType (left));
5657 retype = getSpec (operandType (right));
5658 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5660 /* assign the left & right amsops */
5663 genCmp (right, left, ic, ifx, sign);
5666 /*-----------------------------------------------------------------*/
5667 /* genCmpLt - less than comparisons */
5668 /*-----------------------------------------------------------------*/
5670 genCmpLt (iCode * ic, iCode * ifx)
5672 operand *left, *right;
5673 sym_link *letype, *retype;
5676 D (emitcode (";", "genCmpLt "););
5678 left = IC_LEFT (ic);
5679 right = IC_RIGHT (ic);
5681 letype = getSpec (operandType (left));
5682 retype = getSpec (operandType (right));
5683 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5685 /* assign the left & right amsops */
5688 genCmp (left, right, ic, ifx, sign);
5691 /*-----------------------------------------------------------------*/
5692 /* gencjneshort - compare and jump if not equal */
5693 /*-----------------------------------------------------------------*/
5695 gencjneshort (operand * left, operand * right, symbol * lbl)
5697 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5699 unsigned long lit = 0L;
5701 D (emitcode (";", "gencjneshort");
5704 /* if the left side is a literal or
5705 if the right is in a pointer register and left
5707 if ((AOP_TYPE (left) == AOP_LIT) ||
5708 (AOP_TYPE (left) == AOP_IMMD) ||
5709 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5716 if (AOP_TYPE (right) == AOP_LIT)
5717 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5719 if (opIsGptr (left) || opIsGptr (right))
5721 /* We are comparing a generic pointer to something.
5722 * Exclude the generic type byte from the comparison.
5725 D (emitcode (";", "cjneshort: generic ptr special case."););
5729 /* if the right side is a literal then anything goes */
5730 if (AOP_TYPE (right) == AOP_LIT &&
5731 AOP_TYPE (left) != AOP_DIR)
5735 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5736 emitcode ("cjne", "a,%s,!tlabel",
5737 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5743 /* if the right side is in a register or in direct space or
5744 if the left is a pointer register & right is not */
5745 else if (AOP_TYPE (right) == AOP_REG ||
5746 AOP_TYPE (right) == AOP_DIR ||
5747 AOP_TYPE (right) == AOP_LIT ||
5748 AOP_TYPE (right) == AOP_IMMD ||
5749 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5750 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5754 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5755 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5756 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5757 emitcode ("jnz", "!tlabel", lbl->key + 100);
5759 emitcode ("cjne", "a,%s,!tlabel",
5760 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5767 /* right is a pointer reg need both a & b */
5770 MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5771 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5772 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5778 /*-----------------------------------------------------------------*/
5779 /* gencjne - compare and jump if not equal */
5780 /*-----------------------------------------------------------------*/
5782 gencjne (operand * left, operand * right, symbol * lbl)
5784 symbol *tlbl = newiTempLabel (NULL);
5786 D (emitcode (";", "gencjne");
5789 gencjneshort (left, right, lbl);
5791 emitcode ("mov", "a,%s", one);
5792 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5793 emitcode ("", "!tlabeldef", lbl->key + 100);
5794 emitcode ("clr", "a");
5795 emitcode ("", "!tlabeldef", tlbl->key + 100);
5798 /*-----------------------------------------------------------------*/
5799 /* genCmpEq - generates code for equal to */
5800 /*-----------------------------------------------------------------*/
5802 genCmpEq (iCode * ic, iCode * ifx)
5804 operand *left, *right, *result;
5806 D (emitcode (";", "genCmpEq ");
5810 AOP_SET_LOCALS (ic);
5812 /* if literal, literal on the right or
5813 if the right is in a pointer register and left
5815 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5816 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5818 operand *t = IC_RIGHT (ic);
5819 IC_RIGHT (ic) = IC_LEFT (ic);
5823 if (ifx && /* !AOP_SIZE(result) */
5824 OP_SYMBOL (result) &&
5825 OP_SYMBOL (result)->regType == REG_CND)
5828 /* if they are both bit variables */
5829 if (AOP_TYPE (left) == AOP_CRY &&
5830 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5832 if (AOP_TYPE (right) == AOP_LIT)
5834 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5837 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5838 emitcode ("cpl", "c");
5842 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5846 emitcode ("clr", "c");
5848 /* AOP_TYPE(right) == AOP_CRY */
5852 symbol *lbl = newiTempLabel (NULL);
5853 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5854 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5855 emitcode ("cpl", "c");
5856 emitcode ("", "!tlabeldef", (lbl->key + 100));
5858 /* if true label then we jump if condition
5860 tlbl = newiTempLabel (NULL);
5863 emitcode ("jnc", "!tlabel", tlbl->key + 100);
5864 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5868 emitcode ("jc", "!tlabel", tlbl->key + 100);
5869 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5871 emitcode ("", "!tlabeldef", tlbl->key + 100);
5875 tlbl = newiTempLabel (NULL);
5876 gencjneshort (left, right, tlbl);
5879 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5880 emitcode ("", "!tlabeldef", tlbl->key + 100);
5884 symbol *lbl = newiTempLabel (NULL);
5885 emitcode ("sjmp", "!tlabel", lbl->key + 100);
5886 emitcode ("", "!tlabeldef", tlbl->key + 100);
5887 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5888 emitcode ("", "!tlabeldef", lbl->key + 100);
5891 /* mark the icode as generated */
5894 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5895 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5899 /* if they are both bit variables */
5900 if (AOP_TYPE (left) == AOP_CRY &&
5901 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5903 if (AOP_TYPE (right) == AOP_LIT)
5905 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5908 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5909 emitcode ("cpl", "c");
5913 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5917 emitcode ("clr", "c");
5919 /* AOP_TYPE(right) == AOP_CRY */
5923 symbol *lbl = newiTempLabel (NULL);
5924 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5925 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5926 emitcode ("cpl", "c");
5927 emitcode ("", "!tlabeldef", (lbl->key + 100));
5930 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5931 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5933 aopOp (result, ic, TRUE, FALSE);
5936 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5943 genIfxJump (ifx, "c");
5946 /* if the result is used in an arithmetic operation
5947 then put the result in place */
5952 gencjne (left, right, newiTempLabel (NULL));
5954 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5955 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5957 aopOp (result, ic, TRUE, FALSE);
5959 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5961 aopPut (AOP (result), "a", 0);
5966 genIfxJump (ifx, "a");
5969 /* if the result is used in an arithmetic operation
5970 then put the result in place */
5971 if (AOP_TYPE (result) != AOP_CRY)
5973 /* leave the result in acc */
5977 freeAsmop (result, NULL, ic, TRUE);
5980 /*-----------------------------------------------------------------*/
5981 /* ifxForOp - returns the icode containing the ifx for operand */
5982 /*-----------------------------------------------------------------*/
5984 ifxForOp (operand * op, iCode * ic)
5986 /* if true symbol then needs to be assigned */
5987 if (IS_TRUE_SYMOP (op))
5990 /* if this has register type condition and
5991 the next instruction is ifx with the same operand
5992 and live to of the operand is upto the ifx only then */
5994 ic->next->op == IFX &&
5995 IC_COND (ic->next)->key == op->key &&
5996 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6001 /*-----------------------------------------------------------------*/
6002 /* hasInc - operand is incremented before any other use */
6003 /*-----------------------------------------------------------------*/
6005 hasInc (operand *op, iCode *ic, int osize)
6007 sym_link *type = operandType(op);
6008 sym_link *retype = getSpec (type);
6009 iCode *lic = ic->next;
6012 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6013 if (!IS_SYMOP(op)) return NULL;
6015 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6016 if (IS_AGGREGATE(type->next)) return NULL;
6017 if (osize != (isize = getSize(type->next))) return NULL;
6020 /* if operand of the form op = op + <sizeof *op> */
6021 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6022 isOperandEqual(IC_RESULT(lic),op) &&
6023 isOperandLiteral(IC_RIGHT(lic)) &&
6024 operandLitValue(IC_RIGHT(lic)) == isize) {
6027 /* if the operand used or deffed */
6028 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
6031 /* if GOTO or IFX */
6032 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6038 /*-----------------------------------------------------------------*/
6039 /* genAndOp - for && operation */
6040 /*-----------------------------------------------------------------*/
6042 genAndOp (iCode * ic)
6044 operand *left, *right, *result;
6047 D (emitcode (";", "genAndOp "););
6049 /* note here that && operations that are in an
6050 if statement are taken away by backPatchLabels
6051 only those used in arthmetic operations remain */
6053 AOP_SET_LOCALS (ic);
6055 /* if both are bit variables */
6056 if (AOP_TYPE (left) == AOP_CRY &&
6057 AOP_TYPE (right) == AOP_CRY)
6059 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6060 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6061 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6062 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6064 aopOp (result,ic,FALSE, FALSE);
6069 tlbl = newiTempLabel (NULL);
6071 emitcode ("jz", "!tlabel", tlbl->key + 100);
6073 emitcode ("", "!tlabeldef", tlbl->key + 100);
6074 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6075 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6077 aopOp (result,ic,FALSE, FALSE);
6080 freeAsmop (result, NULL, ic, TRUE);
6084 /*-----------------------------------------------------------------*/
6085 /* genOrOp - for || operation */
6086 /*-----------------------------------------------------------------*/
6088 genOrOp (iCode * ic)
6090 operand *left, *right, *result;
6093 D (emitcode (";", "genOrOp "););
6095 /* note here that || operations that are in an
6096 if statement are taken away by backPatchLabels
6097 only those used in arthmetic operations remain */
6099 AOP_SET_LOCALS (ic);
6101 /* if both are bit variables */
6102 if (AOP_TYPE (left) == AOP_CRY &&
6103 AOP_TYPE (right) == AOP_CRY)
6105 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6106 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6107 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6108 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6110 aopOp (result,ic,FALSE, FALSE);
6116 tlbl = newiTempLabel (NULL);
6118 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6120 emitcode ("", "!tlabeldef", tlbl->key + 100);
6121 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6122 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6124 aopOp (result,ic,FALSE, FALSE);
6129 freeAsmop (result, NULL, ic, TRUE);
6132 /*-----------------------------------------------------------------*/
6133 /* isLiteralBit - test if lit == 2^n */
6134 /*-----------------------------------------------------------------*/
6136 isLiteralBit (unsigned long lit)
6138 unsigned long pw[32] =
6139 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6140 0x100L, 0x200L, 0x400L, 0x800L,
6141 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6142 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6143 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6144 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6145 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6148 for (idx = 0; idx < 32; idx++)
6154 /*-----------------------------------------------------------------*/
6155 /* continueIfTrue - */
6156 /*-----------------------------------------------------------------*/
6158 continueIfTrue (iCode * ic)
6161 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6165 /*-----------------------------------------------------------------*/
6167 /*-----------------------------------------------------------------*/
6169 jumpIfTrue (iCode * ic)
6172 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6176 /*-----------------------------------------------------------------*/
6177 /* jmpTrueOrFalse - */
6178 /*-----------------------------------------------------------------*/
6180 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6182 // ugly but optimized by peephole
6185 symbol *nlbl = newiTempLabel (NULL);
6186 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6187 emitcode ("", "!tlabeldef", tlbl->key + 100);
6188 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6189 emitcode ("", "!tlabeldef", nlbl->key + 100);
6193 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6194 emitcode ("", "!tlabeldef", tlbl->key + 100);
6199 // Generate code to perform a bit-wise logic operation
6200 // on two operands in far space (assumed to already have been
6201 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6202 // in far space. This requires pushing the result on the stack
6203 // then popping it into the result.
6205 genFarFarLogicOp(iCode *ic, char *logicOp)
6207 int size, resultSize, compSize;
6211 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6212 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
6213 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6215 _startLazyDPSEvaluation();
6216 for (size = compSize; (size--); offset++)
6218 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6219 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6220 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6222 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6223 emitcode ("push", "acc");
6225 _endLazyDPSEvaluation();
6227 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6228 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6229 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6231 resultSize = AOP_SIZE(IC_RESULT(ic));
6233 ADJUST_PUSHED_RESULT(compSize, resultSize);
6235 _startLazyDPSEvaluation();
6238 emitcode ("pop", "acc");
6239 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6241 _endLazyDPSEvaluation();
6242 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6246 /*-----------------------------------------------------------------*/
6247 /* genAnd - code for and */
6248 /*-----------------------------------------------------------------*/
6250 genAnd (iCode * ic, iCode * ifx)
6252 operand *left, *right, *result;
6253 int size, offset = 0;
6254 unsigned long lit = 0L;
6259 D (emitcode (";", "genAnd "););
6261 AOP_OP_3_NOFATAL (ic, pushResult);
6262 AOP_SET_LOCALS (ic);
6266 genFarFarLogicOp(ic, "anl");
6271 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6273 AOP_TYPE (left), AOP_TYPE (right));
6274 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6276 AOP_SIZE (left), AOP_SIZE (right));
6279 /* if left is a literal & right is not then exchange them */
6280 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6281 #ifdef LOGIC_OPS_BROKEN
6282 || AOP_NEEDSACC (left)
6286 operand *tmp = right;
6291 /* if result = right then exchange them */
6292 if (sameRegs (AOP (result), AOP (right)))
6294 operand *tmp = right;
6299 /* if right is bit then exchange them */
6300 if (AOP_TYPE (right) == AOP_CRY &&
6301 AOP_TYPE (left) != AOP_CRY)
6303 operand *tmp = right;
6307 if (AOP_TYPE (right) == AOP_LIT)
6308 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6310 size = AOP_SIZE (result);
6313 // result = bit & yy;
6314 if (AOP_TYPE (left) == AOP_CRY)
6316 // c = bit & literal;
6317 if (AOP_TYPE (right) == AOP_LIT)
6321 if (size && sameRegs (AOP (result), AOP (left)))
6324 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6329 if (size && (AOP_TYPE (result) == AOP_CRY))
6331 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6334 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6339 emitcode ("clr", "c");
6344 if (AOP_TYPE (right) == AOP_CRY)
6347 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6348 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6353 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6355 emitcode ("rrc", "a");
6356 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6364 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6365 genIfxJump (ifx, "c");
6369 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6370 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6371 if ((AOP_TYPE (right) == AOP_LIT) &&
6372 (AOP_TYPE (result) == AOP_CRY) &&
6373 (AOP_TYPE (left) != AOP_CRY))
6375 int posbit = isLiteralBit (lit);
6380 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6383 emitcode ("mov", "c,acc.%d", posbit & 0x07);
6389 SNPRINTF (buff, sizeof(buff),
6390 "acc.%d", posbit & 0x07);
6391 genIfxJump (ifx, buff);
6395 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6402 symbol *tlbl = newiTempLabel (NULL);
6403 int sizel = AOP_SIZE (left);
6405 emitcode ("setb", "c");
6408 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6410 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6412 if ((posbit = isLiteralBit (bytelit)) != 0)
6413 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6416 if (bytelit != 0x0FFL)
6417 emitcode ("anl", "a,%s",
6418 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6419 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6424 // bit = left & literal
6427 emitcode ("clr", "c");
6428 emitcode ("", "!tlabeldef", tlbl->key + 100);
6430 // if(left & literal)
6434 jmpTrueOrFalse (ifx, tlbl);
6436 emitcode ("", "!tlabeldef", tlbl->key + 100);
6444 /* if left is same as result */
6445 if (sameRegs (AOP (result), AOP (left)))
6447 for (; size--; offset++)
6449 if (AOP_TYPE (right) == AOP_LIT)
6451 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6453 else if (bytelit == 0)
6454 aopPut (AOP (result), zero, offset);
6455 else if (IS_AOP_PREG (result))
6457 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6458 emitcode ("anl", "a,%s",
6459 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6460 aopPut (AOP (result), "a", offset);
6463 emitcode ("anl", "%s,%s",
6464 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6465 aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6469 if (AOP_TYPE (left) == AOP_ACC)
6470 emitcode ("anl", "a,%s",
6471 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6474 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6475 if (IS_AOP_PREG (result))
6477 emitcode ("anl", "a,%s",
6478 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6479 aopPut (AOP (result), "a", offset);
6482 emitcode ("anl", "%s,a",
6483 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6490 // left & result in different registers
6491 if (AOP_TYPE (result) == AOP_CRY)
6494 // if(size), result in bit
6495 // if(!size && ifx), conditional oper: if(left & right)
6496 symbol *tlbl = newiTempLabel (NULL);
6497 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6499 emitcode ("setb", "c");
6502 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6503 emitcode ("anl", "a,%s",
6504 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6506 if (AOP_TYPE(left)==AOP_ACC) {
6507 emitcode("mov", "b,a");
6508 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6509 emitcode("anl", "a,b");
6511 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6512 emitcode ("anl", "a,%s",
6513 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6516 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6522 emitcode ("", "!tlabeldef", tlbl->key + 100);
6526 jmpTrueOrFalse (ifx, tlbl);
6528 emitcode ("", "!tlabeldef", tlbl->key + 100);
6532 for (; (size--); offset++)
6535 // result = left & right
6536 if (AOP_TYPE (right) == AOP_LIT)
6538 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6540 aopPut (AOP (result),
6541 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6545 else if (bytelit == 0)
6547 aopPut (AOP (result), zero, offset);
6550 D (emitcode (";", "better literal AND."););
6551 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6552 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6553 FALSE, FALSE, DP2_RESULT_REG));
6558 // faster than result <- left, anl result,right
6559 // and better if result is SFR
6560 if (AOP_TYPE (left) == AOP_ACC)
6562 emitcode ("anl", "a,%s",
6563 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6567 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6568 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6570 emitcode("mov", "b,a");
6574 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6575 emitcode ("anl", "a,%s", rOp);
6578 aopPut (AOP (result), "a", offset);
6584 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6585 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6586 freeAsmop (result, NULL, ic, TRUE);
6590 /*-----------------------------------------------------------------*/
6591 /* genOr - code for or */
6592 /*-----------------------------------------------------------------*/
6594 genOr (iCode * ic, iCode * ifx)
6596 operand *left, *right, *result;
6597 int size, offset = 0;
6598 unsigned long lit = 0L;
6601 D (emitcode (";", "genOr "););
6603 AOP_OP_3_NOFATAL (ic, pushResult);
6604 AOP_SET_LOCALS (ic);
6608 genFarFarLogicOp(ic, "orl");
6614 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6616 AOP_TYPE (left), AOP_TYPE (right));
6617 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6619 AOP_SIZE (left), AOP_SIZE (right));
6622 /* if left is a literal & right is not then exchange them */
6623 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6624 #ifdef LOGIC_OPS_BROKEN
6625 || AOP_NEEDSACC (left) // I think this is a net loss now.
6629 operand *tmp = right;
6634 /* if result = right then exchange them */
6635 if (sameRegs (AOP (result), AOP (right)))
6637 operand *tmp = right;
6642 /* if right is bit then exchange them */
6643 if (AOP_TYPE (right) == AOP_CRY &&
6644 AOP_TYPE (left) != AOP_CRY)
6646 operand *tmp = right;
6650 if (AOP_TYPE (right) == AOP_LIT)
6651 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6653 size = AOP_SIZE (result);
6657 if (AOP_TYPE (left) == AOP_CRY)
6659 if (AOP_TYPE (right) == AOP_LIT)
6661 // c = bit & literal;
6664 // lit != 0 => result = 1
6665 if (AOP_TYPE (result) == AOP_CRY)
6668 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6670 continueIfTrue (ifx);
6673 emitcode ("setb", "c");
6677 // lit == 0 => result = left
6678 if (size && sameRegs (AOP (result), AOP (left)))
6680 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6685 if (AOP_TYPE (right) == AOP_CRY)
6688 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6689 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6694 symbol *tlbl = newiTempLabel (NULL);
6695 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6696 emitcode ("setb", "c");
6697 emitcode ("jb", "%s,!tlabel",
6698 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6700 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6701 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6703 jmpTrueOrFalse (ifx, tlbl);
6709 emitcode ("", "!tlabeldef", tlbl->key + 100);
6718 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6719 genIfxJump (ifx, "c");
6723 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6724 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6725 if ((AOP_TYPE (right) == AOP_LIT) &&
6726 (AOP_TYPE (result) == AOP_CRY) &&
6727 (AOP_TYPE (left) != AOP_CRY))
6733 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6735 continueIfTrue (ifx);
6740 // lit = 0, result = boolean(left)
6742 emitcode ("setb", "c");
6746 symbol *tlbl = newiTempLabel (NULL);
6747 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6749 emitcode ("", "!tlabeldef", tlbl->key + 100);
6753 genIfxJump (ifx, "a");
6761 /* if left is same as result */
6762 if (sameRegs (AOP (result), AOP (left)))
6764 for (; size--; offset++)
6766 if (AOP_TYPE (right) == AOP_LIT)
6768 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6774 if (IS_AOP_PREG (left))
6776 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6777 emitcode ("orl", "a,%s",
6778 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6779 aopPut (AOP (result), "a", offset);
6783 emitcode ("orl", "%s,%s",
6784 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6785 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6791 if (AOP_TYPE (left) == AOP_ACC)
6793 emitcode ("orl", "a,%s",
6794 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6798 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6799 if (IS_AOP_PREG (left))
6801 emitcode ("orl", "a,%s",
6802 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6803 aopPut (AOP (result), "a", offset);
6807 emitcode ("orl", "%s,a",
6808 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6816 // left & result in different registers
6817 if (AOP_TYPE (result) == AOP_CRY)
6820 // if(size), result in bit
6821 // if(!size && ifx), conditional oper: if(left | right)
6822 symbol *tlbl = newiTempLabel (NULL);
6823 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6825 emitcode ("setb", "c");
6828 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6829 emitcode ("orl", "a,%s",
6830 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6832 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6833 emitcode ("orl", "a,%s",
6834 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6836 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6842 emitcode ("", "!tlabeldef", tlbl->key + 100);
6846 jmpTrueOrFalse (ifx, tlbl);
6848 emitcode ("", "!tlabeldef", tlbl->key + 100);
6852 _startLazyDPSEvaluation();
6853 for (; (size--); offset++)
6856 // result = left & right
6857 if (AOP_TYPE (right) == AOP_LIT)
6859 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6861 aopPut (AOP (result),
6862 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6866 D (emitcode (";", "better literal OR."););
6867 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6868 emitcode ("orl", "a, %s",
6869 aopGet (AOP (right), offset,
6870 FALSE, FALSE, DP2_RESULT_REG));
6875 // faster than result <- left, anl result,right
6876 // and better if result is SFR
6877 if (AOP_TYPE (left) == AOP_ACC)
6879 emitcode ("orl", "a,%s",
6880 aopGet (AOP (right), offset,
6881 FALSE, FALSE, DP2_RESULT_REG));
6885 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6887 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6889 emitcode("mov", "b,a");
6893 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6894 emitcode ("orl", "a,%s", rOp);
6897 aopPut (AOP (result), "a", offset);
6899 _endLazyDPSEvaluation();
6904 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6905 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6906 freeAsmop (result, NULL, ic, TRUE);
6909 /*-----------------------------------------------------------------*/
6910 /* genXor - code for xclusive or */
6911 /*-----------------------------------------------------------------*/
6913 genXor (iCode * ic, iCode * ifx)
6915 operand *left, *right, *result;
6916 int size, offset = 0;
6917 unsigned long lit = 0L;
6920 D (emitcode (";", "genXor "););
6922 AOP_OP_3_NOFATAL (ic, pushResult);
6923 AOP_SET_LOCALS (ic);
6927 genFarFarLogicOp(ic, "xrl");
6932 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6934 AOP_TYPE (left), AOP_TYPE (right));
6935 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6937 AOP_SIZE (left), AOP_SIZE (right));
6940 /* if left is a literal & right is not ||
6941 if left needs acc & right does not */
6942 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6943 #ifdef LOGIC_OPS_BROKEN
6944 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6948 operand *tmp = right;
6953 /* if result = right then exchange them */
6954 if (sameRegs (AOP (result), AOP (right)))
6956 operand *tmp = right;
6961 /* if right is bit then exchange them */
6962 if (AOP_TYPE (right) == AOP_CRY &&
6963 AOP_TYPE (left) != AOP_CRY)
6965 operand *tmp = right;
6969 if (AOP_TYPE (right) == AOP_LIT)
6970 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6972 size = AOP_SIZE (result);
6976 if (AOP_TYPE (left) == AOP_CRY)
6978 if (AOP_TYPE (right) == AOP_LIT)
6980 // c = bit & literal;
6983 // lit>>1 != 0 => result = 1
6984 if (AOP_TYPE (result) == AOP_CRY)
6987 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6989 continueIfTrue (ifx);
6992 emitcode ("setb", "c");
6999 // lit == 0, result = left
7000 if (size && sameRegs (AOP (result), AOP (left)))
7002 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7006 // lit == 1, result = not(left)
7007 if (size && sameRegs (AOP (result), AOP (left)))
7009 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7014 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7015 emitcode ("cpl", "c");
7024 symbol *tlbl = newiTempLabel (NULL);
7025 if (AOP_TYPE (right) == AOP_CRY)
7028 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7032 int sizer = AOP_SIZE (right);
7034 // if val>>1 != 0, result = 1
7035 emitcode ("setb", "c");
7038 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
7040 // test the msb of the lsb
7041 emitcode ("anl", "a,#!constbyte",0xfe);
7042 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7046 emitcode ("rrc", "a");
7048 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7049 emitcode ("cpl", "c");
7050 emitcode ("", "!tlabeldef", (tlbl->key + 100));
7057 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7058 genIfxJump (ifx, "c");
7062 if (sameRegs (AOP (result), AOP (left)))
7064 /* if left is same as result */
7065 for (; size--; offset++)
7067 if (AOP_TYPE (right) == AOP_LIT)
7069 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7071 else if (IS_AOP_PREG (left))
7073 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7074 emitcode ("xrl", "a,%s",
7075 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7076 aopPut (AOP (result), "a", offset);
7079 emitcode ("xrl", "%s,%s",
7080 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7081 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7085 if (AOP_TYPE (left) == AOP_ACC)
7086 emitcode ("xrl", "a,%s",
7087 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7090 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7091 if (IS_AOP_PREG (left))
7093 emitcode ("xrl", "a,%s",
7094 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7095 aopPut (AOP (result), "a", offset);
7098 emitcode ("xrl", "%s,a",
7099 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7106 // left & result in different registers
7107 if (AOP_TYPE (result) == AOP_CRY)
7110 // if(size), result in bit
7111 // if(!size && ifx), conditional oper: if(left ^ right)
7112 symbol *tlbl = newiTempLabel (NULL);
7113 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7116 emitcode ("setb", "c");
7119 if ((AOP_TYPE (right) == AOP_LIT) &&
7120 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7122 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7126 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7127 emitcode ("xrl", "a,%s",
7128 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7130 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7131 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7133 emitcode("mov", "b,a");
7137 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7138 emitcode ("xrl", "a,%s", rOp);
7141 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7147 emitcode ("", "!tlabeldef", tlbl->key + 100);
7151 jmpTrueOrFalse (ifx, tlbl);
7155 for (; (size--); offset++)
7158 // result = left & right
7159 if (AOP_TYPE (right) == AOP_LIT)
7161 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7163 aopPut (AOP (result),
7164 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7168 D (emitcode (";", "better literal XOR."););
7169 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7170 emitcode ("xrl", "a, %s",
7171 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7175 // faster than result <- left, anl result,right
7176 // and better if result is SFR
7177 if (AOP_TYPE (left) == AOP_ACC)
7179 emitcode ("xrl", "a,%s",
7180 aopGet (AOP (right), offset,
7181 FALSE, FALSE, DP2_RESULT_REG));
7185 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7186 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7188 emitcode("mov", "b,a");
7192 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7193 emitcode ("xrl", "a,%s", rOp);
7196 aopPut (AOP (result), "a", offset);
7203 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7204 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7205 freeAsmop (result, NULL, ic, TRUE);
7208 /*-----------------------------------------------------------------*/
7209 /* genInline - write the inline code out */
7210 /*-----------------------------------------------------------------*/
7212 genInline (iCode * ic)
7214 char *buffer, *bp, *bp1;
7216 D (emitcode (";", "genInline "); );
7218 _G.inLine += (!options.asmpeep);
7220 buffer = Safe_strdup(IC_INLINE(ic));
7224 /* emit each line as a code */
7249 /* emitcode("",buffer); */
7250 _G.inLine -= (!options.asmpeep);
7253 /*-----------------------------------------------------------------*/
7254 /* genRRC - rotate right with carry */
7255 /*-----------------------------------------------------------------*/
7259 operand *left, *result;
7262 D (emitcode (";", "genRRC "););
7264 /* rotate right with carry */
7265 left = IC_LEFT (ic);
7266 result = IC_RESULT (ic);
7267 aopOp (left, ic, FALSE, FALSE);
7268 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7270 /* move it to the result */
7271 size = AOP_SIZE (result);
7275 _startLazyDPSEvaluation ();
7278 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7279 emitcode ("rrc", "a");
7280 if (AOP_SIZE (result) > 1)
7281 aopPut (AOP (result), "a", offset--);
7283 _endLazyDPSEvaluation ();
7285 /* now we need to put the carry into the
7286 highest order byte of the result */
7287 if (AOP_SIZE (result) > 1)
7289 MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7291 emitcode ("mov", "acc.7,c");
7292 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7293 freeAsmop (left, NULL, ic, TRUE);
7294 freeAsmop (result, NULL, ic, TRUE);
7297 /*-----------------------------------------------------------------*/
7298 /* genRLC - generate code for rotate left with carry */
7299 /*-----------------------------------------------------------------*/
7303 operand *left, *result;
7307 D (emitcode (";", "genRLC "););
7309 /* rotate right with carry */
7310 left = IC_LEFT (ic);
7311 result = IC_RESULT (ic);
7312 aopOp (left, ic, FALSE, FALSE);
7313 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7315 /* move it to the result */
7316 size = AOP_SIZE (result);
7320 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7322 emitcode ("add", "a,acc");
7323 if (AOP_SIZE (result) > 1)
7325 aopPut (AOP (result), "a", offset++);
7328 _startLazyDPSEvaluation ();
7331 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7333 emitcode ("rlc", "a");
7334 if (AOP_SIZE (result) > 1)
7335 aopPut (AOP (result), "a", offset++);
7337 _endLazyDPSEvaluation ();
7339 /* now we need to put the carry into the
7340 highest order byte of the result */
7341 if (AOP_SIZE (result) > 1)
7343 l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7346 emitcode ("mov", "acc.0,c");
7347 aopPut (AOP (result), "a", 0);
7348 freeAsmop (left, NULL, ic, TRUE);
7349 freeAsmop (result, NULL, ic, TRUE);
7352 /*-----------------------------------------------------------------*/
7353 /* genGetHbit - generates code get highest order bit */
7354 /*-----------------------------------------------------------------*/
7356 genGetHbit (iCode * ic)
7358 operand *left, *result;
7359 left = IC_LEFT (ic);
7360 result = IC_RESULT (ic);
7361 aopOp (left, ic, FALSE, FALSE);
7362 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7364 D (emitcode (";", "genGetHbit "););
7366 /* get the highest order byte into a */
7367 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7368 if (AOP_TYPE (result) == AOP_CRY)
7370 emitcode ("rlc", "a");
7375 emitcode ("rl", "a");
7376 emitcode ("anl", "a,#1");
7381 freeAsmop (left, NULL, ic, TRUE);
7382 freeAsmop (result, NULL, ic, TRUE);
7385 /*-----------------------------------------------------------------*/
7386 /* genSwap - generates code to swap nibbles or bytes */
7387 /*-----------------------------------------------------------------*/
7389 genSwap (iCode * ic)
7391 operand *left, *result;
7393 D(emitcode ("; genSwap",""));
7395 left = IC_LEFT (ic);
7396 result = IC_RESULT (ic);
7397 aopOp (left, ic, FALSE, FALSE);
7398 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7400 _startLazyDPSEvaluation ();
7401 switch (AOP_SIZE (left))
7403 case 1: /* swap nibbles in byte */
7404 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7405 emitcode ("swap", "a");
7406 aopPut (AOP (result), "a", 0);
7408 case 2: /* swap bytes in word */
7409 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7411 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7412 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7413 aopPut (AOP (result), "a", 1);
7415 else if (operandsEqu (left, result))
7418 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7419 if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
7421 emitcode ("mov", "b,a");
7425 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7426 aopPut (AOP (result), reg, 1);
7431 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7432 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE, NULL), 1);
7436 wassertl(FALSE, "unsupported SWAP operand size");
7438 _endLazyDPSEvaluation ();
7440 freeAsmop (left, NULL, ic, TRUE);
7441 freeAsmop (result, NULL, ic, TRUE);
7444 /*-----------------------------------------------------------------*/
7445 /* AccRol - rotate left accumulator by known count */
7446 /*-----------------------------------------------------------------*/
7448 AccRol (int shCount)
7450 shCount &= 0x0007; // shCount : 0..7
7457 emitcode ("rl", "a");
7460 emitcode ("rl", "a");
7461 emitcode ("rl", "a");
7464 emitcode ("swap", "a");
7465 emitcode ("rr", "a");
7468 emitcode ("swap", "a");
7471 emitcode ("swap", "a");
7472 emitcode ("rl", "a");
7475 emitcode ("rr", "a");
7476 emitcode ("rr", "a");
7479 emitcode ("rr", "a");
7484 /*-----------------------------------------------------------------*/
7485 /* AccLsh - left shift accumulator by known count */
7486 /*-----------------------------------------------------------------*/
7488 AccLsh (int shCount)
7493 emitcode ("add", "a,acc");
7494 else if (shCount == 2)
7496 emitcode ("add", "a,acc");
7497 emitcode ("add", "a,acc");
7501 /* rotate left accumulator */
7503 /* and kill the lower order bits */
7504 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7509 /*-----------------------------------------------------------------*/
7510 /* AccRsh - right shift accumulator by known count */
7511 /*-----------------------------------------------------------------*/
7513 AccRsh (int shCount)
7520 emitcode ("rrc", "a");
7524 /* rotate right accumulator */
7525 AccRol (8 - shCount);
7526 /* and kill the higher order bits */
7527 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7532 #ifdef BETTER_LITERAL_SHIFT
7533 /*-----------------------------------------------------------------*/
7534 /* AccSRsh - signed right shift accumulator by known count */
7535 /*-----------------------------------------------------------------*/
7537 AccSRsh (int shCount)
7544 emitcode ("mov", "c,acc.7");
7545 emitcode ("rrc", "a");
7547 else if (shCount == 2)
7549 emitcode ("mov", "c,acc.7");
7550 emitcode ("rrc", "a");
7551 emitcode ("mov", "c,acc.7");
7552 emitcode ("rrc", "a");
7556 tlbl = newiTempLabel (NULL);
7557 /* rotate right accumulator */
7558 AccRol (8 - shCount);
7559 /* and kill the higher order bits */
7560 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7561 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7562 emitcode ("orl", "a,#!constbyte",
7563 (unsigned char) ~SRMask[shCount]);
7564 emitcode ("", "!tlabeldef", tlbl->key + 100);
7570 #ifdef BETTER_LITERAL_SHIFT
7571 /*-----------------------------------------------------------------*/
7572 /* shiftR1Left2Result - shift right one byte from left to result */
7573 /*-----------------------------------------------------------------*/
7575 shiftR1Left2Result (operand * left, int offl,
7576 operand * result, int offr,
7577 int shCount, int sign)
7579 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7580 /* shift right accumulator */
7585 aopPut (AOP (result), "a", offr);
7589 #ifdef BETTER_LITERAL_SHIFT
7590 /*-----------------------------------------------------------------*/
7591 /* shiftL1Left2Result - shift left one byte from left to result */
7592 /*-----------------------------------------------------------------*/
7594 shiftL1Left2Result (operand * left, int offl,
7595 operand * result, int offr, int shCount)
7597 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7598 /* shift left accumulator */
7600 aopPut (AOP (result), "a", offr);
7604 #ifdef BETTER_LITERAL_SHIFT
7605 /*-----------------------------------------------------------------*/
7606 /* movLeft2Result - move byte from left to result */
7607 /*-----------------------------------------------------------------*/
7609 movLeft2Result (operand * left, int offl,
7610 operand * result, int offr, int sign)
7613 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7615 l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7617 if (*l == '@' && (IS_AOP_PREG (result)))
7619 emitcode ("mov", "a,%s", l);
7620 aopPut (AOP (result), "a", offr);
7626 aopPut (AOP (result), l, offr);
7630 /* MSB sign in acc.7 ! */
7631 if (getDataSize (left) == offl + 1)
7633 emitcode ("mov", "a,%s", l);
7634 aopPut (AOP (result), "a", offr);
7642 #ifdef BETTER_LITERAL_SHIFT
7643 /*-----------------------------------------------------------------*/
7644 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7645 /*-----------------------------------------------------------------*/
7649 emitcode ("rrc", "a");
7650 emitcode ("xch", "a,%s", x);
7651 emitcode ("rrc", "a");
7652 emitcode ("xch", "a,%s", x);
7656 #ifdef BETTER_LITERAL_SHIFT
7658 /*-----------------------------------------------------------------*/
7659 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7660 /*-----------------------------------------------------------------*/
7664 emitcode ("xch", "a,%s", x);
7665 emitcode ("rlc", "a");
7666 emitcode ("xch", "a,%s", x);
7667 emitcode ("rlc", "a");
7671 #ifdef BETTER_LITERAL_SHIFT
7672 /*-----------------------------------------------------------------*/
7673 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7674 /*-----------------------------------------------------------------*/
7678 emitcode ("xch", "a,%s", x);
7679 emitcode ("add", "a,acc");
7680 emitcode ("xch", "a,%s", x);
7681 emitcode ("rlc", "a");
7685 #ifdef BETTER_LITERAL_SHIFT
7686 /*-----------------------------------------------------------------*/
7687 /* AccAXLsh - left shift a:x by known count (0..7) */
7688 /*-----------------------------------------------------------------*/
7690 AccAXLsh (char *x, int shCount)
7705 case 5: // AAAAABBB:CCCCCDDD
7707 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7709 emitcode ("anl", "a,#!constbyte",
7710 SLMask[shCount]); // BBB00000:CCCCCDDD
7712 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7714 AccRol (shCount); // DDDCCCCC:BBB00000
7716 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7718 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7720 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7722 emitcode ("anl", "a,#!constbyte",
7723 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7725 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7727 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7730 case 6: // AAAAAABB:CCCCCCDD
7731 emitcode ("anl", "a,#!constbyte",
7732 SRMask[shCount]); // 000000BB:CCCCCCDD
7733 emitcode ("mov", "c,acc.0"); // c = B
7734 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7736 AccAXRrl1 (x); // BCCCCCCD:D000000B
7737 AccAXRrl1 (x); // BBCCCCCC:DD000000
7739 emitcode("rrc","a");
7740 emitcode("xch","a,%s", x);
7741 emitcode("rrc","a");
7742 emitcode("mov","c,acc.0"); //<< get correct bit
7743 emitcode("xch","a,%s", x);
7745 emitcode("rrc","a");
7746 emitcode("xch","a,%s", x);
7747 emitcode("rrc","a");
7748 emitcode("xch","a,%s", x);
7751 case 7: // a:x <<= 7
7753 emitcode ("anl", "a,#!constbyte",
7754 SRMask[shCount]); // 0000000B:CCCCCCCD
7756 emitcode ("mov", "c,acc.0"); // c = B
7758 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7760 AccAXRrl1 (x); // BCCCCCCC:D0000000
7769 #ifdef BETTER_LITERAL_SHIFT
7771 /*-----------------------------------------------------------------*/
7772 /* AccAXRsh - right shift a:x known count (0..7) */
7773 /*-----------------------------------------------------------------*/
7775 AccAXRsh (char *x, int shCount)
7783 AccAXRrl1 (x); // 0->a:x
7788 AccAXRrl1 (x); // 0->a:x
7791 AccAXRrl1 (x); // 0->a:x
7796 case 5: // AAAAABBB:CCCCCDDD = a:x
7798 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7800 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7802 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7804 emitcode ("anl", "a,#!constbyte",
7805 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7807 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7809 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7811 emitcode ("anl", "a,#!constbyte",
7812 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7814 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7816 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7818 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7821 case 6: // AABBBBBB:CCDDDDDD
7823 emitcode ("mov", "c,acc.7");
7824 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7826 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7828 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7830 emitcode ("anl", "a,#!constbyte",
7831 SRMask[shCount]); // 000000AA:BBBBBBCC
7834 case 7: // ABBBBBBB:CDDDDDDD
7836 emitcode ("mov", "c,acc.7"); // c = A
7838 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7840 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7842 emitcode ("anl", "a,#!constbyte",
7843 SRMask[shCount]); // 0000000A:BBBBBBBC
7852 #ifdef BETTER_LITERAL_SHIFT
7853 /*-----------------------------------------------------------------*/
7854 /* AccAXRshS - right shift signed a:x known count (0..7) */
7855 /*-----------------------------------------------------------------*/
7857 AccAXRshS (char *x, int shCount)
7865 emitcode ("mov", "c,acc.7");
7866 AccAXRrl1 (x); // s->a:x
7870 emitcode ("mov", "c,acc.7");
7871 AccAXRrl1 (x); // s->a:x
7873 emitcode ("mov", "c,acc.7");
7874 AccAXRrl1 (x); // s->a:x
7879 case 5: // AAAAABBB:CCCCCDDD = a:x
7881 tlbl = newiTempLabel (NULL);
7882 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7884 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7886 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7888 emitcode ("anl", "a,#!constbyte",
7889 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7891 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7893 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7895 emitcode ("anl", "a,#!constbyte",
7896 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7898 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7900 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7902 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7904 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7905 emitcode ("orl", "a,#!constbyte",
7906 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7908 emitcode ("", "!tlabeldef", tlbl->key + 100);
7909 break; // SSSSAAAA:BBBCCCCC
7911 case 6: // AABBBBBB:CCDDDDDD
7913 tlbl = newiTempLabel (NULL);
7914 emitcode ("mov", "c,acc.7");
7915 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7917 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7919 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7921 emitcode ("anl", "a,#!constbyte",
7922 SRMask[shCount]); // 000000AA:BBBBBBCC
7924 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7925 emitcode ("orl", "a,#!constbyte",
7926 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7928 emitcode ("", "!tlabeldef", tlbl->key + 100);
7930 case 7: // ABBBBBBB:CDDDDDDD
7932 tlbl = newiTempLabel (NULL);
7933 emitcode ("mov", "c,acc.7"); // c = A
7935 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7937 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7939 emitcode ("anl", "a,#!constbyte",
7940 SRMask[shCount]); // 0000000A:BBBBBBBC
7942 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7943 emitcode ("orl", "a,#!constbyte",
7944 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7946 emitcode ("", "!tlabeldef", tlbl->key + 100);
7954 #ifdef BETTER_LITERAL_SHIFT
7956 _loadLeftIntoAx(char **lsb,
7962 // Get the initial value from left into a pair of registers.
7963 // MSB must be in A, LSB can be any register.
7965 // If the result is held in registers, it is an optimization
7966 // if the LSB can be held in the register which will hold the,
7967 // result LSB since this saves us from having to copy it into
7968 // the result following AccAXLsh.
7970 // If the result is addressed indirectly, this is not a gain.
7971 if (AOP_NEEDSACC(result))
7975 _startLazyDPSEvaluation();
7976 if (AOP_TYPE(left) == AOP_DPTR2)
7979 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7980 // get LSB in DP2_RESULT_REG.
7981 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7982 assert(!strcmp(leftByte, DP2_RESULT_REG));
7986 // get LSB into DP2_RESULT_REG
7987 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7988 if (strcmp(leftByte, DP2_RESULT_REG))
7991 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7994 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7995 assert(strcmp(leftByte, DP2_RESULT_REG));
7998 _endLazyDPSEvaluation();
7999 *lsb = DP2_RESULT_REG;
8003 if (sameRegs (AOP (result), AOP (left)) &&
8004 ((offl + MSB16) == offr))
8006 /* don't crash result[offr] */
8007 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
8008 emitcode ("xch", "a,%s",
8009 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
8013 movLeft2Result (left, offl, result, offr, 0);
8014 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
8016 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
8017 assert(strcmp(*lsb,"a"));
8022 _storeAxResults(char *lsb,
8026 _startLazyDPSEvaluation();
8027 if (AOP_NEEDSACC(result))
8029 /* We have to explicitly update the result LSB.
8031 emitcode("xch","a,%s", lsb);
8032 aopPut(AOP(result), "a", offr);
8033 emitcode("mov","a,%s", lsb);
8035 if (getDataSize (result) > 1)
8037 aopPut (AOP (result), "a", offr + MSB16);
8039 _endLazyDPSEvaluation();
8042 /*-----------------------------------------------------------------*/
8043 /* shiftL2Left2Result - shift left two bytes from left to result */
8044 /*-----------------------------------------------------------------*/
8046 shiftL2Left2Result (operand * left, int offl,
8047 operand * result, int offr, int shCount)
8051 _loadLeftIntoAx(&lsb, left, result, offl, offr);
8053 AccAXLsh (lsb, shCount);
8055 _storeAxResults(lsb, result, offr);
8059 #ifdef BETTER_LITERAL_SHIFT
8060 /*-----------------------------------------------------------------*/
8061 /* shiftR2Left2Result - shift right two bytes from left to result */
8062 /*-----------------------------------------------------------------*/
8064 shiftR2Left2Result (operand * left, int offl,
8065 operand * result, int offr,
8066 int shCount, int sign)
8070 _loadLeftIntoAx(&lsb, left, result, offl, offr);
8072 /* a:x >> shCount (x = lsb(result)) */
8075 AccAXRshS(lsb, shCount);
8079 AccAXRsh(lsb, shCount);
8082 _storeAxResults(lsb, result, offr);
8086 /*-----------------------------------------------------------------*/
8087 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8088 /*-----------------------------------------------------------------*/
8090 shiftLLeftOrResult (operand * left, int offl,
8091 operand * result, int offr, int shCount)
8093 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8094 /* shift left accumulator */
8096 /* or with result */
8097 emitcode ("orl", "a,%s",
8098 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8099 /* back to result */
8100 aopPut (AOP (result), "a", offr);
8105 /*-----------------------------------------------------------------*/
8106 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8107 /*-----------------------------------------------------------------*/
8109 shiftRLeftOrResult (operand * left, int offl,
8110 operand * result, int offr, int shCount)
8112 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8113 /* shift right accumulator */
8115 /* or with result */
8116 emitcode ("orl", "a,%s",
8117 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8118 /* back to result */
8119 aopPut (AOP (result), "a", offr);
8123 #ifdef BETTER_LITERAL_SHIFT
8124 /*-----------------------------------------------------------------*/
8125 /* genlshOne - left shift a one byte quantity by known count */
8126 /*-----------------------------------------------------------------*/
8128 genlshOne (operand * result, operand * left, int shCount)
8130 D (emitcode (";", "genlshOne "););
8131 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8135 #ifdef BETTER_LITERAL_SHIFT
8136 /*-----------------------------------------------------------------*/
8137 /* genlshTwo - left shift two bytes by known amount != 0 */
8138 /*-----------------------------------------------------------------*/
8140 genlshTwo (operand * result, operand * left, int shCount)
8144 D (emitcode (";", "genlshTwo "););
8146 size = getDataSize (result);
8148 /* if shCount >= 8 */
8153 _startLazyDPSEvaluation();
8159 _endLazyDPSEvaluation();
8160 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8161 aopPut (AOP (result), zero, LSB);
8165 movLeft2Result (left, LSB, result, MSB16, 0);
8166 aopPut (AOP (result), zero, LSB);
8167 _endLazyDPSEvaluation();
8172 aopPut (AOP (result), zero, LSB);
8173 _endLazyDPSEvaluation();
8177 /* 1 <= shCount <= 7 */
8182 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8186 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8194 /*-----------------------------------------------------------------*/
8195 /* shiftLLong - shift left one long from left to result */
8196 /* offl = LSB or MSB16 */
8197 /*-----------------------------------------------------------------*/
8199 shiftLLong (operand * left, operand * result, int offr)
8202 int size = AOP_SIZE (result);
8204 if (size >= LSB + offr)
8206 l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8208 emitcode ("add", "a,acc");
8209 if (sameRegs (AOP (left), AOP (result)) &&
8210 size >= MSB16 + offr && offr != LSB)
8211 emitcode ("xch", "a,%s",
8212 aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8214 aopPut (AOP (result), "a", LSB + offr);
8217 if (size >= MSB16 + offr)
8219 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8221 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8223 emitcode ("rlc", "a");
8224 if (sameRegs (AOP (left), AOP (result)) &&
8225 size >= MSB24 + offr && offr != LSB)
8226 emitcode ("xch", "a,%s",
8227 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8229 aopPut (AOP (result), "a", MSB16 + offr);
8232 if (size >= MSB24 + offr)
8234 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8236 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8238 emitcode ("rlc", "a");
8239 if (sameRegs (AOP (left), AOP (result)) &&
8240 size >= MSB32 + offr && offr != LSB)
8241 emitcode ("xch", "a,%s",
8242 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8244 aopPut (AOP (result), "a", MSB24 + offr);
8247 if (size > MSB32 + offr)
8249 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8251 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8253 emitcode ("rlc", "a");
8254 aopPut (AOP (result), "a", MSB32 + offr);
8257 aopPut (AOP (result), zero, LSB);
8263 /*-----------------------------------------------------------------*/
8264 /* genlshFour - shift four byte by a known amount != 0 */
8265 /*-----------------------------------------------------------------*/
8267 genlshFour (operand * result, operand * left, int shCount)
8271 D (emitcode (";", "genlshFour ");
8274 size = AOP_SIZE (result);
8276 /* if shifting more that 3 bytes */
8281 /* lowest order of left goes to the highest
8282 order of the destination */
8283 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8285 movLeft2Result (left, LSB, result, MSB32, 0);
8286 aopPut (AOP (result), zero, LSB);
8287 aopPut (AOP (result), zero, MSB16);
8288 aopPut (AOP (result), zero, MSB24);
8292 /* more than two bytes */
8293 else if (shCount >= 16)
8295 /* lower order two bytes goes to higher order two bytes */
8297 /* if some more remaining */
8299 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8302 movLeft2Result (left, MSB16, result, MSB32, 0);
8303 movLeft2Result (left, LSB, result, MSB24, 0);
8305 aopPut (AOP (result), zero, MSB16);
8306 aopPut (AOP (result), zero, LSB);
8310 /* if more than 1 byte */
8311 else if (shCount >= 8)
8313 /* lower order three bytes goes to higher order three bytes */
8318 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8320 movLeft2Result (left, LSB, result, MSB16, 0);
8326 movLeft2Result (left, MSB24, result, MSB32, 0);
8327 movLeft2Result (left, MSB16, result, MSB24, 0);
8328 movLeft2Result (left, LSB, result, MSB16, 0);
8329 aopPut (AOP (result), zero, LSB);
8331 else if (shCount == 1)
8332 shiftLLong (left, result, MSB16);
8335 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8336 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8337 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8338 aopPut (AOP (result), zero, LSB);
8343 /* 1 <= shCount <= 7 */
8344 else if (shCount <= 2)
8346 shiftLLong (left, result, LSB);
8348 shiftLLong (result, result, LSB);
8350 /* 3 <= shCount <= 7, optimize */
8353 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8354 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8355 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8360 #ifdef BETTER_LITERAL_SHIFT
8361 /*-----------------------------------------------------------------*/
8362 /* genLeftShiftLiteral - left shifting by known count */
8363 /*-----------------------------------------------------------------*/
8365 genLeftShiftLiteral (operand * left,
8370 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8373 size = getSize (operandType (result));
8375 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8377 /* We only handle certain easy cases so far. */
8379 && (shCount < (size * 8))
8383 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8387 freeAsmop (right, NULL, ic, TRUE);
8389 aopOp(left, ic, FALSE, FALSE);
8390 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8393 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8395 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8396 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8398 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8401 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8403 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8404 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8406 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8412 emitcode ("; shift left ", "result %d, left %d", size,
8416 /* I suppose that the left size >= result size */
8419 _startLazyDPSEvaluation();
8422 movLeft2Result (left, size, result, size, 0);
8424 _endLazyDPSEvaluation();
8426 else if (shCount >= (size * 8))
8428 _startLazyDPSEvaluation();
8431 aopPut (AOP (result), zero, size);
8433 _endLazyDPSEvaluation();
8440 genlshOne (result, left, shCount);
8444 genlshTwo (result, left, shCount);
8448 genlshFour (result, left, shCount);
8452 fprintf(stderr, "*** ack! mystery literal shift!\n");
8456 freeAsmop (left, NULL, ic, TRUE);
8457 freeAsmop (result, NULL, ic, TRUE);
8462 /*-----------------------------------------------------------------*/
8463 /* genLeftShift - generates code for left shifting */
8464 /*-----------------------------------------------------------------*/
8466 genLeftShift (iCode * ic)
8468 operand *left, *right, *result;
8471 symbol *tlbl, *tlbl1;
8473 D (emitcode (";", "genLeftShift "););
8475 right = IC_RIGHT (ic);
8476 left = IC_LEFT (ic);
8477 result = IC_RESULT (ic);
8479 aopOp (right, ic, FALSE, FALSE);
8482 #ifdef BETTER_LITERAL_SHIFT
8483 /* if the shift count is known then do it
8484 as efficiently as possible */
8485 if (AOP_TYPE (right) == AOP_LIT)
8487 if (genLeftShiftLiteral (left, right, result, ic))
8494 /* shift count is unknown then we have to form
8495 a loop get the loop count in B : Note: we take
8496 only the lower order byte since shifting
8497 more that 32 bits make no sense anyway, ( the
8498 largest size of an object can be only 32 bits ) */
8500 if (AOP_TYPE (right) == AOP_LIT)
8502 /* Really should be handled by genLeftShiftLiteral,
8503 * but since I'm too lazy to fix that today, at least we can make
8504 * some small improvement.
8506 emitcode("mov", "b,#!constbyte",
8507 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8511 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8512 emitcode ("inc", "b");
8514 freeAsmop (right, NULL, ic, TRUE);
8515 aopOp (left, ic, FALSE, FALSE);
8516 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8518 /* now move the left to the result if they are not the
8520 if (!sameRegs (AOP (left), AOP (result)) &&
8521 AOP_SIZE (result) > 1)
8524 size = AOP_SIZE (result);
8526 _startLazyDPSEvaluation ();
8529 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8530 if (*l == '@' && (IS_AOP_PREG (result)))
8533 emitcode ("mov", "a,%s", l);
8534 aopPut (AOP (result), "a", offset);
8537 aopPut (AOP (result), l, offset);
8540 _endLazyDPSEvaluation ();
8543 tlbl = newiTempLabel (NULL);
8544 size = AOP_SIZE (result);
8546 tlbl1 = newiTempLabel (NULL);
8548 /* if it is only one byte then */
8551 symbol *tlbl1 = newiTempLabel (NULL);
8553 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8554 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8555 emitcode ("", "!tlabeldef", tlbl->key + 100);
8556 emitcode ("add", "a,acc");
8557 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8558 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8559 aopPut (AOP (result), "a", 0);
8563 reAdjustPreg (AOP (result));
8565 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8566 emitcode ("", "!tlabeldef", tlbl->key + 100);
8567 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8568 emitcode ("add", "a,acc");
8569 aopPut (AOP (result), "a", offset++);
8570 _startLazyDPSEvaluation ();
8573 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8574 emitcode ("rlc", "a");
8575 aopPut (AOP (result), "a", offset++);
8577 _endLazyDPSEvaluation ();
8578 reAdjustPreg (AOP (result));
8580 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8581 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8583 freeAsmop (left, NULL, ic, TRUE);
8584 freeAsmop (result, NULL, ic, TRUE);
8587 #ifdef BETTER_LITERAL_SHIFT
8588 /*-----------------------------------------------------------------*/
8589 /* genrshOne - right shift a one byte quantity by known count */
8590 /*-----------------------------------------------------------------*/
8592 genrshOne (operand * result, operand * left,
8593 int shCount, int sign)
8595 D (emitcode (";", "genrshOne"););
8596 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8600 #ifdef BETTER_LITERAL_SHIFT
8601 /*-----------------------------------------------------------------*/
8602 /* genrshTwo - right shift two bytes by known amount != 0 */
8603 /*-----------------------------------------------------------------*/
8605 genrshTwo (operand * result, operand * left,
8606 int shCount, int sign)
8608 D (emitcode (";", "genrshTwo"););
8610 /* if shCount >= 8 */
8614 _startLazyDPSEvaluation();
8617 shiftR1Left2Result (left, MSB16, result, LSB,
8622 movLeft2Result (left, MSB16, result, LSB, sign);
8624 addSign (result, MSB16, sign);
8625 _endLazyDPSEvaluation();
8628 /* 1 <= shCount <= 7 */
8631 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8636 /*-----------------------------------------------------------------*/
8637 /* shiftRLong - shift right one long from left to result */
8638 /* offl = LSB or MSB16 */
8639 /*-----------------------------------------------------------------*/
8641 shiftRLong (operand * left, int offl,
8642 operand * result, int sign)
8644 int isSameRegs=sameRegs(AOP(left),AOP(result));
8646 if (isSameRegs && offl>1) {
8647 // we are in big trouble, but this shouldn't happen
8648 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8651 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8656 emitcode ("rlc", "a");
8657 emitcode ("subb", "a,acc");
8658 emitcode ("xch", "a,%s",
8659 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
8661 aopPut (AOP(result), zero, MSB32);
8666 emitcode ("clr", "c");
8668 emitcode ("mov", "c,acc.7");
8671 emitcode ("rrc", "a");
8673 if (isSameRegs && offl==MSB16) {
8675 "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
8677 aopPut (AOP (result), "a", MSB32);
8678 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8681 emitcode ("rrc", "a");
8682 if (isSameRegs && offl==1) {
8683 emitcode ("xch", "a,%s",
8684 aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
8686 aopPut (AOP (result), "a", MSB24);
8687 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
8689 emitcode ("rrc", "a");
8690 aopPut (AOP (result), "a", MSB16 - offl);
8694 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
8695 emitcode ("rrc", "a");
8696 aopPut (AOP (result), "a", LSB);
8700 /*-----------------------------------------------------------------*/
8701 /* genrshFour - shift four byte by a known amount != 0 */
8702 /*-----------------------------------------------------------------*/
8704 genrshFour (operand * result, operand * left,
8705 int shCount, int sign)
8707 D (emitcode (";", "genrshFour"););
8709 /* if shifting more that 3 bytes */
8713 _startLazyDPSEvaluation();
8715 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8717 movLeft2Result (left, MSB32, result, LSB, sign);
8718 addSign (result, MSB16, sign);
8719 _endLazyDPSEvaluation();
8721 else if (shCount >= 16)
8724 _startLazyDPSEvaluation();
8726 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8729 movLeft2Result (left, MSB24, result, LSB, 0);
8730 movLeft2Result (left, MSB32, result, MSB16, sign);
8732 addSign (result, MSB24, sign);
8733 _endLazyDPSEvaluation();
8735 else if (shCount >= 8)
8738 _startLazyDPSEvaluation();
8741 shiftRLong (left, MSB16, result, sign);
8743 else if (shCount == 0)
8745 movLeft2Result (left, MSB16, result, LSB, 0);
8746 movLeft2Result (left, MSB24, result, MSB16, 0);
8747 movLeft2Result (left, MSB32, result, MSB24, sign);
8748 addSign (result, MSB32, sign);
8752 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8753 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8754 /* the last shift is signed */
8755 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8756 addSign (result, MSB32, sign);
8758 _endLazyDPSEvaluation();
8762 /* 1 <= shCount <= 7 */
8765 shiftRLong (left, LSB, result, sign);
8767 shiftRLong (result, LSB, result, sign);
8771 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8772 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8773 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8778 #ifdef BETTER_LITERAL_SHIFT
8779 /*-----------------------------------------------------------------*/
8780 /* genRightShiftLiteral - right shifting by known count */
8781 /*-----------------------------------------------------------------*/
8783 genRightShiftLiteral (operand * left,
8789 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8792 size = getSize (operandType (result));
8794 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8796 /* We only handle certain easy cases so far. */
8798 && (shCount < (size * 8))
8803 D(emitcode (";", "genRightShiftLiteral wimping out"););
8807 freeAsmop (right, NULL, ic, TRUE);
8809 aopOp (left, ic, FALSE, FALSE);
8810 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8813 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8817 /* test the LEFT size !!! */
8819 /* I suppose that the left size >= result size */
8822 size = getDataSize (result);
8823 _startLazyDPSEvaluation();
8826 movLeft2Result (left, size, result, size, 0);
8828 _endLazyDPSEvaluation();
8830 else if (shCount >= (size * 8))
8834 /* get sign in acc.7 */
8835 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8837 addSign (result, LSB, sign);
8844 genrshOne (result, left, shCount, sign);
8848 genrshTwo (result, left, shCount, sign);
8852 genrshFour (result, left, shCount, sign);
8859 freeAsmop (left, NULL, ic, TRUE);
8860 freeAsmop (result, NULL, ic, TRUE);
8866 /*-----------------------------------------------------------------*/
8867 /* genSignedRightShift - right shift of signed number */
8868 /*-----------------------------------------------------------------*/
8870 genSignedRightShift (iCode * ic)
8872 operand *right, *left, *result;
8875 symbol *tlbl, *tlbl1;
8877 D (emitcode (";", "genSignedRightShift "););
8879 /* we do it the hard way put the shift count in b
8880 and loop thru preserving the sign */
8882 right = IC_RIGHT (ic);
8883 left = IC_LEFT (ic);
8884 result = IC_RESULT (ic);
8886 aopOp (right, ic, FALSE, FALSE);
8888 #ifdef BETTER_LITERAL_SHIFT
8889 if (AOP_TYPE (right) == AOP_LIT)
8891 if (genRightShiftLiteral (left, right, result, ic, 1))
8897 /* shift count is unknown then we have to form
8898 a loop get the loop count in B : Note: we take
8899 only the lower order byte since shifting
8900 more that 32 bits make no sense anyway, ( the
8901 largest size of an object can be only 32 bits ) */
8903 if (AOP_TYPE (right) == AOP_LIT)
8905 /* Really should be handled by genRightShiftLiteral,
8906 * but since I'm too lazy to fix that today, at least we can make
8907 * some small improvement.
8909 emitcode("mov", "b,#!constbyte",
8910 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8914 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8915 emitcode ("inc", "b");
8917 freeAsmop (right, NULL, ic, TRUE);
8918 aopOp (left, ic, FALSE, FALSE);
8919 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8921 /* now move the left to the result if they are not the
8923 if (!sameRegs (AOP (left), AOP (result)) &&
8924 AOP_SIZE (result) > 1)
8927 size = AOP_SIZE (result);
8929 _startLazyDPSEvaluation ();
8932 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8933 if (*l == '@' && IS_AOP_PREG (result))
8936 emitcode ("mov", "a,%s", l);
8937 aopPut (AOP (result), "a", offset);
8940 aopPut (AOP (result), l, offset);
8943 _endLazyDPSEvaluation ();
8946 /* mov the highest order bit to OVR */
8947 tlbl = newiTempLabel (NULL);
8948 tlbl1 = newiTempLabel (NULL);
8950 size = AOP_SIZE (result);
8952 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8953 emitcode ("rlc", "a");
8954 emitcode ("mov", "ov,c");
8955 /* if it is only one byte then */
8958 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8959 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8960 emitcode ("", "!tlabeldef", tlbl->key + 100);
8961 emitcode ("mov", "c,ov");
8962 emitcode ("rrc", "a");
8963 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8964 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8965 aopPut (AOP (result), "a", 0);
8969 reAdjustPreg (AOP (result));
8970 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8971 emitcode ("", "!tlabeldef", tlbl->key + 100);
8972 emitcode ("mov", "c,ov");
8973 _startLazyDPSEvaluation ();
8976 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8977 emitcode ("rrc", "a");
8978 aopPut (AOP (result), "a", offset--);
8980 _endLazyDPSEvaluation ();
8981 reAdjustPreg (AOP (result));
8982 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8983 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8986 freeAsmop (left, NULL, ic, TRUE);
8987 freeAsmop (result, NULL, ic, TRUE);
8990 /*-----------------------------------------------------------------*/
8991 /* genRightShift - generate code for right shifting */
8992 /*-----------------------------------------------------------------*/
8994 genRightShift (iCode * ic)
8996 operand *right, *left, *result;
9000 symbol *tlbl, *tlbl1;
9002 D (emitcode (";", "genRightShift "););
9004 /* if signed then we do it the hard way preserve the
9005 sign bit moving it inwards */
9006 letype = getSpec (operandType (IC_LEFT (ic)));
9008 if (!SPEC_USIGN (letype))
9010 genSignedRightShift (ic);
9014 /* signed & unsigned types are treated the same : i.e. the
9015 signed is NOT propagated inwards : quoting from the
9016 ANSI - standard : "for E1 >> E2, is equivalent to division
9017 by 2**E2 if unsigned or if it has a non-negative value,
9018 otherwise the result is implementation defined ", MY definition
9019 is that the sign does not get propagated */
9021 right = IC_RIGHT (ic);
9022 left = IC_LEFT (ic);
9023 result = IC_RESULT (ic);
9025 aopOp (right, ic, FALSE, FALSE);
9027 #ifdef BETTER_LITERAL_SHIFT
9028 /* if the shift count is known then do it
9029 as efficiently as possible */
9030 if (AOP_TYPE (right) == AOP_LIT)
9032 if (genRightShiftLiteral (left, right, result, ic, 0))
9039 /* shift count is unknown then we have to form
9040 a loop get the loop count in B : Note: we take
9041 only the lower order byte since shifting
9042 more that 32 bits make no sense anyway, ( the
9043 largest size of an object can be only 32 bits ) */
9045 if (AOP_TYPE (right) == AOP_LIT)
9047 /* Really should be handled by genRightShiftLiteral,
9048 * but since I'm too lazy to fix that today, at least we can make
9049 * some small improvement.
9051 emitcode("mov", "b,#!constbyte",
9052 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9056 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9057 emitcode ("inc", "b");
9059 freeAsmop (right, NULL, ic, TRUE);
9060 aopOp (left, ic, FALSE, FALSE);
9061 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9063 /* now move the left to the result if they are not the
9065 if (!sameRegs (AOP (left), AOP (result)) &&
9066 AOP_SIZE (result) > 1)
9069 size = AOP_SIZE (result);
9071 _startLazyDPSEvaluation ();
9074 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9075 if (*l == '@' && IS_AOP_PREG (result))
9078 emitcode ("mov", "a,%s", l);
9079 aopPut (AOP (result), "a", offset);
9082 aopPut (AOP (result), l, offset);
9085 _endLazyDPSEvaluation ();
9088 tlbl = newiTempLabel (NULL);
9089 tlbl1 = newiTempLabel (NULL);
9090 size = AOP_SIZE (result);
9093 /* if it is only one byte then */
9096 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9097 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9098 emitcode ("", "!tlabeldef", tlbl->key + 100);
9100 emitcode ("rrc", "a");
9101 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9102 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9103 aopPut (AOP (result), "a", 0);
9107 reAdjustPreg (AOP (result));
9108 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9109 emitcode ("", "!tlabeldef", tlbl->key + 100);
9111 _startLazyDPSEvaluation ();
9114 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9115 emitcode ("rrc", "a");
9116 aopPut (AOP (result), "a", offset--);
9118 _endLazyDPSEvaluation ();
9119 reAdjustPreg (AOP (result));
9121 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9122 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9125 freeAsmop (left, NULL, ic, TRUE);
9126 freeAsmop (result, NULL, ic, TRUE);
9130 /*-----------------------------------------------------------------*/
9131 /* emitPtrByteGet - emits code to get a byte into A through a */
9132 /* pointer register (R0, R1, or DPTR). The */
9133 /* original value of A can be preserved in B. */
9134 /*-----------------------------------------------------------------*/
9136 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9143 emitcode ("mov", "b,a");
9144 emitcode ("mov", "a,@%s", rname);
9149 emitcode ("mov", "b,a");
9150 emitcode ("movx", "a,@%s", rname);
9155 emitcode ("mov", "b,a");
9156 emitcode ("movx", "a,@dptr");
9161 emitcode ("mov", "b,a");
9162 emitcode ("clr", "a");
9163 emitcode ("movc", "a,@a+dptr");
9169 emitcode ("push", "b");
9170 emitcode ("push", "acc");
9172 emitcode ("lcall", "__gptrget");
9174 emitcode ("pop", "b");
9179 /*-----------------------------------------------------------------*/
9180 /* emitPtrByteSet - emits code to set a byte from src through a */
9181 /* pointer register (R0, R1, or DPTR). */
9182 /*-----------------------------------------------------------------*/
9184 emitPtrByteSet (char *rname, int p_type, char *src)
9193 emitcode ("mov", "@%s,a", rname);
9196 emitcode ("mov", "@%s,%s", rname, src);
9201 emitcode ("movx", "@%s,a", rname);
9206 emitcode ("movx", "@dptr,a");
9211 emitcode ("lcall", "__gptrput");
9216 /*-----------------------------------------------------------------*/
9217 /* genUnpackBits - generates code for unpacking bits */
9218 /*-----------------------------------------------------------------*/
9220 genUnpackBits (operand * result, char *rname, int ptype)
9222 int offset = 0; /* result byte offset */
9223 int rsize; /* result size */
9224 int rlen = 0; /* remaining bitfield length */
9225 sym_link *etype; /* bitfield type information */
9226 int blen; /* bitfield length */
9227 int bstr; /* bitfield starting bit within byte */
9229 D(emitcode ("; genUnpackBits",""));
9231 etype = getSpec (operandType (result));
9232 rsize = getSize (operandType (result));
9233 blen = SPEC_BLEN (etype);
9234 bstr = SPEC_BSTR (etype);
9236 /* If the bitfield length is less than a byte */
9239 emitPtrByteGet (rname, ptype, FALSE);
9241 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9242 aopPut (AOP (result), "a", offset++);
9246 /* Bit field did not fit in a byte. Copy all
9247 but the partial byte at the end. */
9248 for (rlen=blen;rlen>=8;rlen-=8)
9250 emitPtrByteGet (rname, ptype, FALSE);
9251 aopPut (AOP (result), "a", offset++);
9253 emitcode ("inc", "%s", rname);
9256 /* Handle the partial byte at the end */
9259 emitPtrByteGet (rname, ptype, FALSE);
9260 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9261 aopPut (AOP (result), "a", offset++);
9269 aopPut (AOP (result), zero, offset++);
9274 /*-----------------------------------------------------------------*/
9275 /* genDataPointerGet - generates code when ptr offset is known */
9276 /*-----------------------------------------------------------------*/
9278 genDataPointerGet (operand * left,
9284 int size, offset = 0;
9285 aopOp (result, ic, TRUE, FALSE);
9287 /* get the string representation of the name */
9288 l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9289 size = AOP_SIZE (result);
9290 _startLazyDPSEvaluation ();
9295 SNPRINTF (buff, sizeof(buff),
9296 "(%s + %d)", l + 1, offset);
9300 SNPRINTF (buff, sizeof(buff),
9303 aopPut (AOP (result), buff, offset++);
9305 _endLazyDPSEvaluation ();
9307 freeAsmop (left, NULL, ic, TRUE);
9308 freeAsmop (result, NULL, ic, TRUE);
9311 /*-----------------------------------------------------------------*/
9312 /* genNearPointerGet - emitcode for near pointer fetch */
9313 /*-----------------------------------------------------------------*/
9315 genNearPointerGet (operand * left,
9323 sym_link *rtype, *retype, *letype;
9324 sym_link *ltype = operandType (left);
9327 rtype = operandType (result);
9328 retype = getSpec (rtype);
9329 letype = getSpec (ltype);
9331 aopOp (left, ic, FALSE, FALSE);
9333 /* if left is rematerialisable and
9334 result is not bit variable type and
9335 the left is pointer to data space i.e
9336 lower 128 bytes of space */
9337 if (AOP_TYPE (left) == AOP_IMMD &&
9338 !IS_BITVAR (retype) &&
9339 !IS_BITVAR (letype) &&
9340 DCL_TYPE (ltype) == POINTER)
9342 genDataPointerGet (left, result, ic);
9346 /* if the value is already in a pointer register
9347 then don't need anything more */
9348 if (!AOP_INPREG (AOP (left)))
9350 /* otherwise get a free pointer register */
9352 preg = getFreePtr (ic, &aop, FALSE);
9353 emitcode ("mov", "%s,%s",
9355 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9359 rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9361 freeAsmop (left, NULL, ic, TRUE);
9362 aopOp (result, ic, FALSE, FALSE);
9364 /* if bitfield then unpack the bits */
9365 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9366 genUnpackBits (result, rname, POINTER);
9369 /* we have can just get the values */
9370 int size = AOP_SIZE (result);
9375 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9378 emitcode ("mov", "a,@%s", rname);
9379 aopPut (AOP (result), "a", offset);
9383 SNPRINTF (buff, sizeof(buff), "@%s", rname);
9384 aopPut (AOP (result), buff, offset);
9389 emitcode ("inc", "%s", rname);
9394 /* now some housekeeping stuff */
9397 /* we had to allocate for this iCode */
9398 if (pi) { /* post increment present */
9399 aopPut(AOP ( left ),rname,0);
9401 freeAsmop (NULL, aop, ic, TRUE);
9405 /* we did not allocate which means left
9406 already in a pointer register, then
9407 if size > 0 && this could be used again
9408 we have to point it back to where it
9410 if (AOP_SIZE (result) > 1 &&
9411 !OP_SYMBOL (left)->remat &&
9412 (OP_SYMBOL (left)->liveTo > ic->seq ||
9416 int size = AOP_SIZE (result) - 1;
9418 emitcode ("dec", "%s", rname);
9423 freeAsmop (result, NULL, ic, TRUE);
9424 if (pi) pi->generated = 1;
9427 /*-----------------------------------------------------------------*/
9428 /* genPagedPointerGet - emitcode for paged pointer fetch */
9429 /*-----------------------------------------------------------------*/
9431 genPagedPointerGet (operand * left,
9439 sym_link *rtype, *retype, *letype;
9441 rtype = operandType (result);
9442 retype = getSpec (rtype);
9443 letype = getSpec (operandType (left));
9444 aopOp (left, ic, FALSE, FALSE);
9446 /* if the value is already in a pointer register
9447 then don't need anything more */
9448 if (!AOP_INPREG (AOP (left)))
9450 /* otherwise get a free pointer register */
9452 preg = getFreePtr (ic, &aop, FALSE);
9453 emitcode ("mov", "%s,%s",
9455 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9459 rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9461 freeAsmop (left, NULL, ic, TRUE);
9462 aopOp (result, ic, FALSE, FALSE);
9464 /* if bitfield then unpack the bits */
9465 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9466 genUnpackBits (result, rname, PPOINTER);
9469 /* we have can just get the values */
9470 int size = AOP_SIZE (result);
9476 emitcode ("movx", "a,@%s", rname);
9477 aopPut (AOP (result), "a", offset);
9482 emitcode ("inc", "%s", rname);
9486 /* now some housekeeping stuff */
9489 /* we had to allocate for this iCode */
9490 if (pi) aopPut ( AOP (left), rname, 0);
9491 freeAsmop (NULL, aop, ic, TRUE);
9495 /* we did not allocate which means left
9496 already in a pointer register, then
9497 if size > 0 && this could be used again
9498 we have to point it back to where it
9500 if (AOP_SIZE (result) > 1 &&
9501 !OP_SYMBOL (left)->remat &&
9502 (OP_SYMBOL (left)->liveTo > ic->seq ||
9506 int size = AOP_SIZE (result) - 1;
9508 emitcode ("dec", "%s", rname);
9513 freeAsmop (result, NULL, ic, TRUE);
9514 if (pi) pi->generated = 1;
9517 /*-----------------------------------------------------------------*/
9518 /* genFarPointerGet - gget value from far space */
9519 /*-----------------------------------------------------------------*/
9521 genFarPointerGet (operand * left,
9522 operand * result, iCode * ic, iCode *pi)
9524 int size, offset, dopi=1;
9525 sym_link *retype = getSpec (operandType (result));
9526 sym_link *letype = getSpec (operandType (left));
9527 D (emitcode (";", "genFarPointerGet"););
9529 aopOp (left, ic, FALSE, FALSE);
9531 /* if the operand is already in dptr
9532 then we do nothing else we move the value to dptr */
9533 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9535 /* if this is remateriazable */
9536 if (AOP_TYPE (left) == AOP_IMMD)
9538 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9542 /* we need to get it byte by byte */
9543 _startLazyDPSEvaluation ();
9544 if (AOP_TYPE (left) != AOP_DPTR)
9546 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9547 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9548 if (options.model == MODEL_FLAT24)
9549 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9553 /* We need to generate a load to DPTR indirect through DPTR. */
9554 D (emitcode (";", "genFarPointerGet -- indirection special case."););
9555 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9556 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9557 if (options.model == MODEL_FLAT24)
9558 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9559 emitcode ("pop", "dph");
9560 emitcode ("pop", "dpl");
9563 _endLazyDPSEvaluation ();
9566 /* so dptr know contains the address */
9567 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9569 /* if bit then unpack */
9570 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9571 if (AOP_INDPTRn(left)) {
9572 genSetDPTR(AOP(left)->aopu.dptr);
9574 genUnpackBits (result, "dptr", FPOINTER);
9575 if (AOP_INDPTRn(left)) {
9580 size = AOP_SIZE (result);
9583 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9585 genSetDPTR(AOP(left)->aopu.dptr);
9586 emitcode ("movx", "a,@dptr");
9587 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9588 emitcode ("inc", "dptr");
9590 aopPut (AOP (result), "a", offset++);
9593 _startLazyDPSEvaluation ();
9595 if (AOP_INDPTRn(left)) {
9596 genSetDPTR(AOP(left)->aopu.dptr);
9602 emitcode ("movx", "a,@dptr");
9603 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9604 emitcode ("inc", "dptr");
9606 aopPut (AOP (result), "a", offset++);
9608 _endLazyDPSEvaluation ();
9611 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9612 if (!AOP_INDPTRn(left)) {
9613 _startLazyDPSEvaluation ();
9614 aopPut ( AOP (left), "dpl", 0);
9615 aopPut ( AOP (left), "dph", 1);
9616 if (options.model == MODEL_FLAT24)
9617 aopPut ( AOP (left), "dpx", 2);
9618 _endLazyDPSEvaluation ();
9621 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
9622 AOP_SIZE(result) > 1 &&
9624 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9626 size = AOP_SIZE (result) - 1;
9627 if (AOP_INDPTRn(left)) {
9628 genSetDPTR(AOP(left)->aopu.dptr);
9630 while (size--) emitcode ("lcall","__decdptr");
9631 if (AOP_INDPTRn(left)) {
9636 freeAsmop (left, NULL, ic, TRUE);
9637 freeAsmop (result, NULL, ic, TRUE);
9640 /*-----------------------------------------------------------------*/
9641 /* genCodePointerGet - get value from code space */
9642 /*-----------------------------------------------------------------*/
9644 genCodePointerGet (operand * left,
9645 operand * result, iCode * ic, iCode *pi)
9647 int size, offset, dopi=1;
9648 sym_link *retype = getSpec (operandType (result));
9650 aopOp (left, ic, FALSE, FALSE);
9652 /* if the operand is already in dptr
9653 then we do nothing else we move the value to dptr */
9654 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9656 /* if this is remateriazable */
9657 if (AOP_TYPE (left) == AOP_IMMD)
9659 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9662 { /* we need to get it byte by byte */
9663 _startLazyDPSEvaluation ();
9664 if (AOP_TYPE (left) != AOP_DPTR)
9666 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9667 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9668 if (options.model == MODEL_FLAT24)
9669 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9673 /* We need to generate a load to DPTR indirect through DPTR. */
9674 D (emitcode (";", "gencodePointerGet -- indirection special case."););
9675 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9676 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9677 if (options.model == MODEL_FLAT24)
9678 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9679 emitcode ("pop", "dph");
9680 emitcode ("pop", "dpl");
9683 _endLazyDPSEvaluation ();
9686 /* so dptr know contains the address */
9687 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9689 /* if bit then unpack */
9690 if (IS_BITVAR (retype)) {
9691 if (AOP_INDPTRn(left)) {
9692 genSetDPTR(AOP(left)->aopu.dptr);
9694 genUnpackBits (result, "dptr", CPOINTER);
9695 if (AOP_INDPTRn(left)) {
9700 size = AOP_SIZE (result);
9702 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9704 genSetDPTR(AOP(left)->aopu.dptr);
9705 emitcode ("clr", "a");
9706 emitcode ("movc", "a,@a+dptr");
9707 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9708 emitcode ("inc", "dptr");
9710 aopPut (AOP (result), "a", offset++);
9713 _startLazyDPSEvaluation ();
9716 if (AOP_INDPTRn(left)) {
9717 genSetDPTR(AOP(left)->aopu.dptr);
9723 emitcode ("clr", "a");
9724 emitcode ("movc", "a,@a+dptr");
9725 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9726 emitcode ("inc", "dptr");
9727 aopPut (AOP (result), "a", offset++);
9729 _endLazyDPSEvaluation ();
9732 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9733 if (!AOP_INDPTRn(left)) {
9734 _startLazyDPSEvaluation ();
9736 aopPut ( AOP (left), "dpl", 0);
9737 aopPut ( AOP (left), "dph", 1);
9738 if (options.model == MODEL_FLAT24)
9739 aopPut ( AOP (left), "dpx", 2);
9741 _endLazyDPSEvaluation ();
9744 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9745 AOP_SIZE(result) > 1 &&
9746 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9748 size = AOP_SIZE (result) - 1;
9749 if (AOP_INDPTRn(left)) {
9750 genSetDPTR(AOP(left)->aopu.dptr);
9752 while (size--) emitcode ("lcall","__decdptr");
9753 if (AOP_INDPTRn(left)) {
9758 freeAsmop (left, NULL, ic, TRUE);
9759 freeAsmop (result, NULL, ic, TRUE);
9762 /*-----------------------------------------------------------------*/
9763 /* genGenPointerGet - gget value from generic pointer space */
9764 /*-----------------------------------------------------------------*/
9766 genGenPointerGet (operand * left,
9767 operand * result, iCode * ic, iCode * pi)
9770 sym_link *retype = getSpec (operandType (result));
9771 sym_link *letype = getSpec (operandType (left));
9773 D (emitcode (";", "genGenPointerGet "); );
9775 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9777 /* if the operand is already in dptr
9778 then we do nothing else we move the value to dptr */
9779 if (AOP_TYPE (left) != AOP_STR)
9781 /* if this is remateriazable */
9782 if (AOP_TYPE (left) == AOP_IMMD)
9784 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9785 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9787 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9791 emitcode ("mov", "b,#%d", pointerCode (retype));
9795 { /* we need to get it byte by byte */
9796 _startLazyDPSEvaluation ();
9797 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9798 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9799 if (options.model == MODEL_FLAT24) {
9800 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9801 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9803 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9805 _endLazyDPSEvaluation ();
9809 /* so dptr-b now contains the address */
9811 aopOp (result, ic, FALSE, TRUE);
9814 /* if bit then unpack */
9815 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9817 genUnpackBits (result, "dptr", GPOINTER);
9821 size = AOP_SIZE (result);
9828 // Get two bytes at a time, results in _AP & A.
9829 // dptr will be incremented ONCE by __gptrgetWord.
9831 // Note: any change here must be coordinated
9832 // with the implementation of __gptrgetWord
9833 // in device/lib/_gptrget.c
9834 emitcode ("lcall", "__gptrgetWord");
9835 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9836 aopPut (AOP (result), "a", offset++);
9841 // Only one byte to get.
9842 emitcode ("lcall", "__gptrget");
9843 aopPut (AOP (result), "a", offset++);
9846 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9848 emitcode ("inc", "dptr");
9853 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9854 _startLazyDPSEvaluation ();
9856 aopPut ( AOP (left), "dpl", 0);
9857 aopPut ( AOP (left), "dph", 1);
9858 if (options.model == MODEL_FLAT24) {
9859 aopPut ( AOP (left), "dpx", 2);
9860 aopPut ( AOP (left), "b", 3);
9861 } else aopPut ( AOP (left), "b", 2);
9863 _endLazyDPSEvaluation ();
9866 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9867 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9869 size = AOP_SIZE (result) - 1;
9870 while (size--) emitcode ("lcall","__decdptr");
9873 freeAsmop (left, NULL, ic, TRUE);
9874 freeAsmop (result, NULL, ic, TRUE);
9877 /*-----------------------------------------------------------------*/
9878 /* genPointerGet - generate code for pointer get */
9879 /*-----------------------------------------------------------------*/
9881 genPointerGet (iCode * ic, iCode *pi)
9883 operand *left, *result;
9884 sym_link *type, *etype;
9887 D (emitcode (";", "genPointerGet ");
9890 left = IC_LEFT (ic);
9891 result = IC_RESULT (ic);
9893 /* depending on the type of pointer we need to
9894 move it to the correct pointer register */
9895 type = operandType (left);
9896 etype = getSpec (type);
9897 /* if left is of type of pointer then it is simple */
9898 if (IS_PTR (type) && !IS_FUNC (type->next))
9899 p_type = DCL_TYPE (type);
9902 /* we have to go by the storage class */
9903 p_type = PTR_TYPE (SPEC_OCLS (etype));
9905 /* special case when cast remat */
9906 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9907 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9908 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9909 type = operandType (left);
9910 p_type = DCL_TYPE (type);
9912 /* now that we have the pointer type we assign
9913 the pointer values */
9919 genNearPointerGet (left, result, ic, pi);
9923 genPagedPointerGet (left, result, ic, pi);
9927 genFarPointerGet (left, result, ic, pi);
9931 genCodePointerGet (left, result, ic, pi);
9935 genGenPointerGet (left, result, ic, pi);
9941 /*-----------------------------------------------------------------*/
9942 /* genPackBits - generates code for packed bit storage */
9943 /*-----------------------------------------------------------------*/
9945 genPackBits (sym_link * etype,
9947 char *rname, int p_type)
9949 int offset = 0; /* source byte offset */
9950 int rlen = 0; /* remaining bitfield length */
9951 int blen; /* bitfield length */
9952 int bstr; /* bitfield starting bit within byte */
9953 int litval; /* source literal value (if AOP_LIT) */
9954 unsigned char mask; /* bitmask within current byte */
9956 D(emitcode ("; genPackBits",""));
9958 blen = SPEC_BLEN (etype);
9959 bstr = SPEC_BSTR (etype);
9961 /* If the bitfield length is less than a byte */
9964 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9965 (unsigned char) (0xFF >> (8 - bstr)));
9967 if (AOP_TYPE (right) == AOP_LIT)
9969 /* Case with a bitfield length <8 and literal source
9971 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9973 litval &= (~mask) & 0xff;
9974 emitPtrByteGet (rname, p_type, FALSE);
9975 if ((mask|litval)!=0xff)
9976 emitcode ("anl","a,#!constbyte", mask);
9978 emitcode ("orl","a,#!constbyte", litval);
9982 if ((blen==1) && (p_type!=GPOINTER))
9984 /* Case with a bitfield length == 1 and no generic pointer
9986 if (AOP_TYPE (right) == AOP_CRY)
9987 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9990 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9991 emitcode ("rrc","a");
9993 emitPtrByteGet (rname, p_type, FALSE);
9994 emitcode ("mov","acc.%d,c",bstr);
9998 /* Case with a bitfield length < 8 and arbitrary source
10000 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10001 /* shift and mask source value */
10003 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10005 /* transfer A to B and get next byte */
10006 emitPtrByteGet (rname, p_type, TRUE);
10008 emitcode ("anl", "a,#!constbyte", mask);
10009 emitcode ("orl", "a,b");
10010 if (p_type == GPOINTER)
10011 emitcode ("pop", "b");
10015 emitPtrByteSet (rname, p_type, "a");
10019 /* Bit length is greater than 7 bits. In this case, copy */
10020 /* all except the partial byte at the end */
10021 for (rlen=blen;rlen>=8;rlen-=8)
10023 emitPtrByteSet (rname, p_type,
10024 aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
10026 emitcode ("inc", "%s", rname);
10029 /* If there was a partial byte at the end */
10032 mask = (((unsigned char) -1 << rlen) & 0xff);
10034 if (AOP_TYPE (right) == AOP_LIT)
10036 /* Case with partial byte and literal source
10038 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10039 litval >>= (blen-rlen);
10040 litval &= (~mask) & 0xff;
10041 emitPtrByteGet (rname, p_type, FALSE);
10042 if ((mask|litval)!=0xff)
10043 emitcode ("anl","a,#!constbyte", mask);
10045 emitcode ("orl","a,#!constbyte", litval);
10049 /* Case with partial byte and arbitrary source
10051 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10052 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10054 /* transfer A to B and get next byte */
10055 emitPtrByteGet (rname, p_type, TRUE);
10057 emitcode ("anl", "a,#!constbyte", mask);
10058 emitcode ("orl", "a,b");
10059 if (p_type == GPOINTER)
10060 emitcode ("pop", "b");
10062 emitPtrByteSet (rname, p_type, "a");
10068 /*-----------------------------------------------------------------*/
10069 /* genDataPointerSet - remat pointer to data space */
10070 /*-----------------------------------------------------------------*/
10072 genDataPointerSet (operand * right,
10076 int size, offset = 0;
10077 char *l, buff[256];
10079 aopOp (right, ic, FALSE, FALSE);
10081 l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
10082 size = AOP_SIZE (right);
10087 SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
10091 SNPRINTF (buff, sizeof(buff), "%s", l + 1);
10094 emitcode ("mov", "%s,%s", buff,
10095 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10098 freeAsmop (right, NULL, ic, TRUE);
10099 freeAsmop (result, NULL, ic, TRUE);
10102 /*-----------------------------------------------------------------*/
10103 /* genNearPointerSet - emitcode for near pointer put */
10104 /*-----------------------------------------------------------------*/
10106 genNearPointerSet (operand * right,
10113 sym_link *retype, *letype;
10114 sym_link *ptype = operandType (result);
10116 retype = getSpec (operandType (right));
10117 letype = getSpec (ptype);
10119 aopOp (result, ic, FALSE, FALSE);
10121 /* if the result is rematerializable &
10122 in data space & not a bit variable */
10123 if (AOP_TYPE (result) == AOP_IMMD &&
10124 DCL_TYPE (ptype) == POINTER &&
10125 !IS_BITVAR (retype) &&
10126 !IS_BITVAR (letype))
10128 genDataPointerSet (right, result, ic);
10132 /* if the value is already in a pointer register
10133 then don't need anything more */
10134 if (!AOP_INPREG (AOP (result)))
10136 /* otherwise get a free pointer register */
10139 aop = newAsmop (0);
10140 preg = getFreePtr (ic, &aop, FALSE);
10141 emitcode ("mov", "%s,%s",
10143 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10144 rname = preg->name;
10147 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10149 aopOp (right, ic, FALSE, FALSE);
10151 /* if bitfield then unpack the bits */
10152 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10153 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
10156 /* we have can just get the values */
10157 int size = AOP_SIZE (right);
10162 l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10166 emitcode ("mov", "@%s,a", rname);
10169 emitcode ("mov", "@%s,%s", rname, l);
10171 emitcode ("inc", "%s", rname);
10176 /* now some housekeeping stuff */
10179 /* we had to allocate for this iCode */
10180 if (pi) aopPut (AOP (result),rname,0);
10181 freeAsmop (NULL, aop, ic, TRUE);
10185 /* we did not allocate which means left
10186 already in a pointer register, then
10187 if size > 0 && this could be used again
10188 we have to point it back to where it
10190 if (AOP_SIZE (right) > 1 &&
10191 !OP_SYMBOL (result)->remat &&
10192 (OP_SYMBOL (result)->liveTo > ic->seq ||
10196 int size = AOP_SIZE (right) - 1;
10198 emitcode ("dec", "%s", rname);
10203 if (pi) pi->generated = 1;
10204 freeAsmop (result, NULL, ic, TRUE);
10205 freeAsmop (right, NULL, ic, TRUE);
10210 /*-----------------------------------------------------------------*/
10211 /* genPagedPointerSet - emitcode for Paged pointer put */
10212 /*-----------------------------------------------------------------*/
10214 genPagedPointerSet (operand * right,
10221 sym_link *retype, *letype;
10223 retype = getSpec (operandType (right));
10224 letype = getSpec (operandType (result));
10226 aopOp (result, ic, FALSE, FALSE);
10228 /* if the value is already in a pointer register
10229 then don't need anything more */
10230 if (!AOP_INPREG (AOP (result)))
10232 /* otherwise get a free pointer register */
10235 aop = newAsmop (0);
10236 preg = getFreePtr (ic, &aop, FALSE);
10237 emitcode ("mov", "%s,%s",
10239 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10240 rname = preg->name;
10243 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10245 aopOp (right, ic, FALSE, FALSE);
10247 /* if bitfield then unpack the bits */
10248 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10249 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10252 /* we have can just get the values */
10253 int size = AOP_SIZE (right);
10258 MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10260 emitcode ("movx", "@%s,a", rname);
10263 emitcode ("inc", "%s", rname);
10269 /* now some housekeeping stuff */
10272 if (pi) aopPut (AOP (result),rname,0);
10273 /* we had to allocate for this iCode */
10274 freeAsmop (NULL, aop, ic, TRUE);
10278 /* we did not allocate which means left
10279 already in a pointer register, then
10280 if size > 0 && this could be used again
10281 we have to point it back to where it
10283 if (AOP_SIZE (right) > 1 &&
10284 !OP_SYMBOL (result)->remat &&
10285 (OP_SYMBOL (result)->liveTo > ic->seq ||
10289 int size = AOP_SIZE (right) - 1;
10291 emitcode ("dec", "%s", rname);
10296 if (pi) pi->generated = 1;
10297 freeAsmop (result, NULL, ic, TRUE);
10298 freeAsmop (right, NULL, ic, TRUE);
10303 /*-----------------------------------------------------------------*/
10304 /* genFarPointerSet - set value from far space */
10305 /*-----------------------------------------------------------------*/
10307 genFarPointerSet (operand * right,
10308 operand * result, iCode * ic, iCode *pi)
10310 int size, offset, dopi=1;
10311 sym_link *retype = getSpec (operandType (right));
10312 sym_link *letype = getSpec (operandType (result));
10314 aopOp (result, ic, FALSE, FALSE);
10316 /* if the operand is already in dptr
10317 then we do nothing else we move the value to dptr */
10318 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10320 /* if this is remateriazable */
10321 if (AOP_TYPE (result) == AOP_IMMD)
10322 emitcode ("mov", "dptr,%s",
10323 aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10326 /* we need to get it byte by byte */
10327 _startLazyDPSEvaluation ();
10328 if (AOP_TYPE (result) != AOP_DPTR)
10330 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10331 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10332 if (options.model == MODEL_FLAT24)
10333 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10337 /* We need to generate a load to DPTR indirect through DPTR. */
10338 D (emitcode (";", "genFarPointerSet -- indirection special case."););
10340 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10341 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10342 if (options.model == MODEL_FLAT24)
10343 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10344 emitcode ("pop", "dph");
10345 emitcode ("pop", "dpl");
10348 _endLazyDPSEvaluation ();
10351 /* so dptr know contains the address */
10352 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10354 /* if bit then unpack */
10355 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10356 if (AOP_INDPTRn(result)) {
10357 genSetDPTR(AOP(result)->aopu.dptr);
10359 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10360 if (AOP_INDPTRn(result)) {
10364 size = AOP_SIZE (right);
10366 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10368 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10370 genSetDPTR(AOP(result)->aopu.dptr);
10371 emitcode ("movx", "@dptr,a");
10372 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10373 emitcode ("inc", "dptr");
10377 _startLazyDPSEvaluation ();
10379 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10381 if (AOP_INDPTRn(result)) {
10382 genSetDPTR(AOP(result)->aopu.dptr);
10388 emitcode ("movx", "@dptr,a");
10389 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10390 emitcode ("inc", "dptr");
10392 _endLazyDPSEvaluation ();
10396 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10397 if (!AOP_INDPTRn(result)) {
10398 _startLazyDPSEvaluation ();
10400 aopPut (AOP(result),"dpl",0);
10401 aopPut (AOP(result),"dph",1);
10402 if (options.model == MODEL_FLAT24)
10403 aopPut (AOP(result),"dpx",2);
10405 _endLazyDPSEvaluation ();
10408 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10409 AOP_SIZE(right) > 1 &&
10410 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10412 size = AOP_SIZE (right) - 1;
10413 if (AOP_INDPTRn(result)) {
10414 genSetDPTR(AOP(result)->aopu.dptr);
10416 while (size--) emitcode ("lcall","__decdptr");
10417 if (AOP_INDPTRn(result)) {
10421 freeAsmop (result, NULL, ic, TRUE);
10422 freeAsmop (right, NULL, ic, TRUE);
10425 /*-----------------------------------------------------------------*/
10426 /* genGenPointerSet - set value from generic pointer space */
10427 /*-----------------------------------------------------------------*/
10429 genGenPointerSet (operand * right,
10430 operand * result, iCode * ic, iCode *pi)
10433 sym_link *retype = getSpec (operandType (right));
10434 sym_link *letype = getSpec (operandType (result));
10436 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10438 /* if the operand is already in dptr
10439 then we do nothing else we move the value to dptr */
10440 if (AOP_TYPE (result) != AOP_STR)
10442 _startLazyDPSEvaluation ();
10443 /* if this is remateriazable */
10444 if (AOP_TYPE (result) == AOP_IMMD)
10446 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10447 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10449 MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10454 "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10458 { /* we need to get it byte by byte */
10459 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10460 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10461 if (options.model == MODEL_FLAT24) {
10462 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10463 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10465 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10468 _endLazyDPSEvaluation ();
10470 /* so dptr + b now contains the address */
10472 aopOp (right, ic, FALSE, TRUE);
10476 /* if bit then unpack */
10477 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10479 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10483 size = AOP_SIZE (right);
10486 _startLazyDPSEvaluation ();
10491 // Set two bytes at a time, passed in _AP & A.
10492 // dptr will be incremented ONCE by __gptrputWord.
10494 // Note: any change here must be coordinated
10495 // with the implementation of __gptrputWord
10496 // in device/lib/_gptrput.c
10497 emitcode("mov", "_ap, %s",
10498 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10499 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10503 emitcode ("lcall", "__gptrputWord");
10508 // Only one byte to put.
10509 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10513 emitcode ("lcall", "__gptrput");
10516 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10518 emitcode ("inc", "dptr");
10521 _endLazyDPSEvaluation ();
10524 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10525 _startLazyDPSEvaluation ();
10527 aopPut (AOP(result),"dpl",0);
10528 aopPut (AOP(result),"dph",1);
10529 if (options.model == MODEL_FLAT24) {
10530 aopPut (AOP(result),"dpx",2);
10531 aopPut (AOP(result),"b",3);
10533 aopPut (AOP(result),"b",2);
10535 _endLazyDPSEvaluation ();
10538 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10539 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10541 size = AOP_SIZE (right) - 1;
10542 while (size--) emitcode ("lcall","__decdptr");
10544 freeAsmop (result, NULL, ic, TRUE);
10545 freeAsmop (right, NULL, ic, TRUE);
10548 /*-----------------------------------------------------------------*/
10549 /* genPointerSet - stores the value into a pointer location */
10550 /*-----------------------------------------------------------------*/
10552 genPointerSet (iCode * ic, iCode *pi)
10554 operand *right, *result;
10555 sym_link *type, *etype;
10558 D (emitcode (";", "genPointerSet "););
10560 right = IC_RIGHT (ic);
10561 result = IC_RESULT (ic);
10563 /* depending on the type of pointer we need to
10564 move it to the correct pointer register */
10565 type = operandType (result);
10566 etype = getSpec (type);
10567 /* if left is of type of pointer then it is simple */
10568 if (IS_PTR (type) && !IS_FUNC (type->next))
10570 p_type = DCL_TYPE (type);
10574 /* we have to go by the storage class */
10575 p_type = PTR_TYPE (SPEC_OCLS (etype));
10577 /* special case when cast remat */
10578 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10579 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10580 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10581 type = operandType (result);
10582 p_type = DCL_TYPE (type);
10585 /* now that we have the pointer type we assign
10586 the pointer values */
10592 genNearPointerSet (right, result, ic, pi);
10596 genPagedPointerSet (right, result, ic, pi);
10600 genFarPointerSet (right, result, ic, pi);
10604 genGenPointerSet (right, result, ic, pi);
10608 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10609 "genPointerSet: illegal pointer type");
10614 /*-----------------------------------------------------------------*/
10615 /* genIfx - generate code for Ifx statement */
10616 /*-----------------------------------------------------------------*/
10618 genIfx (iCode * ic, iCode * popIc)
10620 operand *cond = IC_COND (ic);
10623 D (emitcode (";", "genIfx "););
10625 aopOp (cond, ic, FALSE, FALSE);
10627 /* get the value into acc */
10628 if (AOP_TYPE (cond) != AOP_CRY)
10637 /* the result is now in the accumulator */
10638 freeAsmop (cond, NULL, ic, TRUE);
10640 /* if there was something to be popped then do it */
10644 /* if the condition is a bit variable */
10645 if (isbit && IS_ITEMP (cond) &&
10648 genIfxJump (ic, SPIL_LOC (cond)->rname);
10650 else if (isbit && !IS_ITEMP (cond))
10652 genIfxJump (ic, OP_SYMBOL (cond)->rname);
10656 genIfxJump (ic, "a");
10662 /*-----------------------------------------------------------------*/
10663 /* genAddrOf - generates code for address of */
10664 /*-----------------------------------------------------------------*/
10666 genAddrOf (iCode * ic)
10668 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10671 D (emitcode (";", "genAddrOf ");
10674 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10676 /* if the operand is on the stack then we
10677 need to get the stack offset of this
10679 if (sym->onStack) {
10681 /* if 10 bit stack */
10682 if (options.stack10bit) {
10686 tsprintf(buff, sizeof(buff),
10687 "#!constbyte",(options.stack_loc >> 16) & 0xff);
10688 /* if it has an offset then we need to compute it */
10689 /* emitcode ("subb", "a,#!constbyte", */
10690 /* -((sym->stack < 0) ? */
10691 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10692 /* ((short) sym->stack)) & 0xff); */
10693 /* emitcode ("mov","b,a"); */
10694 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10695 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10696 /* ((short) sym->stack)) >> 8) & 0xff); */
10698 emitcode ("mov", "a,_bpx");
10699 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
10700 ((char) (sym->stack - _G.nRegsSaved)) :
10701 ((char) sym->stack )) & 0xff);
10702 emitcode ("mov", "b,a");
10703 emitcode ("mov", "a,_bpx+1");
10705 offset = (((sym->stack < 0) ?
10706 ((short) (sym->stack - _G.nRegsSaved)) :
10707 ((short) sym->stack )) >> 8) & 0xff;
10709 emitcode ("addc","a,#!constbyte", offset);
10711 aopPut (AOP (IC_RESULT (ic)), "b", 0);
10712 aopPut (AOP (IC_RESULT (ic)), "a", 1);
10713 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10715 /* we can just move _bp */
10716 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10717 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10718 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10721 /* if it has an offset then we need to compute it */
10723 emitcode ("mov", "a,_bp");
10724 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10725 aopPut (AOP (IC_RESULT (ic)), "a", 0);
10727 /* we can just move _bp */
10728 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10730 /* fill the result with zero */
10731 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10734 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10736 "*** warning: pointer to stack var truncated.\n");
10741 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10747 /* object not on stack then we need the name */
10748 size = AOP_SIZE (IC_RESULT (ic));
10753 char s[SDCC_NAME_MAX];
10757 tsprintf(s, sizeof(s), "#!his",sym->rname);
10760 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
10763 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
10765 default: /* should not need this (just in case) */
10766 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10773 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10776 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10780 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10784 #if 0 // obsolete, and buggy for != xdata
10785 /*-----------------------------------------------------------------*/
10786 /* genArrayInit - generates code for address of */
10787 /*-----------------------------------------------------------------*/
10789 genArrayInit (iCode * ic)
10791 literalList *iLoop;
10793 int elementSize = 0, eIndex;
10794 unsigned val, lastVal;
10796 operand *left=IC_LEFT(ic);
10798 D (emitcode (";", "genArrayInit "););
10800 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10802 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10804 // Load immediate value into DPTR.
10805 emitcode("mov", "dptr, %s",
10806 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10808 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10811 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10812 "Unexpected operand to genArrayInit.\n");
10815 // a regression because of SDCCcse.c:1.52
10816 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10817 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10818 if (options.model == MODEL_FLAT24)
10819 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10823 type = operandType(IC_LEFT(ic));
10825 if (type && type->next)
10827 elementSize = getSize(type->next);
10831 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10832 "can't determine element size in genArrayInit.\n");
10836 iLoop = IC_ARRAYILIST(ic);
10841 bool firstpass = TRUE;
10843 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10844 iLoop->count, (int)iLoop->literalValue, elementSize);
10850 symbol *tlbl = NULL;
10852 count = ix > 256 ? 256 : ix;
10856 tlbl = newiTempLabel (NULL);
10857 if (firstpass || (count & 0xff))
10859 emitcode("mov", "b, #!constbyte", count & 0xff);
10862 emitcode ("", "!tlabeldef", tlbl->key + 100);
10867 for (eIndex = 0; eIndex < elementSize; eIndex++)
10869 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10870 if (val != lastVal)
10872 emitcode("mov", "a, #!constbyte", val);
10876 emitcode("movx", "@dptr, a");
10877 emitcode("inc", "dptr");
10882 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10888 iLoop = iLoop->next;
10891 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10895 /*-----------------------------------------------------------------*/
10896 /* genFarFarAssign - assignment when both are in far space */
10897 /*-----------------------------------------------------------------*/
10899 genFarFarAssign (operand * result, operand * right, iCode * ic)
10901 int size = AOP_SIZE (right);
10903 symbol *rSym = NULL;
10907 /* quick & easy case. */
10908 D(emitcode(";","genFarFarAssign (1 byte case)"););
10909 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10910 freeAsmop (right, NULL, ic, FALSE);
10911 /* now assign DPTR to result */
10913 aopOp(result, ic, FALSE, FALSE);
10915 aopPut(AOP(result), "a", 0);
10916 freeAsmop(result, NULL, ic, FALSE);
10920 /* See if we've got an underlying symbol to abuse. */
10921 if (IS_SYMOP(result) && OP_SYMBOL(result))
10923 if (IS_TRUE_SYMOP(result))
10925 rSym = OP_SYMBOL(result);
10927 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10929 rSym = OP_SYMBOL(result)->usl.spillLoc;
10933 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10935 /* We can use the '390 auto-toggle feature to good effect here. */
10937 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10938 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10939 emitcode ("mov", "dptr,#%s", rSym->rname);
10940 /* DP2 = result, DP1 = right, DP1 is current. */
10943 emitcode("movx", "a,@dptr");
10944 emitcode("movx", "@dptr,a");
10947 emitcode("inc", "dptr");
10948 emitcode("inc", "dptr");
10951 emitcode("mov", "dps,#0");
10952 freeAsmop (right, NULL, ic, FALSE);
10954 some alternative code for processors without auto-toggle
10955 no time to test now, so later well put in...kpb
10956 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10957 emitcode("mov", "dps,#1"); /* Select DPTR2. */
10958 emitcode ("mov", "dptr,#%s", rSym->rname);
10959 /* DP2 = result, DP1 = right, DP1 is current. */
10963 emitcode("movx", "a,@dptr");
10965 emitcode("inc", "dptr");
10966 emitcode("inc", "dps");
10967 emitcode("movx", "@dptr,a");
10969 emitcode("inc", "dptr");
10970 emitcode("inc", "dps");
10972 emitcode("mov", "dps,#0");
10973 freeAsmop (right, NULL, ic, FALSE);
10978 D (emitcode (";", "genFarFarAssign"););
10979 aopOp (result, ic, TRUE, TRUE);
10981 _startLazyDPSEvaluation ();
10985 aopPut (AOP (result),
10986 aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10989 _endLazyDPSEvaluation ();
10990 freeAsmop (result, NULL, ic, FALSE);
10991 freeAsmop (right, NULL, ic, FALSE);
10995 /*-----------------------------------------------------------------*/
10996 /* genAssign - generate code for assignment */
10997 /*-----------------------------------------------------------------*/
10999 genAssign (iCode * ic)
11001 operand *result, *right;
11003 unsigned long lit = 0L;
11005 D (emitcode (";", "genAssign ");
11008 result = IC_RESULT (ic);
11009 right = IC_RIGHT (ic);
11011 /* if they are the same */
11012 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11015 aopOp (right, ic, FALSE, FALSE);
11017 emitcode (";", "genAssign: resultIsFar = %s",
11018 isOperandInFarSpace (result) ?
11021 /* special case both in far space */
11022 if ((AOP_TYPE (right) == AOP_DPTR ||
11023 AOP_TYPE (right) == AOP_DPTR2) &&
11024 /* IS_TRUE_SYMOP(result) && */
11025 isOperandInFarSpace (result))
11027 genFarFarAssign (result, right, ic);
11031 aopOp (result, ic, TRUE, FALSE);
11033 /* if they are the same registers */
11034 if (sameRegs (AOP (right), AOP (result)))
11037 /* if the result is a bit */
11038 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
11040 /* if the right size is a literal then
11041 we know what the value is */
11042 if (AOP_TYPE (right) == AOP_LIT)
11044 if (((int) operandLitValue (right)))
11045 aopPut (AOP (result), one, 0);
11047 aopPut (AOP (result), zero, 0);
11051 /* the right is also a bit variable */
11052 if (AOP_TYPE (right) == AOP_CRY)
11054 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11055 aopPut (AOP (result), "c", 0);
11059 /* we need to or */
11061 aopPut (AOP (result), "a", 0);
11065 /* bit variables done */
11067 size = AOP_SIZE (result);
11069 if (AOP_TYPE (right) == AOP_LIT)
11070 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11073 (AOP_TYPE (result) != AOP_REG) &&
11074 (AOP_TYPE (right) == AOP_LIT) &&
11075 !IS_FLOAT (operandType (right)))
11077 _startLazyDPSEvaluation ();
11078 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
11080 aopPut (AOP (result),
11081 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11086 /* And now fill the rest with zeros. */
11089 emitcode ("clr", "a");
11093 aopPut (AOP (result), "a", offset++);
11095 _endLazyDPSEvaluation ();
11099 _startLazyDPSEvaluation ();
11102 aopPut (AOP (result),
11103 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11107 _endLazyDPSEvaluation ();
11111 freeAsmop (right, NULL, ic, FALSE);
11112 freeAsmop (result, NULL, ic, TRUE);
11115 /*-----------------------------------------------------------------*/
11116 /* genJumpTab - generates code for jump table */
11117 /*-----------------------------------------------------------------*/
11119 genJumpTab (iCode * ic)
11124 D (emitcode (";", "genJumpTab ");
11127 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11128 /* get the condition into accumulator */
11129 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11131 /* multiply by four! */
11132 emitcode ("add", "a,acc");
11133 emitcode ("add", "a,acc");
11134 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11136 jtab = newiTempLabel (NULL);
11137 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11138 emitcode ("jmp", "@a+dptr");
11139 emitcode ("", "!tlabeldef", jtab->key + 100);
11140 /* now generate the jump labels */
11141 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11142 jtab = setNextItem (IC_JTLABELS (ic)))
11143 emitcode ("ljmp", "!tlabel", jtab->key + 100);
11147 /*-----------------------------------------------------------------*/
11148 /* genCast - gen code for casting */
11149 /*-----------------------------------------------------------------*/
11151 genCast (iCode * ic)
11153 operand *result = IC_RESULT (ic);
11154 sym_link *ctype = operandType (IC_LEFT (ic));
11155 sym_link *rtype = operandType (IC_RIGHT (ic));
11156 operand *right = IC_RIGHT (ic);
11159 D (emitcode (";", "genCast "););
11161 /* if they are equivalent then do nothing */
11162 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11165 aopOp (right, ic, FALSE, FALSE);
11166 aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
11168 /* if the result is a bit */
11169 if (IS_BITVAR (OP_SYMBOL (result)->type)
11170 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11172 /* if the right size is a literal then
11173 we know what the value is */
11174 if (AOP_TYPE (right) == AOP_LIT)
11176 if (((int) operandLitValue (right)))
11177 aopPut (AOP (result), one, 0);
11179 aopPut (AOP (result), zero, 0);
11184 /* the right is also a bit variable */
11185 if (AOP_TYPE (right) == AOP_CRY)
11187 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11188 aopPut (AOP (result), "c", 0);
11192 /* we need to or */
11194 aopPut (AOP (result), "a", 0);
11198 /* if they are the same size : or less */
11199 if (AOP_SIZE (result) <= AOP_SIZE (right))
11202 /* if they are in the same place */
11203 if (sameRegs (AOP (right), AOP (result)))
11206 /* if they in different places then copy */
11207 size = AOP_SIZE (result);
11209 _startLazyDPSEvaluation ();
11212 aopPut (AOP (result),
11213 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11217 _endLazyDPSEvaluation ();
11222 /* if the result is of type pointer */
11223 if (IS_PTR (ctype))
11227 sym_link *type = operandType (right);
11229 /* pointer to generic pointer */
11230 if (IS_GENPTR (ctype))
11234 p_type = DCL_TYPE (type);
11238 #if OLD_CAST_BEHAVIOR
11239 /* KV: we are converting a non-pointer type to
11240 * a generic pointer. This (ifdef'd out) code
11241 * says that the resulting generic pointer
11242 * should have the same class as the storage
11243 * location of the non-pointer variable.
11245 * For example, converting an int (which happens
11246 * to be stored in DATA space) to a pointer results
11247 * in a DATA generic pointer; if the original int
11248 * in XDATA space, so will be the resulting pointer.
11250 * I don't like that behavior, and thus this change:
11251 * all such conversions will be forced to XDATA and
11252 * throw a warning. If you want some non-XDATA
11253 * type, or you want to suppress the warning, you
11254 * must go through an intermediate cast, like so:
11256 * char _generic *gp = (char _xdata *)(intVar);
11258 sym_link *etype = getSpec (type);
11260 /* we have to go by the storage class */
11261 if (SPEC_OCLS (etype) != generic)
11263 p_type = PTR_TYPE (SPEC_OCLS (etype));
11268 /* Converting unknown class (i.e. register variable)
11269 * to generic pointer. This is not good, but
11270 * we'll make a guess (and throw a warning).
11273 werror (W_INT_TO_GEN_PTR_CAST);
11277 /* the first two bytes are known */
11278 size = GPTRSIZE - 1;
11280 _startLazyDPSEvaluation ();
11283 aopPut (AOP (result),
11284 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11288 _endLazyDPSEvaluation ();
11290 /* the last byte depending on type */
11292 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11297 // pointerTypeToGPByte will have bitched.
11301 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11302 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11307 /* just copy the pointers */
11308 size = AOP_SIZE (result);
11310 _startLazyDPSEvaluation ();
11313 aopPut (AOP (result),
11314 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11318 _endLazyDPSEvaluation ();
11322 /* so we now know that the size of destination is greater
11323 than the size of the source */
11324 /* we move to result for the size of source */
11325 size = AOP_SIZE (right);
11327 _startLazyDPSEvaluation ();
11330 aopPut (AOP (result),
11331 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11335 _endLazyDPSEvaluation ();
11337 /* now depending on the sign of the source && destination */
11338 size = AOP_SIZE (result) - AOP_SIZE (right);
11339 /* if unsigned or not an integral type */
11340 /* also, if the source is a bit, we don't need to sign extend, because
11341 * it can't possibly have set the sign bit.
11343 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11347 aopPut (AOP (result), zero, offset++);
11352 /* we need to extend the sign :{ */
11353 MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11354 FALSE, FALSE, NULL));
11355 emitcode ("rlc", "a");
11356 emitcode ("subb", "a,acc");
11358 aopPut (AOP (result), "a", offset++);
11361 /* we are done hurray !!!! */
11364 freeAsmop (right, NULL, ic, TRUE);
11365 freeAsmop (result, NULL, ic, TRUE);
11369 /*-----------------------------------------------------------------*/
11370 /* genDjnz - generate decrement & jump if not zero instrucion */
11371 /*-----------------------------------------------------------------*/
11373 genDjnz (iCode * ic, iCode * ifx)
11375 symbol *lbl, *lbl1;
11379 /* if the if condition has a false label
11380 then we cannot save */
11381 if (IC_FALSE (ifx))
11384 /* if the minus is not of the form
11386 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11387 !IS_OP_LITERAL (IC_RIGHT (ic)))
11390 if (operandLitValue (IC_RIGHT (ic)) != 1)
11393 /* if the size of this greater than one then no
11395 if (getSize (operandType (IC_RESULT (ic))) > 1)
11398 /* otherwise we can save BIG */
11399 D(emitcode(";", "genDjnz"););
11401 lbl = newiTempLabel (NULL);
11402 lbl1 = newiTempLabel (NULL);
11404 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11406 if (AOP_NEEDSACC(IC_RESULT(ic)))
11408 /* If the result is accessed indirectly via
11409 * the accumulator, we must explicitly write
11410 * it back after the decrement.
11412 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11414 if (strcmp(rByte, "a"))
11416 /* Something is hopelessly wrong */
11417 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11418 __FILE__, __LINE__);
11419 /* We can just give up; the generated code will be inefficient,
11420 * but what the hey.
11422 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11425 emitcode ("dec", "%s", rByte);
11426 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11427 emitcode ("jnz", "!tlabel", lbl->key + 100);
11429 else if (IS_AOP_PREG (IC_RESULT (ic)))
11431 emitcode ("dec", "%s",
11432 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11433 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11434 emitcode ("jnz", "!tlabel", lbl->key + 100);
11438 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11441 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11442 emitcode ("", "!tlabeldef", lbl->key + 100);
11443 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11444 emitcode ("", "!tlabeldef", lbl1->key + 100);
11446 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11447 ifx->generated = 1;
11451 /*-----------------------------------------------------------------*/
11452 /* genReceive - generate code for a receive iCode */
11453 /*-----------------------------------------------------------------*/
11455 genReceive (iCode * ic)
11457 int size = getSize (operandType (IC_RESULT (ic)));
11461 D (emitcode (";", "genReceive "););
11463 if (ic->argreg == 1)
11465 /* first parameter */
11466 if (AOP_IS_STR(IC_RESULT(ic)))
11468 /* Nothing to do: it's already in the proper place. */
11475 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11476 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11477 IS_TRUE_SYMOP (IC_RESULT (ic)));
11480 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11483 /* Sanity checking... */
11484 if (AOP_USESDPTR(IC_RESULT(ic)))
11486 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11487 "genReceive got unexpected DPTR.");
11489 assignResultValue (IC_RESULT (ic));
11494 /* second receive onwards */
11495 /* this gets a little tricky since unused recevies will be
11496 eliminated, we have saved the reg in the type field . and
11497 we use that to figure out which register to use */
11498 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11499 rb1off = ic->argreg;
11502 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11505 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11508 /*-----------------------------------------------------------------*/
11509 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11510 /*-----------------------------------------------------------------*/
11511 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11513 operand *from , *to , *count;
11518 /* we know it has to be 3 parameters */
11519 assert (nparms == 3);
11521 rsave = newBitVect(16);
11522 /* save DPTR if it needs to be saved */
11523 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11524 if (bitVectBitValue(ic->rMask,i))
11525 rsave = bitVectSetBit(rsave,i);
11527 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11528 ds390_rUmaskForOp (IC_RESULT(ic))));
11535 aopOp (from, ic->next, FALSE, FALSE);
11537 /* get from into DPTR1 */
11538 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11539 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11540 if (options.model == MODEL_FLAT24) {
11541 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11544 freeAsmop (from, NULL, ic, FALSE);
11545 aopOp (to, ic, FALSE, FALSE);
11546 /* get "to" into DPTR */
11547 /* if the operand is already in dptr
11548 then we do nothing else we move the value to dptr */
11549 if (AOP_TYPE (to) != AOP_STR) {
11550 /* if already in DPTR then we need to push */
11551 if (AOP_TYPE(to) == AOP_DPTR) {
11552 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11553 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11554 if (options.model == MODEL_FLAT24)
11555 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11556 emitcode ("pop", "dph");
11557 emitcode ("pop", "dpl");
11559 _startLazyDPSEvaluation ();
11560 /* if this is remateriazable */
11561 if (AOP_TYPE (to) == AOP_IMMD) {
11562 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11563 } else { /* we need to get it byte by byte */
11564 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11565 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11566 if (options.model == MODEL_FLAT24) {
11567 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11570 _endLazyDPSEvaluation ();
11573 freeAsmop (to, NULL, ic, FALSE);
11574 _G.dptrInUse = _G.dptr1InUse = 1;
11575 aopOp (count, ic->next->next, FALSE,FALSE);
11576 lbl =newiTempLabel(NULL);
11578 /* now for the actual copy */
11579 if (AOP_TYPE(count) == AOP_LIT &&
11580 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11581 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11583 emitcode ("lcall","__bi_memcpyc2x_s");
11585 emitcode ("lcall","__bi_memcpyx2x_s");
11587 freeAsmop (count, NULL, ic, FALSE);
11589 symbol *lbl1 = newiTempLabel(NULL);
11591 emitcode (";"," Auto increment but no djnz");
11592 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11593 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11594 freeAsmop (count, NULL, ic, FALSE);
11595 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11596 emitcode ("","!tlabeldef",lbl->key+100);
11598 emitcode ("clr","a");
11599 emitcode ("movc", "a,@a+dptr");
11601 emitcode ("movx", "a,@dptr");
11602 emitcode ("movx", "@dptr,a");
11603 emitcode ("inc", "dptr");
11604 emitcode ("inc", "dptr");
11605 emitcode ("mov","a,b");
11606 emitcode ("orl","a,_ap");
11607 emitcode ("jz","!tlabel",lbl1->key+100);
11608 emitcode ("mov","a,_ap");
11609 emitcode ("add","a,#!constbyte",0xFF);
11610 emitcode ("mov","_ap,a");
11611 emitcode ("mov","a,b");
11612 emitcode ("addc","a,#!constbyte",0xFF);
11613 emitcode ("mov","b,a");
11614 emitcode ("sjmp","!tlabel",lbl->key+100);
11615 emitcode ("","!tlabeldef",lbl1->key+100);
11617 emitcode ("mov", "dps,#0");
11618 _G.dptrInUse = _G.dptr1InUse = 0;
11619 unsavermask(rsave);
11623 /*-----------------------------------------------------------------*/
11624 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
11625 /*-----------------------------------------------------------------*/
11626 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11628 operand *from , *to , *count;
11633 /* we know it has to be 3 parameters */
11634 assert (nparms == 3);
11636 rsave = newBitVect(16);
11637 /* save DPTR if it needs to be saved */
11638 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11639 if (bitVectBitValue(ic->rMask,i))
11640 rsave = bitVectSetBit(rsave,i);
11642 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11643 ds390_rUmaskForOp (IC_RESULT(ic))));
11650 aopOp (from, ic->next, FALSE, FALSE);
11652 /* get from into DPTR1 */
11653 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11654 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11655 if (options.model == MODEL_FLAT24) {
11656 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11659 freeAsmop (from, NULL, ic, FALSE);
11660 aopOp (to, ic, FALSE, FALSE);
11661 /* get "to" into DPTR */
11662 /* if the operand is already in dptr
11663 then we do nothing else we move the value to dptr */
11664 if (AOP_TYPE (to) != AOP_STR) {
11665 /* if already in DPTR then we need to push */
11666 if (AOP_TYPE(to) == AOP_DPTR) {
11667 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11668 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11669 if (options.model == MODEL_FLAT24)
11670 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11671 emitcode ("pop", "dph");
11672 emitcode ("pop", "dpl");
11674 _startLazyDPSEvaluation ();
11675 /* if this is remateriazable */
11676 if (AOP_TYPE (to) == AOP_IMMD) {
11677 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11678 } else { /* we need to get it byte by byte */
11679 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11680 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11681 if (options.model == MODEL_FLAT24) {
11682 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11685 _endLazyDPSEvaluation ();
11688 freeAsmop (to, NULL, ic, FALSE);
11689 _G.dptrInUse = _G.dptr1InUse = 1;
11690 aopOp (count, ic->next->next, FALSE,FALSE);
11691 lbl =newiTempLabel(NULL);
11692 lbl2 =newiTempLabel(NULL);
11694 /* now for the actual compare */
11695 if (AOP_TYPE(count) == AOP_LIT &&
11696 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11697 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11699 emitcode("lcall","__bi_memcmpc2x_s");
11701 emitcode("lcall","__bi_memcmpx2x_s");
11702 freeAsmop (count, NULL, ic, FALSE);
11703 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11704 aopPut(AOP(IC_RESULT(ic)),"a",0);
11705 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11707 symbol *lbl1 = newiTempLabel(NULL);
11709 emitcode("push","ar0");
11710 emitcode (";"," Auto increment but no djnz");
11711 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11712 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11713 freeAsmop (count, NULL, ic, FALSE);
11714 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11715 emitcode ("","!tlabeldef",lbl->key+100);
11717 emitcode ("clr","a");
11718 emitcode ("movc", "a,@a+dptr");
11720 emitcode ("movx", "a,@dptr");
11721 emitcode ("mov","r0,a");
11722 emitcode ("movx", "a,@dptr");
11723 emitcode ("clr","c");
11724 emitcode ("subb","a,r0");
11725 emitcode ("jnz","!tlabel",lbl2->key+100);
11726 emitcode ("inc", "dptr");
11727 emitcode ("inc", "dptr");
11728 emitcode ("mov","a,b");
11729 emitcode ("orl","a,_ap");
11730 emitcode ("jz","!tlabel",lbl1->key+100);
11731 emitcode ("mov","a,_ap");
11732 emitcode ("add","a,#!constbyte",0xFF);
11733 emitcode ("mov","_ap,a");
11734 emitcode ("mov","a,b");
11735 emitcode ("addc","a,#!constbyte",0xFF);
11736 emitcode ("mov","b,a");
11737 emitcode ("sjmp","!tlabel",lbl->key+100);
11738 emitcode ("","!tlabeldef",lbl1->key+100);
11739 emitcode ("clr","a");
11740 emitcode ("","!tlabeldef",lbl2->key+100);
11741 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11742 aopPut(AOP(IC_RESULT(ic)),"a",0);
11743 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11744 emitcode("pop","ar0");
11745 emitcode ("mov", "dps,#0");
11747 _G.dptrInUse = _G.dptr1InUse = 0;
11748 unsavermask(rsave);
11752 /*-----------------------------------------------------------------*/
11753 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11754 /* port, first parameter output area second parameter pointer to */
11755 /* port third parameter count */
11756 /*-----------------------------------------------------------------*/
11757 static void genInp( iCode *ic, int nparms, operand **parms)
11759 operand *from , *to , *count;
11764 /* we know it has to be 3 parameters */
11765 assert (nparms == 3);
11767 rsave = newBitVect(16);
11768 /* save DPTR if it needs to be saved */
11769 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11770 if (bitVectBitValue(ic->rMask,i))
11771 rsave = bitVectSetBit(rsave,i);
11773 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11774 ds390_rUmaskForOp (IC_RESULT(ic))));
11781 aopOp (from, ic->next, FALSE, FALSE);
11783 /* get from into DPTR1 */
11784 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11785 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11786 if (options.model == MODEL_FLAT24) {
11787 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11790 freeAsmop (from, NULL, ic, FALSE);
11791 aopOp (to, ic, FALSE, FALSE);
11792 /* get "to" into DPTR */
11793 /* if the operand is already in dptr
11794 then we do nothing else we move the value to dptr */
11795 if (AOP_TYPE (to) != AOP_STR) {
11796 /* if already in DPTR then we need to push */
11797 if (AOP_TYPE(to) == AOP_DPTR) {
11798 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11799 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11800 if (options.model == MODEL_FLAT24)
11801 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11802 emitcode ("pop", "dph");
11803 emitcode ("pop", "dpl");
11805 _startLazyDPSEvaluation ();
11806 /* if this is remateriazable */
11807 if (AOP_TYPE (to) == AOP_IMMD) {
11808 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11809 } else { /* we need to get it byte by byte */
11810 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11811 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11812 if (options.model == MODEL_FLAT24) {
11813 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11816 _endLazyDPSEvaluation ();
11819 freeAsmop (to, NULL, ic, FALSE);
11821 _G.dptrInUse = _G.dptr1InUse = 1;
11822 aopOp (count, ic->next->next, FALSE,FALSE);
11823 lbl =newiTempLabel(NULL);
11825 /* now for the actual copy */
11826 if (AOP_TYPE(count) == AOP_LIT &&
11827 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11828 emitcode (";","OH JOY auto increment with djnz (very fast)");
11829 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11830 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11831 freeAsmop (count, NULL, ic, FALSE);
11832 emitcode ("","!tlabeldef",lbl->key+100);
11833 emitcode ("movx", "a,@dptr"); /* read data from port */
11834 emitcode ("dec","dps"); /* switch to DPTR */
11835 emitcode ("movx", "@dptr,a"); /* save into location */
11836 emitcode ("inc", "dptr"); /* point to next area */
11837 emitcode ("inc","dps"); /* switch to DPTR2 */
11838 emitcode ("djnz","b,!tlabel",lbl->key+100);
11840 symbol *lbl1 = newiTempLabel(NULL);
11842 emitcode (";"," Auto increment but no djnz");
11843 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11844 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11845 freeAsmop (count, NULL, ic, FALSE);
11846 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11847 emitcode ("","!tlabeldef",lbl->key+100);
11848 emitcode ("movx", "a,@dptr");
11849 emitcode ("dec","dps"); /* switch to DPTR */
11850 emitcode ("movx", "@dptr,a");
11851 emitcode ("inc", "dptr");
11852 emitcode ("inc","dps"); /* switch to DPTR2 */
11853 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
11854 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11855 emitcode ("mov","a,b");
11856 emitcode ("orl","a,_ap");
11857 emitcode ("jz","!tlabel",lbl1->key+100);
11858 emitcode ("mov","a,_ap");
11859 emitcode ("add","a,#!constbyte",0xFF);
11860 emitcode ("mov","_ap,a");
11861 emitcode ("mov","a,b");
11862 emitcode ("addc","a,#!constbyte",0xFF);
11863 emitcode ("mov","b,a");
11864 emitcode ("sjmp","!tlabel",lbl->key+100);
11865 emitcode ("","!tlabeldef",lbl1->key+100);
11867 emitcode ("mov", "dps,#0");
11868 _G.dptrInUse = _G.dptr1InUse = 0;
11869 unsavermask(rsave);
11873 /*-----------------------------------------------------------------*/
11874 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11875 /* port, first parameter output area second parameter pointer to */
11876 /* port third parameter count */
11877 /*-----------------------------------------------------------------*/
11878 static void genOutp( iCode *ic, int nparms, operand **parms)
11880 operand *from , *to , *count;
11885 /* we know it has to be 3 parameters */
11886 assert (nparms == 3);
11888 rsave = newBitVect(16);
11889 /* save DPTR if it needs to be saved */
11890 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11891 if (bitVectBitValue(ic->rMask,i))
11892 rsave = bitVectSetBit(rsave,i);
11894 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11895 ds390_rUmaskForOp (IC_RESULT(ic))));
11902 aopOp (from, ic->next, FALSE, FALSE);
11904 /* get from into DPTR1 */
11905 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11906 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11907 if (options.model == MODEL_FLAT24) {
11908 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11911 freeAsmop (from, NULL, ic, FALSE);
11912 aopOp (to, ic, FALSE, FALSE);
11913 /* get "to" into DPTR */
11914 /* if the operand is already in dptr
11915 then we do nothing else we move the value to dptr */
11916 if (AOP_TYPE (to) != AOP_STR) {
11917 /* if already in DPTR then we need to push */
11918 if (AOP_TYPE(to) == AOP_DPTR) {
11919 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11920 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11921 if (options.model == MODEL_FLAT24)
11922 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11923 emitcode ("pop", "dph");
11924 emitcode ("pop", "dpl");
11926 _startLazyDPSEvaluation ();
11927 /* if this is remateriazable */
11928 if (AOP_TYPE (to) == AOP_IMMD) {
11929 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11930 } else { /* we need to get it byte by byte */
11931 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11932 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11933 if (options.model == MODEL_FLAT24) {
11934 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11937 _endLazyDPSEvaluation ();
11940 freeAsmop (to, NULL, ic, FALSE);
11942 _G.dptrInUse = _G.dptr1InUse = 1;
11943 aopOp (count, ic->next->next, FALSE,FALSE);
11944 lbl =newiTempLabel(NULL);
11946 /* now for the actual copy */
11947 if (AOP_TYPE(count) == AOP_LIT &&
11948 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11949 emitcode (";","OH JOY auto increment with djnz (very fast)");
11950 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11951 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11952 emitcode ("","!tlabeldef",lbl->key+100);
11953 emitcode ("movx", "a,@dptr"); /* read data from port */
11954 emitcode ("inc","dps"); /* switch to DPTR2 */
11955 emitcode ("movx", "@dptr,a"); /* save into location */
11956 emitcode ("inc", "dptr"); /* point to next area */
11957 emitcode ("dec","dps"); /* switch to DPTR */
11958 emitcode ("djnz","b,!tlabel",lbl->key+100);
11959 freeAsmop (count, NULL, ic, FALSE);
11961 symbol *lbl1 = newiTempLabel(NULL);
11963 emitcode (";"," Auto increment but no djnz");
11964 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11965 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11966 freeAsmop (count, NULL, ic, FALSE);
11967 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11968 emitcode ("","!tlabeldef",lbl->key+100);
11969 emitcode ("movx", "a,@dptr");
11970 emitcode ("inc", "dptr");
11971 emitcode ("inc","dps"); /* switch to DPTR2 */
11972 emitcode ("movx", "@dptr,a");
11973 emitcode ("dec","dps"); /* switch to DPTR */
11974 emitcode ("mov","a,b");
11975 emitcode ("orl","a,_ap");
11976 emitcode ("jz","!tlabel",lbl1->key+100);
11977 emitcode ("mov","a,_ap");
11978 emitcode ("add","a,#!constbyte",0xFF);
11979 emitcode ("mov","_ap,a");
11980 emitcode ("mov","a,b");
11981 emitcode ("addc","a,#!constbyte",0xFF);
11982 emitcode ("mov","b,a");
11983 emitcode ("sjmp","!tlabel",lbl->key+100);
11984 emitcode ("","!tlabeldef",lbl1->key+100);
11986 emitcode ("mov", "dps,#0");
11987 _G.dptrInUse = _G.dptr1InUse = 0;
11988 unsavermask(rsave);
11992 /*-----------------------------------------------------------------*/
11993 /* genSwapW - swap lower & high order bytes */
11994 /*-----------------------------------------------------------------*/
11995 static void genSwapW(iCode *ic, int nparms, operand **parms)
11999 assert (nparms==1);
12002 dest=IC_RESULT(ic);
12004 assert(getSize(operandType(src))==2);
12006 aopOp (src, ic, FALSE, FALSE);
12007 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
12009 MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
12011 freeAsmop (src, NULL, ic, FALSE);
12013 aopOp (dest,ic, FALSE, FALSE);
12014 aopPut(AOP(dest),"b",0);
12015 aopPut(AOP(dest),"a",1);
12016 freeAsmop (dest, NULL, ic, FALSE);
12019 /*-----------------------------------------------------------------*/
12020 /* genMemsetX - gencode for memSetX data */
12021 /*-----------------------------------------------------------------*/
12022 static void genMemsetX(iCode *ic, int nparms, operand **parms)
12024 operand *to , *val , *count;
12030 /* we know it has to be 3 parameters */
12031 assert (nparms == 3);
12037 /* save DPTR if it needs to be saved */
12038 rsave = newBitVect(16);
12039 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12040 if (bitVectBitValue(ic->rMask,i))
12041 rsave = bitVectSetBit(rsave,i);
12043 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12044 ds390_rUmaskForOp (IC_RESULT(ic))));
12047 aopOp (to, ic, FALSE, FALSE);
12048 /* get "to" into DPTR */
12049 /* if the operand is already in dptr
12050 then we do nothing else we move the value to dptr */
12051 if (AOP_TYPE (to) != AOP_STR) {
12052 /* if already in DPTR then we need to push */
12053 if (AOP_TYPE(to) == AOP_DPTR) {
12054 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12055 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12056 if (options.model == MODEL_FLAT24)
12057 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12058 emitcode ("pop", "dph");
12059 emitcode ("pop", "dpl");
12061 _startLazyDPSEvaluation ();
12062 /* if this is remateriazable */
12063 if (AOP_TYPE (to) == AOP_IMMD) {
12064 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12065 } else { /* we need to get it byte by byte */
12066 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12067 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12068 if (options.model == MODEL_FLAT24) {
12069 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12072 _endLazyDPSEvaluation ();
12075 freeAsmop (to, NULL, ic, FALSE);
12077 aopOp (val, ic->next->next, FALSE,FALSE);
12078 aopOp (count, ic->next->next, FALSE,FALSE);
12079 lbl =newiTempLabel(NULL);
12080 /* now for the actual copy */
12081 if (AOP_TYPE(count) == AOP_LIT &&
12082 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12083 l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
12084 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12086 emitcode ("","!tlabeldef",lbl->key+100);
12087 emitcode ("movx", "@dptr,a");
12088 emitcode ("inc", "dptr");
12089 emitcode ("djnz","b,!tlabel",lbl->key+100);
12091 symbol *lbl1 = newiTempLabel(NULL);
12093 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12094 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12095 emitcode ("","!tlabeldef",lbl->key+100);
12096 MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
12097 emitcode ("movx", "@dptr,a");
12098 emitcode ("inc", "dptr");
12099 emitcode ("mov","a,b");
12100 emitcode ("orl","a,_ap");
12101 emitcode ("jz","!tlabel",lbl1->key+100);
12102 emitcode ("mov","a,_ap");
12103 emitcode ("add","a,#!constbyte",0xFF);
12104 emitcode ("mov","_ap,a");
12105 emitcode ("mov","a,b");
12106 emitcode ("addc","a,#!constbyte",0xFF);
12107 emitcode ("mov","b,a");
12108 emitcode ("sjmp","!tlabel",lbl->key+100);
12109 emitcode ("","!tlabeldef",lbl1->key+100);
12111 freeAsmop (count, NULL, ic, FALSE);
12112 unsavermask(rsave);
12115 /*-----------------------------------------------------------------*/
12116 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12117 /*-----------------------------------------------------------------*/
12118 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12121 operand *pnum, *result;
12124 assert (nparms==1);
12125 /* save registers that need to be saved */
12126 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12127 ds390_rUmaskForOp (IC_RESULT(ic))));
12130 aopOp (pnum, ic, FALSE, FALSE);
12131 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12132 freeAsmop (pnum, NULL, ic, FALSE);
12133 emitcode ("lcall","NatLib_LoadPrimitive");
12134 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12135 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
12136 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12137 for (i = (size-1) ; i >= 0 ; i-- ) {
12138 emitcode ("push","a%s",javaRet[i]);
12140 for (i=0; i < size ; i++ ) {
12141 emitcode ("pop","a%s",
12142 aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12145 for (i = 0 ; i < size ; i++ ) {
12146 aopPut(AOP(result),javaRet[i],i);
12149 freeAsmop (result, NULL, ic, FALSE);
12150 unsavermask(rsave);
12153 /*-----------------------------------------------------------------*/
12154 /* genNatLibLoadPointer - calls TINI api function to load pointer */
12155 /*-----------------------------------------------------------------*/
12156 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12159 operand *pnum, *result;
12163 assert (nparms==1);
12164 /* save registers that need to be saved */
12165 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12166 ds390_rUmaskForOp (IC_RESULT(ic))));
12169 aopOp (pnum, ic, FALSE, FALSE);
12170 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12171 freeAsmop (pnum, NULL, ic, FALSE);
12172 emitcode ("lcall","NatLib_LoadPointer");
12173 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12174 if (AOP_TYPE(result)!=AOP_STR) {
12175 for (i = 0 ; i < size ; i++ ) {
12176 aopPut(AOP(result),fReturn[i],i);
12179 freeAsmop (result, NULL, ic, FALSE);
12180 unsavermask(rsave);
12183 /*-----------------------------------------------------------------*/
12184 /* genNatLibInstallStateBlock - */
12185 /*-----------------------------------------------------------------*/
12186 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
12187 operand **parms, const char *name)
12190 operand *psb, *handle;
12191 assert (nparms==2);
12193 /* save registers that need to be saved */
12194 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12195 ds390_rUmaskForOp (IC_RESULT(ic))));
12199 /* put pointer to state block into DPTR1 */
12200 aopOp (psb, ic, FALSE, FALSE);
12201 if (AOP_TYPE (psb) == AOP_IMMD) {
12202 emitcode ("mov","dps,#1");
12203 emitcode ("mov", "dptr,%s",
12204 aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12205 emitcode ("mov","dps,#0");
12207 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12208 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12209 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12211 freeAsmop (psb, NULL, ic, FALSE);
12213 /* put libraryID into DPTR */
12214 emitcode ("mov","dptr,#LibraryID");
12216 /* put handle into r3:r2 */
12217 aopOp (handle, ic, FALSE, FALSE);
12218 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12219 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12220 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12221 emitcode ("pop","ar3");
12222 emitcode ("pop","ar2");
12224 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12225 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12227 freeAsmop (psb, NULL, ic, FALSE);
12229 /* make the call */
12230 emitcode ("lcall","NatLib_Install%sStateBlock",name);
12232 /* put return value into place*/
12234 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12236 aopPut(AOP(IC_RESULT(ic)),"a",0);
12237 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12238 unsavermask(rsave);
12241 /*-----------------------------------------------------------------*/
12242 /* genNatLibRemoveStateBlock - */
12243 /*-----------------------------------------------------------------*/
12244 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12250 /* save registers that need to be saved */
12251 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12252 ds390_rUmaskForOp (IC_RESULT(ic))));
12254 /* put libraryID into DPTR */
12255 emitcode ("mov","dptr,#LibraryID");
12256 /* make the call */
12257 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12258 unsavermask(rsave);
12261 /*-----------------------------------------------------------------*/
12262 /* genNatLibGetStateBlock - */
12263 /*-----------------------------------------------------------------*/
12264 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12265 operand **parms,const char *name)
12268 symbol *lbl = newiTempLabel(NULL);
12271 /* save registers that need to be saved */
12272 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12273 ds390_rUmaskForOp (IC_RESULT(ic))));
12275 /* put libraryID into DPTR */
12276 emitcode ("mov","dptr,#LibraryID");
12277 /* make the call */
12278 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12279 emitcode ("jnz","!tlabel",lbl->key+100);
12281 /* put return value into place */
12282 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12283 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12284 emitcode ("push","ar3");
12285 emitcode ("push","ar2");
12286 emitcode ("pop","%s",
12287 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12288 emitcode ("pop","%s",
12289 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12291 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12292 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12294 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12295 emitcode ("","!tlabeldef",lbl->key+100);
12296 unsavermask(rsave);
12299 /*-----------------------------------------------------------------*/
12300 /* genMMMalloc - */
12301 /*-----------------------------------------------------------------*/
12302 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12303 int size, const char *name)
12308 symbol *lbl = newiTempLabel(NULL);
12310 assert (nparms == 1);
12311 /* save registers that need to be saved */
12312 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12313 ds390_rUmaskForOp (IC_RESULT(ic))));
12316 aopOp (bsize,ic,FALSE,FALSE);
12318 /* put the size in R4-R2 */
12319 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12320 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12321 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12323 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12324 emitcode("pop","ar4");
12326 emitcode("pop","ar3");
12327 emitcode("pop","ar2");
12329 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12330 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12332 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12335 freeAsmop (bsize, NULL, ic, FALSE);
12337 /* make the call */
12338 emitcode ("lcall","MM_%s",name);
12339 emitcode ("jz","!tlabel",lbl->key+100);
12340 emitcode ("mov","r2,#!constbyte",0xff);
12341 emitcode ("mov","r3,#!constbyte",0xff);
12342 emitcode ("","!tlabeldef",lbl->key+100);
12343 /* we don't care about the pointer : we just save the handle */
12344 rsym = OP_SYMBOL(IC_RESULT(ic));
12345 if (rsym->liveFrom != rsym->liveTo) {
12346 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12347 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12348 emitcode ("push","ar3");
12349 emitcode ("push","ar2");
12350 emitcode ("pop","%s",
12351 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12352 emitcode ("pop","%s",
12353 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12355 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12356 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12358 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12360 unsavermask(rsave);
12363 /*-----------------------------------------------------------------*/
12365 /*-----------------------------------------------------------------*/
12366 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12371 assert (nparms == 1);
12372 /* save registers that need to be saved */
12373 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12374 ds390_rUmaskForOp (IC_RESULT(ic))));
12377 aopOp (handle,ic,FALSE,FALSE);
12379 /* put the size in R4-R2 */
12380 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12381 emitcode("push","%s",
12382 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12383 emitcode("push","%s",
12384 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12385 emitcode("pop","ar3");
12386 emitcode("pop","ar2");
12388 emitcode ("mov","r2,%s",
12389 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12390 emitcode ("mov","r3,%s",
12391 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12393 freeAsmop (handle, NULL, ic, FALSE);
12395 /* make the call */
12396 emitcode ("lcall","MM_Deref");
12399 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12400 if (rsym->liveFrom != rsym->liveTo) {
12401 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12402 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12403 _startLazyDPSEvaluation ();
12405 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12406 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12407 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12409 _endLazyDPSEvaluation ();
12414 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12415 unsavermask(rsave);
12418 /*-----------------------------------------------------------------*/
12419 /* genMMUnrestrictedPersist - */
12420 /*-----------------------------------------------------------------*/
12421 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12426 assert (nparms == 1);
12427 /* save registers that need to be saved */
12428 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12429 ds390_rUmaskForOp (IC_RESULT(ic))));
12432 aopOp (handle,ic,FALSE,FALSE);
12434 /* put the size in R3-R2 */
12435 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12436 emitcode("push","%s",
12437 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12438 emitcode("push","%s",
12439 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12440 emitcode("pop","ar3");
12441 emitcode("pop","ar2");
12443 emitcode ("mov","r2,%s",
12444 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12445 emitcode ("mov","r3,%s",
12446 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12448 freeAsmop (handle, NULL, ic, FALSE);
12450 /* make the call */
12451 emitcode ("lcall","MM_UnrestrictedPersist");
12454 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12455 if (rsym->liveFrom != rsym->liveTo) {
12456 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12457 aopPut(AOP(IC_RESULT(ic)),"a",0);
12458 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12461 unsavermask(rsave);
12464 /*-----------------------------------------------------------------*/
12465 /* genSystemExecJavaProcess - */
12466 /*-----------------------------------------------------------------*/
12467 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12470 operand *handle, *pp;
12472 assert (nparms==2);
12473 /* save registers that need to be saved */
12474 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12475 ds390_rUmaskForOp (IC_RESULT(ic))));
12480 /* put the handle in R3-R2 */
12481 aopOp (handle,ic,FALSE,FALSE);
12482 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12483 emitcode("push","%s",
12484 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12485 emitcode("push","%s",
12486 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12487 emitcode("pop","ar3");
12488 emitcode("pop","ar2");
12490 emitcode ("mov","r2,%s",
12491 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12492 emitcode ("mov","r3,%s",
12493 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12495 freeAsmop (handle, NULL, ic, FALSE);
12497 /* put pointer in DPTR */
12498 aopOp (pp,ic,FALSE,FALSE);
12499 if (AOP_TYPE(pp) == AOP_IMMD) {
12500 emitcode ("mov", "dptr,%s",
12501 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12502 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12503 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12504 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12505 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12507 freeAsmop (handle, NULL, ic, FALSE);
12509 /* make the call */
12510 emitcode ("lcall","System_ExecJavaProcess");
12512 /* put result in place */
12514 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12515 if (rsym->liveFrom != rsym->liveTo) {
12516 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12517 aopPut(AOP(IC_RESULT(ic)),"a",0);
12518 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12522 unsavermask(rsave);
12525 /*-----------------------------------------------------------------*/
12526 /* genSystemRTCRegisters - */
12527 /*-----------------------------------------------------------------*/
12528 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12534 assert (nparms==1);
12535 /* save registers that need to be saved */
12536 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12537 ds390_rUmaskForOp (IC_RESULT(ic))));
12540 /* put pointer in DPTR */
12541 aopOp (pp,ic,FALSE,FALSE);
12542 if (AOP_TYPE (pp) == AOP_IMMD) {
12543 emitcode ("mov","dps,#1");
12544 emitcode ("mov", "dptr,%s",
12545 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12546 emitcode ("mov","dps,#0");
12548 emitcode ("mov","dpl1,%s",
12549 aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12550 emitcode ("mov","dph1,%s",
12551 aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12552 emitcode ("mov","dpx1,%s",
12553 aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12555 freeAsmop (pp, NULL, ic, FALSE);
12557 /* make the call */
12558 emitcode ("lcall","System_%sRTCRegisters",name);
12560 unsavermask(rsave);
12563 /*-----------------------------------------------------------------*/
12564 /* genSystemThreadSleep - */
12565 /*-----------------------------------------------------------------*/
12566 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12571 assert (nparms==1);
12572 /* save registers that need to be saved */
12573 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12574 ds390_rUmaskForOp (IC_RESULT(ic))));
12577 aopOp(to,ic,FALSE,FALSE);
12578 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12579 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12580 emitcode ("push","%s",
12581 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12582 emitcode ("push","%s",
12583 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12584 emitcode ("push","%s",
12585 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12586 emitcode ("push","%s",
12587 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12588 emitcode ("pop","ar3");
12589 emitcode ("pop","ar2");
12590 emitcode ("pop","ar1");
12591 emitcode ("pop","ar0");
12593 emitcode ("mov","r0,%s",
12594 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12595 emitcode ("mov","r1,%s",
12596 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12597 emitcode ("mov","r2,%s",
12598 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12599 emitcode ("mov","r3,%s",
12600 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12602 freeAsmop (to, NULL, ic, FALSE);
12604 /* suspend in acc */
12606 aopOp(s,ic,FALSE,FALSE);
12607 emitcode ("mov","a,%s",
12608 aopGet(AOP(s),0,FALSE,TRUE,NULL));
12609 freeAsmop (s, NULL, ic, FALSE);
12611 /* make the call */
12612 emitcode ("lcall","System_%s",name);
12614 unsavermask(rsave);
12617 /*-----------------------------------------------------------------*/
12618 /* genSystemThreadResume - */
12619 /*-----------------------------------------------------------------*/
12620 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12625 assert (nparms==2);
12626 /* save registers that need to be saved */
12627 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12628 ds390_rUmaskForOp (IC_RESULT(ic))));
12634 aopOp(pid,ic,FALSE,FALSE);
12635 emitcode ("mov","r0,%s",
12636 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12637 freeAsmop (pid, NULL, ic, FALSE);
12640 aopOp(tid,ic,FALSE,FALSE);
12641 emitcode ("mov","a,%s",
12642 aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12643 freeAsmop (tid, NULL, ic, FALSE);
12645 emitcode ("lcall","System_ThreadResume");
12647 /* put result into place */
12649 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12650 if (rsym->liveFrom != rsym->liveTo) {
12651 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12652 aopPut(AOP(IC_RESULT(ic)),"a",0);
12653 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12656 unsavermask(rsave);
12659 /*-----------------------------------------------------------------*/
12660 /* genSystemProcessResume - */
12661 /*-----------------------------------------------------------------*/
12662 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12667 assert (nparms==1);
12668 /* save registers that need to be saved */
12669 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12670 ds390_rUmaskForOp (IC_RESULT(ic))));
12675 aopOp(pid,ic,FALSE,FALSE);
12676 emitcode ("mov","a,%s",
12677 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12678 freeAsmop (pid, NULL, ic, FALSE);
12680 emitcode ("lcall","System_ProcessResume");
12682 unsavermask(rsave);
12685 /*-----------------------------------------------------------------*/
12687 /*-----------------------------------------------------------------*/
12688 static void genSystem (iCode *ic,int nparms,char *name)
12690 assert(nparms == 0);
12692 emitcode ("lcall","System_%s",name);
12695 /*-----------------------------------------------------------------*/
12696 /* genSystemPoll - */
12697 /*-----------------------------------------------------------------*/
12698 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12703 assert (nparms==1);
12704 /* save registers that need to be saved */
12705 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12706 ds390_rUmaskForOp (IC_RESULT(ic))));
12709 aopOp (fp,ic,FALSE,FALSE);
12710 if (AOP_TYPE (fp) == AOP_IMMD) {
12711 emitcode ("mov", "dptr,%s",
12712 aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12713 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12714 emitcode ("mov","dpl,%s",
12715 aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12716 emitcode ("mov","dph,%s",
12717 aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12718 emitcode ("mov","dpx,%s",
12719 aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12721 freeAsmop (fp, NULL, ic, FALSE);
12723 emitcode ("lcall","System_%sPoll",name);
12725 /* put result into place */
12727 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12728 if (rsym->liveFrom != rsym->liveTo) {
12729 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12730 aopPut(AOP(IC_RESULT(ic)),"a",0);
12731 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12734 unsavermask(rsave);
12737 /*-----------------------------------------------------------------*/
12738 /* genSystemGetCurrentID - */
12739 /*-----------------------------------------------------------------*/
12740 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12742 assert (nparms==0);
12744 emitcode ("lcall","System_GetCurrent%sId",name);
12745 /* put result into place */
12747 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12748 if (rsym->liveFrom != rsym->liveTo) {
12749 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12750 aopPut(AOP(IC_RESULT(ic)),"a",0);
12751 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12756 /*-----------------------------------------------------------------*/
12757 /* genDummyRead - generate code for dummy read of volatiles */
12758 /*-----------------------------------------------------------------*/
12760 genDummyRead (iCode * ic)
12765 D(emitcode("; genDummyRead",""));
12767 op = IC_RIGHT (ic);
12768 if (op && IS_SYMOP (op))
12770 aopOp (op, ic, FALSE, FALSE);
12772 /* if the result is a bit */
12773 if (AOP_TYPE (op) == AOP_CRY)
12774 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
12777 /* bit variables done */
12779 size = AOP_SIZE (op);
12783 MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
12788 freeAsmop (op, NULL, ic, TRUE);
12792 if (op && IS_SYMOP (op))
12794 aopOp (op, ic, FALSE, FALSE);
12796 /* if the result is a bit */
12797 if (AOP_TYPE (op) == AOP_CRY)
12798 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
12801 /* bit variables done */
12803 size = AOP_SIZE (op);
12807 MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
12812 freeAsmop (op, NULL, ic, TRUE);
12817 /*-----------------------------------------------------------------*/
12818 /* genCritical - generate code for start of a critical sequence */
12819 /*-----------------------------------------------------------------*/
12821 genCritical (iCode *ic)
12823 symbol *tlbl = newiTempLabel (NULL);
12825 D(emitcode("; genCritical",""));
12827 if (IC_RESULT (ic))
12828 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
12830 emitcode ("setb", "c");
12831 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
12832 emitcode ("clr", "c");
12833 emitcode ("", "%05d$:", (tlbl->key + 100));
12835 if (IC_RESULT (ic))
12836 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
12838 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
12840 if (IC_RESULT (ic))
12841 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
12844 /*-----------------------------------------------------------------*/
12845 /* genEndCritical - generate code for end of a critical sequence */
12846 /*-----------------------------------------------------------------*/
12848 genEndCritical (iCode *ic)
12850 D(emitcode("; genEndCritical",""));
12854 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
12855 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
12857 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
12858 emitcode ("mov", "ea,c");
12862 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE));
12863 emitcode ("rrc", "a");
12864 emitcode ("mov", "ea,c");
12866 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
12870 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
12871 emitcode ("mov", "ea,c");
12877 /*-----------------------------------------------------------------*/
12878 /* genBuiltIn - calls the appropriate function to generating code */
12879 /* for a built in function */
12880 /*-----------------------------------------------------------------*/
12881 static void genBuiltIn (iCode *ic)
12883 operand *bi_parms[MAX_BUILTIN_ARGS];
12888 /* get all the arguments for a built in function */
12889 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12891 /* which function is it */
12892 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12893 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12894 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12895 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12896 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12897 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12898 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12899 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12900 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12901 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12902 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12903 } else if (strcmp(bif->name,"__builtin_inp")==0) {
12904 genInp(bi_iCode,nbi_parms,bi_parms);
12905 } else if (strcmp(bif->name,"__builtin_outp")==0) {
12906 genOutp(bi_iCode,nbi_parms,bi_parms);
12907 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12908 genSwapW(bi_iCode,nbi_parms,bi_parms);
12909 /* JavaNative builtIns */
12910 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12911 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12912 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12913 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12914 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12915 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12916 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12917 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12918 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12919 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12920 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12921 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12922 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12923 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12924 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12925 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12926 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12927 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12928 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12929 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12930 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12931 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12932 } else if (strcmp(bif->name,"MM_Malloc")==0) {
12933 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12934 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12935 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12936 } else if (strcmp(bif->name,"MM_Free")==0) {
12937 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12938 } else if (strcmp(bif->name,"MM_Deref")==0) {
12939 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12940 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12941 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12942 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12943 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12944 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12945 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12946 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12947 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12948 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12949 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12950 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12951 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12952 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12953 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12954 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12955 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12956 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12957 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12958 } else if (strcmp(bif->name,"System_SaveThread")==0) {
12959 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12960 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12961 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12962 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12963 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12964 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12965 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12966 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12967 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12968 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12969 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12970 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12971 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12972 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12973 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12974 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12975 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12976 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12977 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12978 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12979 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12981 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12987 /*-----------------------------------------------------------------*/
12988 /* gen390Code - generate code for Dallas 390 based controllers */
12989 /*-----------------------------------------------------------------*/
12991 gen390Code (iCode * lic)
12996 lineHead = lineCurr = NULL;
12997 dptrn[1][0] = "dpl1";
12998 dptrn[1][1] = "dph1";
12999 dptrn[1][2] = "dpx1";
13001 if (options.model == MODEL_FLAT24) {
13002 fReturnSizeDS390 = 5;
13003 fReturn = fReturn24;
13005 fReturnSizeDS390 = 4;
13006 fReturn = fReturn16;
13007 options.stack10bit=0;
13010 /* print the allocation information */
13011 if (allocInfo && currFunc)
13012 printAllocInfo (currFunc, codeOutFile);
13014 /* if debug information required */
13015 if (options.debug && currFunc)
13017 debugFile->writeFunction(currFunc);
13019 if (IS_STATIC (currFunc->etype))
13020 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
13022 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
13025 /* stack pointer name */
13026 if (options.useXstack)
13032 for (ic = lic; ic; ic = ic->next)
13035 if (ic->lineno && cln != ic->lineno)
13040 emitcode ("", "C$%s$%d$%d$%d ==.",
13041 FileBaseName (ic->filename), ic->lineno,
13042 ic->level, ic->block);
13045 if (!options.noCcodeInAsm) {
13046 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
13047 printCLine(ic->filename, ic->lineno));
13051 if (options.iCodeInAsm) {
13052 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
13054 /* if the result is marked as
13055 spilt and rematerializable or code for
13056 this has already been generated then
13058 if (resultRemat (ic) || ic->generated)
13061 /* depending on the operation */
13081 /* IPOP happens only when trying to restore a
13082 spilt live range, if there is an ifx statement
13083 following this pop then the if statement might
13084 be using some of the registers being popped which
13085 would destory the contents of the register so
13086 we need to check for this condition and handle it */
13088 ic->next->op == IFX &&
13089 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
13090 genIfx (ic->next, ic);
13108 genEndFunction (ic);
13128 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
13145 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
13149 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
13156 /* note these two are xlated by algebraic equivalence
13157 during parsing SDCC.y */
13158 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13159 "got '>=' or '<=' shouldn't have come here");
13163 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
13175 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
13179 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
13183 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
13207 genRightShift (ic);
13210 case GET_VALUE_AT_ADDRESS:
13211 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13215 if (POINTER_SET (ic))
13216 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13242 if (ic->builtinSEND) genBuiltIn(ic);
13243 else addSet (&_G.sendSet, ic);
13246 case DUMMY_READ_VOLATILE:
13255 genEndCritical (ic);
13262 #if 0 // obsolete, and buggy for != xdata
13274 /* now we are ready to call the
13275 peep hole optimizer */
13276 if (!options.nopeep)
13277 peepHole (&lineHead);
13279 /* now do the actual printing */
13280 printLine (lineHead, codeOutFile);