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]);
2680 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2681 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2685 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2687 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2692 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2695 assignResultValue (IC_RESULT (ic));
2697 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2701 /* adjust the stack for parameters if
2703 if (ic->parmBytes) {
2705 if (options.stack10bit) {
2706 if (ic->parmBytes <= 10) {
2707 emitcode(";","stack adjustment for parms");
2708 for (i=0; i < ic->parmBytes ; i++) {
2709 emitcode("pop","acc");
2713 emitcode ("clr","c");
2714 emitcode ("mov","a,sp");
2715 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2716 emitcode ("mov","sp,a");
2717 emitcode ("mov","a,esp");
2719 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2720 emitcode ("mov","esp,a");
2724 if (ic->parmBytes > 3) {
2725 emitcode ("mov", "a,%s", spname);
2726 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2727 emitcode ("mov", "%s,a", spname);
2729 for (i = 0; i < ic->parmBytes; i++)
2730 emitcode ("dec", "%s", spname);
2734 /* if we hade saved some registers then unsave them */
2736 unsaveRegisters (ic);
2738 /* if register bank was saved then pop them */
2740 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2743 /*-----------------------------------------------------------------*/
2744 /* genPcall - generates a call by pointer statement */
2745 /*-----------------------------------------------------------------*/
2747 genPcall (iCode * ic)
2750 symbol *rlbl = newiTempLabel (NULL);
2751 bool restoreBank=FALSE;
2753 D (emitcode (";", "genPcall ");
2757 /* if caller saves & we have not saved then */
2761 /* if we are calling a function that is not using
2762 the same register bank then we need to save the
2763 destination registers on the stack */
2764 dtype = operandType (IC_LEFT (ic));
2765 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2766 IFFUNC_ISISR (currFunc->type) &&
2767 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2768 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2772 /* push the return address on to the stack */
2773 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2774 emitcode ("push", "acc");
2775 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2776 emitcode ("push", "acc");
2778 if (options.model == MODEL_FLAT24)
2780 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2781 emitcode ("push", "acc");
2784 /* now push the calling address */
2785 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2787 pushSide (IC_LEFT (ic), FPTRSIZE);
2789 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2791 /* if send set is not empty the assign */
2794 genSend(reverseSet(_G.sendSet));
2798 emitcode ("ret", "");
2799 emitcode ("", "!tlabeldef", (rlbl->key + 100));
2802 /* if we need assign a result value */
2803 if ((IS_ITEMP (IC_RESULT (ic)) &&
2804 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2805 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2806 IS_TRUE_SYMOP (IC_RESULT (ic)))
2810 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2813 assignResultValue (IC_RESULT (ic));
2815 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2818 /* adjust the stack for parameters if
2823 if (options.stack10bit) {
2824 if (ic->parmBytes <= 10) {
2825 emitcode(";","stack adjustment for parms");
2826 for (i=0; i < ic->parmBytes ; i++) {
2827 emitcode("pop","acc");
2831 emitcode ("clr","c");
2832 emitcode ("mov","a,sp");
2833 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2834 emitcode ("mov","sp,a");
2835 emitcode ("mov","a,esp");
2837 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2838 emitcode ("mov","esp,a");
2842 if (ic->parmBytes > 3) {
2843 emitcode ("mov", "a,%s", spname);
2844 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2845 emitcode ("mov", "%s,a", spname);
2848 for (i = 0; i < ic->parmBytes; i++)
2849 emitcode ("dec", "%s", spname);
2853 /* if register bank was saved then unsave them */
2855 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2857 /* if we hade saved some registers then
2860 unsaveRegisters (ic);
2864 /*-----------------------------------------------------------------*/
2865 /* resultRemat - result is rematerializable */
2866 /*-----------------------------------------------------------------*/
2868 resultRemat (iCode * ic)
2870 if (SKIP_IC (ic) || ic->op == IFX)
2873 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2875 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2876 if (sym->remat && !POINTER_SET (ic))
2883 #if defined(__BORLANDC__) || defined(_MSC_VER)
2884 #define STRCASECMP stricmp
2886 #define STRCASECMP strcasecmp
2889 /*-----------------------------------------------------------------*/
2890 /* inExcludeList - return 1 if the string is in exclude Reg list */
2891 /*-----------------------------------------------------------------*/
2893 regsCmp(void *p1, void *p2)
2895 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2899 inExcludeList (char *s)
2901 const char *p = setFirstItem(options.excludeRegsSet);
2903 if (p == NULL || STRCASECMP(p, "none") == 0)
2907 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2910 /*-----------------------------------------------------------------*/
2911 /* genFunction - generated code for function entry */
2912 /*-----------------------------------------------------------------*/
2914 genFunction (iCode * ic)
2918 bool switchedPSW = FALSE;
2920 D (emitcode (";", "genFunction "););
2923 /* create the function header */
2924 emitcode (";", "-----------------------------------------");
2925 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2926 emitcode (";", "-----------------------------------------");
2928 emitcode ("", "%s:", sym->rname);
2929 ftype = operandType (IC_LEFT (ic));
2931 if (IFFUNC_ISNAKED(ftype))
2933 emitcode(";", "naked function: no prologue.");
2937 if (options.stack_probe)
2938 emitcode ("lcall","__stack_probe");
2940 /* here we need to generate the equates for the
2941 register bank if required */
2942 if (FUNC_REGBANK (ftype) != rbank)
2946 rbank = FUNC_REGBANK (ftype);
2947 for (i = 0; i < ds390_nRegs; i++)
2949 if (regs390[i].print) {
2950 if (strcmp (regs390[i].base, "0") == 0)
2951 emitcode ("", "%s !equ !constbyte",
2953 8 * rbank + regs390[i].offset);
2955 emitcode ("", "%s !equ %s + !constbyte",
2958 8 * rbank + regs390[i].offset);
2963 /* if this is an interrupt service routine then
2964 save acc, b, dpl, dph */
2965 if (IFFUNC_ISISR (sym->type))
2967 if (!inExcludeList ("acc"))
2968 emitcode ("push", "acc");
2969 if (!inExcludeList ("b"))
2970 emitcode ("push", "b");
2971 if (!inExcludeList ("dpl"))
2972 emitcode ("push", "dpl");
2973 if (!inExcludeList ("dph"))
2974 emitcode ("push", "dph");
2975 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2977 emitcode ("push", "dpx");
2978 /* Make sure we're using standard DPTR */
2979 emitcode ("push", "dps");
2980 emitcode ("mov", "dps,#0");
2981 if (options.stack10bit)
2983 /* This ISR could conceivably use DPTR2. Better save it. */
2984 emitcode ("push", "dpl1");
2985 emitcode ("push", "dph1");
2986 emitcode ("push", "dpx1");
2987 emitcode ("push", DP2_RESULT_REG);
2990 /* if this isr has no bank i.e. is going to
2991 run with bank 0 , then we need to save more
2993 if (!FUNC_REGBANK (sym->type))
2997 /* if this function does not call any other
2998 function then we can be economical and
2999 save only those registers that are used */
3000 if (!IFFUNC_HASFCALL(sym->type))
3003 /* if any registers used */
3006 /* save the registers used */
3007 for (i = 0; i < sym->regsUsed->size; i++)
3009 if (bitVectBitValue (sym->regsUsed, i) ||
3010 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3011 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3018 /* this function has a function call cannot
3019 determines register usage so we will have to push the
3021 saveRBank (0, ic, FALSE);
3022 if (options.parms_in_bank1) {
3023 for (i=0; i < 8 ; i++ ) {
3024 emitcode ("push","%s",rb1regs[i]);
3031 /* This ISR uses a non-zero bank.
3033 * We assume that the bank is available for our
3036 * However, if this ISR calls a function which uses some
3037 * other bank, we must save that bank entirely.
3039 unsigned long banksToSave = 0;
3041 if (IFFUNC_HASFCALL(sym->type))
3044 #define MAX_REGISTER_BANKS 4
3049 for (i = ic; i; i = i->next)
3051 if (i->op == ENDFUNCTION)
3053 /* we got to the end OK. */
3061 dtype = operandType (IC_LEFT(i));
3063 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3065 /* Mark this bank for saving. */
3066 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3068 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3072 banksToSave |= (1 << FUNC_REGBANK(dtype));
3075 /* And note that we don't need to do it in
3083 /* This is a mess; we have no idea what
3084 * register bank the called function might
3087 * The only thing I can think of to do is
3088 * throw a warning and hope.
3090 werror(W_FUNCPTR_IN_USING_ISR);
3094 if (banksToSave && options.useXstack)
3096 /* Since we aren't passing it an ic,
3097 * saveRBank will assume r0 is available to abuse.
3099 * So switch to our (trashable) bank now, so
3100 * the caller's R0 isn't trashed.
3102 emitcode ("push", "psw");
3103 emitcode ("mov", "psw,#!constbyte",
3104 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3108 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3110 if (banksToSave & (1 << ix))
3112 saveRBank(ix, NULL, FALSE);
3116 // TODO: this needs a closer look
3117 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3122 /* if callee-save to be used for this function
3123 then save the registers being used in this function */
3124 if (IFFUNC_CALLEESAVES(sym->type))
3128 /* if any registers used */
3131 /* save the registers used */
3132 for (i = 0; i < sym->regsUsed->size; i++)
3134 if (bitVectBitValue (sym->regsUsed, i) ||
3135 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3137 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3145 /* set the register bank to the desired value */
3146 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3149 emitcode ("push", "psw");
3150 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3153 if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3154 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3155 if (options.stack10bit) {
3156 emitcode ("push","_bpx");
3157 emitcode ("push","_bpx+1");
3158 emitcode ("mov","_bpx,%s",spname);
3159 emitcode ("mov","_bpx+1,esp");
3160 adjustEsp("_bpx+1");
3162 if (options.useXstack) {
3163 emitcode ("mov", "r0,%s", spname);
3164 emitcode ("mov", "a,_bp");
3165 emitcode ("movx", "@r0,a");
3166 emitcode ("inc", "%s", spname);
3168 /* set up the stack */
3169 emitcode ("push", "_bp"); /* save the callers stack */
3171 emitcode ("mov", "_bp,%s", spname);
3175 /* adjust the stack for the function */
3178 if (options.stack10bit) {
3179 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3180 assert (sym->recvSize <= 4);
3181 if (sym->stack <= 8) {
3182 while (i--) emitcode ("push","acc");
3185 emitcode ("mov","a,sp");
3186 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3187 emitcode ("mov","sp,a");
3188 emitcode ("mov","a,esp");
3190 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3191 emitcode ("mov","esp,a");
3196 werror (W_STACK_OVERFLOW, sym->name);
3198 if (i > 3 && sym->recvSize < 4) {
3200 emitcode ("mov", "a,sp");
3201 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3202 emitcode ("mov", "sp,a");
3206 emitcode ("inc", "sp");
3213 emitcode ("mov", "a,_spx");
3214 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3215 emitcode ("mov", "_spx,a");
3218 /* if critical function then turn interrupts off */
3219 if (IFFUNC_ISCRITICAL (ftype))
3221 symbol *tlbl = newiTempLabel (NULL);
3222 emitcode ("setb", "c");
3223 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3224 emitcode ("clr", "c");
3225 emitcode ("", "%05d$:", (tlbl->key + 100));
3226 emitcode ("push", "psw"); /* save old ea via c in psw */
3231 /*-----------------------------------------------------------------*/
3232 /* genEndFunction - generates epilogue for functions */
3233 /*-----------------------------------------------------------------*/
3235 genEndFunction (iCode * ic)
3237 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3239 D (emitcode (";", "genEndFunction "););
3241 if (IFFUNC_ISNAKED(sym->type))
3243 emitcode(";", "naked function: no epilogue.");
3247 if (IFFUNC_ISCRITICAL (sym->type))
3249 emitcode ("pop", "psw"); /* restore ea via c in psw */
3250 emitcode ("mov", "ea,c");
3253 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3254 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3256 if (options.stack10bit) {
3258 emitcode ("mov", "sp,_bpx", spname);
3259 emitcode ("mov", "esp,_bpx+1", spname);
3262 emitcode ("mov", "%s,_bp", spname);
3266 /* if use external stack but some variables were
3267 added to the local stack then decrement the
3269 if (options.useXstack && sym->stack) {
3270 emitcode ("mov", "a,sp");
3271 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3272 emitcode ("mov", "sp,a");
3276 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3277 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3279 if (options.useXstack) {
3280 emitcode ("mov", "r0,%s", spname);
3281 emitcode ("movx", "a,@r0");
3282 emitcode ("mov", "_bp,a");
3283 emitcode ("dec", "%s", spname);
3285 if (options.stack10bit) {
3286 emitcode ("pop", "_bpx+1");
3287 emitcode ("pop", "_bpx");
3289 emitcode ("pop", "_bp");
3294 /* restore the register bank */
3295 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3297 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3298 || !options.useXstack)
3300 /* Special case of ISR using non-zero bank with useXstack
3303 emitcode ("pop", "psw");
3307 if (IFFUNC_ISISR (sym->type))
3310 /* now we need to restore the registers */
3311 /* if this isr has no bank i.e. is going to
3312 run with bank 0 , then we need to save more
3314 if (!FUNC_REGBANK (sym->type))
3317 /* if this function does not call any other
3318 function then we can be economical and
3319 save only those registers that are used */
3320 if (!IFFUNC_HASFCALL(sym->type))
3323 /* if any registers used */
3326 /* save the registers used */
3327 for (i = sym->regsUsed->size; i >= 0; i--)
3329 if (bitVectBitValue (sym->regsUsed, i) ||
3330 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3331 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3338 /* this function has a function call cannot
3339 determines register usage so we will have to pop the
3341 if (options.parms_in_bank1) {
3342 for (i = 7 ; i >= 0 ; i-- ) {
3343 emitcode ("pop","%s",rb1regs[i]);
3346 unsaveRBank (0, ic, FALSE);
3351 /* This ISR uses a non-zero bank.
3353 * Restore any register banks saved by genFunction
3356 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3359 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3361 if (savedBanks & (1 << ix))
3363 unsaveRBank(ix, NULL, FALSE);
3367 if (options.useXstack)
3369 /* Restore bank AFTER calling unsaveRBank,
3370 * since it can trash r0.
3372 emitcode ("pop", "psw");
3376 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3378 if (options.stack10bit)
3380 emitcode ("pop", DP2_RESULT_REG);
3381 emitcode ("pop", "dpx1");
3382 emitcode ("pop", "dph1");
3383 emitcode ("pop", "dpl1");
3385 emitcode ("pop", "dps");
3386 emitcode ("pop", "dpx");
3388 if (!inExcludeList ("dph"))
3389 emitcode ("pop", "dph");
3390 if (!inExcludeList ("dpl"))
3391 emitcode ("pop", "dpl");
3392 if (!inExcludeList ("b"))
3393 emitcode ("pop", "b");
3394 if (!inExcludeList ("acc"))
3395 emitcode ("pop", "acc");
3397 /* if debug then send end of function */
3398 if (options.debug && currFunc) {
3400 emitcode ("", "C$%s$%d$%d$%d ==.",
3401 FileBaseName (ic->filename), currFunc->lastLine,
3402 ic->level, ic->block);
3403 if (IS_STATIC (currFunc->etype))
3404 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3406 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3410 emitcode ("reti", "");
3414 if (IFFUNC_CALLEESAVES(sym->type))
3418 /* if any registers used */
3421 /* save the registers used */
3422 for (i = sym->regsUsed->size; i >= 0; i--)
3424 if (bitVectBitValue (sym->regsUsed, i) ||
3425 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3426 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3432 /* if debug then send end of function */
3433 if (options.debug && currFunc)
3436 emitcode ("", "C$%s$%d$%d$%d ==.",
3437 FileBaseName (ic->filename), currFunc->lastLine,
3438 ic->level, ic->block);
3439 if (IS_STATIC (currFunc->etype))
3440 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3442 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3446 emitcode ("ret", "");
3451 /*-----------------------------------------------------------------*/
3452 /* genJavaNativeRet - generate code for return JavaNative */
3453 /*-----------------------------------------------------------------*/
3454 static void genJavaNativeRet(iCode *ic)
3458 aopOp (IC_LEFT (ic), ic, FALSE,
3459 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3460 size = AOP_SIZE (IC_LEFT (ic));
3464 /* it is assigned to GPR0-R3 then push them */
3465 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3466 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3467 for (i = 0 ; i < size ; i++ ) {
3468 emitcode ("push","%s",
3469 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3471 for (i = (size-1) ; i >= 0 ; i--) {
3472 emitcode ("pop","a%s",javaRet[i]);
3475 for (i = 0 ; i < size ; i++)
3476 emitcode ("mov","%s,%s",javaRet[i],
3477 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3479 for (i = size ; i < 4 ; i++ )
3480 emitcode ("mov","%s,#0",javaRet[i]);
3484 /*-----------------------------------------------------------------*/
3485 /* genRet - generate code for return statement */
3486 /*-----------------------------------------------------------------*/
3490 int size, offset = 0, pushed = 0;
3492 D (emitcode (";", "genRet "););
3494 /* if we have no return value then
3495 just generate the "ret" */
3499 /* if this is a JavaNative function then return
3500 value in different register */
3501 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3502 genJavaNativeRet(ic);
3505 /* we have something to return then
3506 move the return value into place */
3507 aopOp (IC_LEFT (ic), ic, FALSE,
3508 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3509 size = AOP_SIZE (IC_LEFT (ic));
3511 _startLazyDPSEvaluation ();
3515 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3517 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3519 emitcode ("push", "%s", l);
3524 /* Since A is the last element of fReturn,
3525 * is is OK to clobber it in the aopGet.
3527 l = aopGet (AOP (IC_LEFT (ic)), offset,
3528 FALSE, FALSE, NULL);
3529 if (strcmp (fReturn[offset], l))
3530 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3533 _endLazyDPSEvaluation ();
3540 if (strcmp (fReturn[pushed], "a"))
3541 emitcode ("pop", fReturn[pushed]);
3543 emitcode ("pop", "acc");
3546 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3549 /* generate a jump to the return label
3550 if the next is not the return statement */
3551 if (!(ic->next && ic->next->op == LABEL &&
3552 IC_LABEL (ic->next) == returnLabel))
3554 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3558 /*-----------------------------------------------------------------*/
3559 /* genLabel - generates a label */
3560 /*-----------------------------------------------------------------*/
3562 genLabel (iCode * ic)
3564 /* special case never generate */
3565 if (IC_LABEL (ic) == entryLabel)
3568 D (emitcode (";", "genLabel ");
3571 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3574 /*-----------------------------------------------------------------*/
3575 /* genGoto - generates a ljmp */
3576 /*-----------------------------------------------------------------*/
3578 genGoto (iCode * ic)
3580 D (emitcode (";", "genGoto ");
3582 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3585 /*-----------------------------------------------------------------*/
3586 /* findLabelBackwards: walks back through the iCode chain looking */
3587 /* for the given label. Returns number of iCode instructions */
3588 /* between that label and given ic. */
3589 /* Returns zero if label not found. */
3590 /*-----------------------------------------------------------------*/
3592 findLabelBackwards (iCode * ic, int key)
3601 /* If we have any pushes or pops, we cannot predict the distance.
3602 I don't like this at all, this should be dealt with in the
3604 if (ic->op == IPUSH || ic->op == IPOP) {
3608 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3610 /* printf("findLabelBackwards = %d\n", count); */
3618 /*-----------------------------------------------------------------*/
3619 /* genPlusIncr :- does addition with increment if possible */
3620 /*-----------------------------------------------------------------*/
3622 genPlusIncr (iCode * ic)
3624 unsigned int icount;
3625 unsigned int size = getDataSize (IC_RESULT (ic));
3627 /* will try to generate an increment */
3628 /* if the right side is not a literal
3630 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3633 /* if the literal value of the right hand side
3634 is greater than 4 then it is not worth it */
3635 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3638 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3639 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3641 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3645 /* if increment 16 bits in register */
3647 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3648 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3649 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3658 /* If the next instruction is a goto and the goto target
3659 * is <= 5 instructions previous to this, we can generate
3660 * jumps straight to that target.
3662 if (ic->next && ic->next->op == GOTO
3663 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3666 D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3667 tlbl = IC_LABEL (ic->next);
3672 tlbl = newiTempLabel (NULL);
3676 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3677 emitcode ("inc", "%s", l);
3679 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3680 IS_AOP_PREG (IC_RESULT (ic)))
3682 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3686 emitcode ("clr", "a");
3687 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3690 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
3691 emitcode ("inc", "%s", l);
3694 if (!strcmp(l, "acc"))
3696 emitcode("jnz", "!tlabel", tlbl->key + 100);
3698 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3699 IS_AOP_PREG (IC_RESULT (ic)))
3701 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3705 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3708 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3709 emitcode ("inc", "%s", l);
3713 if (!strcmp(l, "acc"))
3715 emitcode("jnz", "!tlabel", tlbl->key + 100);
3717 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3718 IS_AOP_PREG (IC_RESULT (ic)))
3720 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3724 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3727 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3728 emitcode ("inc", "%s", l); }
3732 emitcode ("", "!tlabeldef", tlbl->key + 100);
3737 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3738 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
3739 options.model == MODEL_FLAT24 ) {
3743 emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3745 emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3747 emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3750 while (icount--) emitcode ("inc","dptr");
3754 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3755 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3757 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3758 while (icount--) emitcode ("inc","dptr");
3759 emitcode ("mov","dps,#0");
3763 /* if the sizes are greater than 1 then we cannot */
3764 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3765 AOP_SIZE (IC_LEFT (ic)) > 1)
3768 /* we can if the aops of the left & result match or
3769 if they are in registers and the registers are the
3772 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3773 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3774 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3779 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3780 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3781 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3786 _startLazyDPSEvaluation ();
3789 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3791 _endLazyDPSEvaluation ();
3800 /*-----------------------------------------------------------------*/
3801 /* outBitAcc - output a bit in acc */
3802 /*-----------------------------------------------------------------*/
3804 outBitAcc (operand * result)
3806 symbol *tlbl = newiTempLabel (NULL);
3807 /* if the result is a bit */
3808 if (AOP_TYPE (result) == AOP_CRY)
3810 aopPut (AOP (result), "a", 0);
3814 emitcode ("jz", "!tlabel", tlbl->key + 100);
3815 emitcode ("mov", "a,%s", one);
3816 emitcode ("", "!tlabeldef", tlbl->key + 100);
3821 /*-----------------------------------------------------------------*/
3822 /* genPlusBits - generates code for addition of two bits */
3823 /*-----------------------------------------------------------------*/
3825 genPlusBits (iCode * ic)
3827 D (emitcode (";", "genPlusBits "););
3829 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3831 symbol *lbl = newiTempLabel (NULL);
3832 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3833 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3834 emitcode ("cpl", "c");
3835 emitcode ("", "!tlabeldef", (lbl->key + 100));
3836 outBitC (IC_RESULT (ic));
3840 emitcode ("clr", "a");
3841 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3842 emitcode ("rlc", "a");
3843 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3844 emitcode ("addc", "a,#0");
3845 outAcc (IC_RESULT (ic));
3850 adjustArithmeticResult (iCode * ic)
3852 if (opIsGptr (IC_RESULT (ic)) &&
3853 opIsGptr (IC_LEFT (ic)) &&
3854 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3856 aopPut (AOP (IC_RESULT (ic)),
3857 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3861 if (opIsGptr (IC_RESULT (ic)) &&
3862 opIsGptr (IC_RIGHT (ic)) &&
3863 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3865 aopPut (AOP (IC_RESULT (ic)),
3866 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3870 if (opIsGptr (IC_RESULT (ic)) &&
3871 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3872 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3873 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3874 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3877 SNPRINTF (buff, sizeof(buff),
3878 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3879 aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3883 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3884 // generates the result if possible. If result is generated, returns TRUE; otherwise
3885 // returns false and caller must deal with fact that result isn't aopOp'd.
3886 bool aopOp3(iCode * ic)
3888 bool dp1InUse, dp2InUse;
3891 // First, generate the right opcode. DPTR may be used if neither left nor result are
3894 // D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3895 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3896 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3897 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3899 // D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3900 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3901 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3902 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3905 // Right uses DPTR unless left or result is an AOP_STR; however,
3906 // if right is an AOP_STR, it must use DPTR regardless.
3907 if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
3908 && !AOP_IS_STR(IC_RIGHT(ic)))
3917 aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
3919 // if the right used DPTR, left MUST use DPTR2.
3920 // if the right used DPTR2, left MUST use DPTR.
3921 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3922 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3923 // enabling us to assign DPTR to result.
3925 if (AOP_USESDPTR(IC_RIGHT(ic)))
3929 else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3935 if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3945 aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3948 // We've op'd the left & right. So, if left or right are the same operand as result,
3949 // we know aopOp will succeed, and we can just do it & bail.
3950 if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3951 isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3953 // D(emitcode(";", "aopOp3: (left | right) & result equal"););
3954 aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3958 // Operands may be equivalent (but not equal) if they share a spill location. If
3959 // so, use the same DPTR or DPTR2.
3960 if (operandsEqu (IC_LEFT(ic), IC_RESULT(ic)))
3962 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
3965 if (operandsEqu (IC_RIGHT(ic), IC_RESULT(ic)))
3967 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
3971 // Note which dptrs are currently in use.
3972 dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3973 dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3975 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
3977 if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3982 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3983 if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3988 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
3989 if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3994 aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3996 // Some sanity checking...
3997 if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
4000 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
4001 __FILE__, __LINE__, ic->filename, ic->lineno);
4002 emitcode(";", ">>> unexpected DPTR here.");
4005 if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
4008 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
4009 __FILE__, __LINE__, ic->filename, ic->lineno);
4010 emitcode(";", ">>> unexpected DPTR2 here.");
4016 // Macro to aopOp all three operands of an ic. If this cannot be done,
4017 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
4018 // will be set TRUE. The caller must then handle the case specially, noting
4019 // that the IC_RESULT operand is not aopOp'd.
4021 #define AOP_OP_3_NOFATAL(ic, rc) \
4022 do { rc = !aopOp3(ic); } while (0)
4024 // aopOp the left & right operands of an ic.
4025 #define AOP_OP_2(ic) \
4026 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
4027 aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
4029 // convienience macro.
4030 #define AOP_SET_LOCALS(ic) \
4031 left = IC_LEFT(ic); \
4032 right = IC_RIGHT(ic); \
4033 result = IC_RESULT(ic);
4036 // Given an integer value of pushedSize bytes on the stack,
4037 // adjust it to be resultSize bytes, either by discarding
4038 // the most significant bytes or by zero-padding.
4040 // On exit from this macro, pushedSize will have been adjusted to
4041 // equal resultSize, and ACC may be trashed.
4042 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
4043 /* If the pushed data is bigger than the result, \
4044 * simply discard unused bytes. Icky, but works. \
4046 while (pushedSize > resultSize) \
4048 D (emitcode (";", "discarding unused result byte."););\
4049 emitcode ("pop", "acc"); \
4052 if (pushedSize < resultSize) \
4054 emitcode ("clr", "a"); \
4055 /* Conversly, we haven't pushed enough here. \
4056 * just zero-pad, and all is well. \
4058 while (pushedSize < resultSize) \
4060 emitcode("push", "acc"); \
4064 assert(pushedSize == resultSize);
4066 /*-----------------------------------------------------------------*/
4067 /* genPlus - generates code for addition */
4068 /*-----------------------------------------------------------------*/
4070 genPlus (iCode * ic)
4072 int size, offset = 0;
4076 D (emitcode (";", "genPlus "););
4078 /* special cases :- */
4079 if ( AOP_IS_STR(IC_LEFT(ic)) &&
4080 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4081 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4082 size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4084 while (size--) emitcode ("inc","dptr");
4086 emitcode ("mov","a,dpl");
4087 emitcode ("add","a,#!constbyte",size & 0xff);
4088 emitcode ("mov","dpl,a");
4089 emitcode ("mov","a,dph");
4090 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4091 emitcode ("mov","dph,a");
4092 emitcode ("mov","a,dpx");
4093 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4094 emitcode ("mov","dpx,a");
4096 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4099 if ( IS_SYMOP(IC_LEFT(ic)) &&
4100 OP_SYMBOL(IC_LEFT(ic))->remat &&
4101 isOperandInFarSpace(IC_RIGHT(ic))) {
4102 operand *op = IC_RIGHT(ic);
4103 IC_RIGHT(ic) = IC_LEFT(ic);
4107 AOP_OP_3_NOFATAL (ic, pushResult);
4111 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4116 /* if literal, literal on the right or
4117 if left requires ACC or right is already
4119 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4120 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4121 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4123 operand *t = IC_RIGHT (ic);
4124 IC_RIGHT (ic) = IC_LEFT (ic);
4126 emitcode (";", "Swapped plus args.");
4129 /* if both left & right are in bit
4131 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4132 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4138 /* if left in bit space & right literal */
4139 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4140 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4142 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4143 /* if result in bit space */
4144 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4146 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4147 emitcode ("cpl", "c");
4148 outBitC (IC_RESULT (ic));
4152 size = getDataSize (IC_RESULT (ic));
4153 _startLazyDPSEvaluation ();
4156 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4157 emitcode ("addc", "a,#0");
4158 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4160 _endLazyDPSEvaluation ();
4165 /* if I can do an increment instead
4166 of add then GOOD for ME */
4167 if (genPlusIncr (ic) == TRUE)
4169 emitcode (";", "did genPlusIncr");
4174 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4176 _startLazyDPSEvaluation ();
4179 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4181 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4183 emitcode ("add", "a,%s",
4184 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4186 emitcode ("addc", "a,%s",
4187 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4191 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4193 /* right is going to use ACC or we would have taken the
4196 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4198 D(emitcode(";", "+ AOP_ACC special case."););
4199 emitcode("xch", "a, %s", DP2_RESULT_REG);
4201 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4204 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4207 emitcode("add", "a, %s", DP2_RESULT_REG);
4211 emitcode ("add", "a,%s",
4212 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4218 emitcode ("addc", "a,%s",
4219 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4225 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4229 emitcode ("push", "acc");
4233 _endLazyDPSEvaluation ();
4237 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4239 size = getDataSize (IC_LEFT (ic));
4240 rSize = getDataSize (IC_RESULT (ic));
4242 ADJUST_PUSHED_RESULT(size, rSize);
4244 _startLazyDPSEvaluation ();
4247 emitcode ("pop", "acc");
4248 aopPut (AOP (IC_RESULT (ic)), "a", size);
4250 _endLazyDPSEvaluation ();
4253 adjustArithmeticResult (ic);
4256 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4257 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4258 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4261 /*-----------------------------------------------------------------*/
4262 /* genMinusDec :- does subtraction with deccrement if possible */
4263 /*-----------------------------------------------------------------*/
4265 genMinusDec (iCode * ic)
4267 unsigned int icount;
4268 unsigned int size = getDataSize (IC_RESULT (ic));
4270 /* will try to generate an increment */
4271 /* if the right side is not a literal
4273 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4276 /* if the literal value of the right hand side
4277 is greater than 4 then it is not worth it */
4278 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4281 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4282 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4284 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4288 /* if decrement 16 bits in register */
4289 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4290 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4291 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4300 /* If the next instruction is a goto and the goto target
4301 * is <= 5 instructions previous to this, we can generate
4302 * jumps straight to that target.
4304 if (ic->next && ic->next->op == GOTO
4305 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4308 emitcode (";", "tail decrement optimized (range %d)", labelRange);
4309 tlbl = IC_LABEL (ic->next);
4314 tlbl = newiTempLabel (NULL);
4318 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4319 emitcode ("dec", "%s", l);
4321 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4322 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4323 IS_AOP_PREG (IC_RESULT (ic)))
4325 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4329 emitcode ("mov", "a,#!constbyte",0xff);
4330 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4332 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4333 emitcode ("dec", "%s", l);
4336 if (!strcmp(l, "acc"))
4338 emitcode("jnz", "!tlabel", tlbl->key + 100);
4340 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4341 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4342 IS_AOP_PREG (IC_RESULT (ic)))
4344 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4348 emitcode ("mov", "a,#!constbyte",0xff);
4349 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4351 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4352 emitcode ("dec", "%s", l);
4356 if (!strcmp(l, "acc"))
4358 emitcode("jnz", "!tlabel", tlbl->key + 100);
4360 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4361 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4362 IS_AOP_PREG (IC_RESULT (ic)))
4364 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4368 emitcode ("mov", "a,#!constbyte",0xff);
4369 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4371 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4372 emitcode ("dec", "%s", l);
4376 emitcode ("", "!tlabeldef", tlbl->key + 100);
4381 /* if the sizes are greater than 1 then we cannot */
4382 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4383 AOP_SIZE (IC_LEFT (ic)) > 1)
4386 /* we can if the aops of the left & result match or
4387 if they are in registers and the registers are the
4390 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4391 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4392 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4395 _startLazyDPSEvaluation ();
4398 emitcode ("dec", "%s",
4399 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4401 _endLazyDPSEvaluation ();
4409 /*-----------------------------------------------------------------*/
4410 /* addSign - complete with sign */
4411 /*-----------------------------------------------------------------*/
4413 addSign (operand * result, int offset, int sign)
4415 int size = (getDataSize (result) - offset);
4418 _startLazyDPSEvaluation();
4421 emitcode ("rlc", "a");
4422 emitcode ("subb", "a,acc");
4425 aopPut (AOP (result), "a", offset++);
4432 aopPut (AOP (result), zero, offset++);
4435 _endLazyDPSEvaluation();
4439 /*-----------------------------------------------------------------*/
4440 /* genMinusBits - generates code for subtraction of two bits */
4441 /*-----------------------------------------------------------------*/
4443 genMinusBits (iCode * ic)
4445 symbol *lbl = newiTempLabel (NULL);
4447 D (emitcode (";", "genMinusBits "););
4449 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4451 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4452 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4453 emitcode ("cpl", "c");
4454 emitcode ("", "!tlabeldef", (lbl->key + 100));
4455 outBitC (IC_RESULT (ic));
4459 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4460 emitcode ("subb", "a,acc");
4461 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4462 emitcode ("inc", "a");
4463 emitcode ("", "!tlabeldef", (lbl->key + 100));
4464 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4465 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4469 /*-----------------------------------------------------------------*/
4470 /* genMinus - generates code for subtraction */
4471 /*-----------------------------------------------------------------*/
4473 genMinus (iCode * ic)
4475 int size, offset = 0;
4480 D (emitcode (";", "genMinus "););
4482 AOP_OP_3_NOFATAL(ic, pushResult);
4486 /* special cases :- */
4487 /* if both left & right are in bit space */
4488 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4489 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4495 /* if I can do an decrement instead
4496 of subtract then GOOD for ME */
4497 if (genMinusDec (ic) == TRUE)
4502 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4504 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4510 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4515 /* if literal, add a,#-lit, else normal subb */
4516 _startLazyDPSEvaluation ();
4518 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4519 if (AOP_USESDPTR(IC_RIGHT(ic))) {
4520 emitcode ("mov","b,%s",
4521 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4522 MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4523 emitcode ("subb","a,b");
4525 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4526 emitcode ("subb", "a,%s",
4527 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE,
4531 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4532 /* first add without previous c */
4534 if (!size && lit==-1) {
4535 emitcode ("dec", "a");
4537 emitcode ("add", "a,#!constbyte",
4538 (unsigned int) (lit & 0x0FFL));
4541 emitcode ("addc", "a,#!constbyte",
4542 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4547 emitcode ("push", "acc");
4549 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4553 _endLazyDPSEvaluation ();
4557 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4559 size = getDataSize (IC_LEFT (ic));
4560 rSize = getDataSize (IC_RESULT (ic));
4562 ADJUST_PUSHED_RESULT(size, rSize);
4564 _startLazyDPSEvaluation ();
4567 emitcode ("pop", "acc");
4568 aopPut (AOP (IC_RESULT (ic)), "a", size);
4570 _endLazyDPSEvaluation ();
4573 adjustArithmeticResult (ic);
4576 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4577 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4578 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4582 /*-----------------------------------------------------------------*/
4583 /* genMultbits :- multiplication of bits */
4584 /*-----------------------------------------------------------------*/
4586 genMultbits (operand * left,
4591 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4592 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4593 aopOp(result, ic, TRUE, FALSE);
4598 /*-----------------------------------------------------------------*/
4599 /* genMultOneByte : 8*8=8/16 bit multiplication */
4600 /*-----------------------------------------------------------------*/
4602 genMultOneByte (operand * left,
4607 sym_link *opetype = operandType (result);
4611 /* (if two literals: the value is computed before) */
4612 /* if one literal, literal on the right */
4613 if (AOP_TYPE (left) == AOP_LIT)
4618 emitcode (";", "swapped left and right");
4621 if (SPEC_USIGN(opetype)
4622 // ignore the sign of left and right, what else can we do?
4623 || (SPEC_USIGN(operandType(left)) &&
4624 SPEC_USIGN(operandType(right)))) {
4625 // just an unsigned 8*8=8/16 multiply
4626 //emitcode (";","unsigned");
4627 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4628 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4629 emitcode ("mul", "ab");
4631 _G.accInUse++; _G.bInUse++;
4632 aopOp(result, ic, TRUE, FALSE);
4634 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4636 // this should never happen
4637 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4638 AOP_SIZE(result), __FILE__, lineno);
4642 aopPut (AOP (result), "a", 0);
4643 _G.accInUse--; _G.bInUse--;
4644 if (AOP_SIZE(result)==2)
4646 aopPut (AOP (result), "b", 1);
4651 // we have to do a signed multiply
4653 emitcode (";", "signed");
4654 emitcode ("clr", "F0"); // reset sign flag
4655 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4657 lbl=newiTempLabel(NULL);
4658 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4659 // left side is negative, 8-bit two's complement, this fails for -128
4660 emitcode ("setb", "F0"); // set sign flag
4661 emitcode ("cpl", "a");
4662 emitcode ("inc", "a");
4664 emitcode ("", "!tlabeldef", lbl->key+100);
4667 if (AOP_TYPE(right)==AOP_LIT) {
4668 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
4669 /* AND literal negative */
4670 if ((int) val < 0) {
4671 emitcode ("cpl", "F0"); // complement sign flag
4672 emitcode ("mov", "b,#!constbyte", -val);
4674 emitcode ("mov", "b,#!constbyte", val);
4677 lbl=newiTempLabel(NULL);
4678 emitcode ("mov", "b,a");
4679 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4680 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4681 // right side is negative, 8-bit two's complement
4682 emitcode ("cpl", "F0"); // complement sign flag
4683 emitcode ("cpl", "a");
4684 emitcode ("inc", "a");
4685 emitcode ("", "!tlabeldef", lbl->key+100);
4687 emitcode ("mul", "ab");
4689 _G.accInUse++;_G.bInUse++;
4690 aopOp(result, ic, TRUE, FALSE);
4692 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4694 // this should never happen
4695 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4696 AOP_SIZE(result), __FILE__, lineno);
4700 lbl=newiTempLabel(NULL);
4701 emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4702 // only ONE op was negative, we have to do a 8/16-bit two's complement
4703 emitcode ("cpl", "a"); // lsb
4704 if (AOP_SIZE(result)==1) {
4705 emitcode ("inc", "a");
4707 emitcode ("add", "a,#1");
4708 emitcode ("xch", "a,b");
4709 emitcode ("cpl", "a"); // msb
4710 emitcode ("addc", "a,#0");
4711 emitcode ("xch", "a,b");
4714 emitcode ("", "!tlabeldef", lbl->key+100);
4715 aopPut (AOP (result), "a", 0);
4716 _G.accInUse--;_G.bInUse--;
4717 if (AOP_SIZE(result)==2) {
4718 aopPut (AOP (result), "b", 1);
4722 /*-----------------------------------------------------------------*/
4723 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4724 /*-----------------------------------------------------------------*/
4725 static void genMultTwoByte (operand *left, operand *right,
4726 operand *result, iCode *ic)
4728 sym_link *retype = getSpec(operandType(right));
4729 sym_link *letype = getSpec(operandType(left));
4730 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4733 if (AOP_TYPE (left) == AOP_LIT) {
4738 /* save EA bit in F1 */
4739 lbl = newiTempLabel(NULL);
4740 emitcode ("setb","F1");
4741 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4742 emitcode ("clr","F1");
4743 emitcode("","!tlabeldef",lbl->key+100);
4745 /* load up MB with right */
4747 emitcode("clr","F0");
4748 if (AOP_TYPE(right) == AOP_LIT) {
4749 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4751 emitcode("setb","F0");
4754 emitcode ("mov","mb,#!constbyte",val & 0xff);
4755 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4757 lbl = newiTempLabel(NULL);
4758 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4759 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4760 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4761 emitcode ("xch", "a,b");
4762 emitcode ("cpl","a");
4763 emitcode ("add", "a,#1");
4764 emitcode ("xch", "a,b");
4765 emitcode ("cpl", "a"); // msb
4766 emitcode ("addc", "a,#0");
4767 emitcode ("setb","F0");
4768 emitcode ("","!tlabeldef",lbl->key+100);
4769 emitcode ("mov","mb,b");
4770 emitcode ("mov","mb,a");
4773 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4774 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4776 /* load up MA with left */
4778 lbl = newiTempLabel(NULL);
4779 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4780 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4781 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4782 emitcode ("xch", "a,b");
4783 emitcode ("cpl","a");
4784 emitcode ("add", "a,#1");
4785 emitcode ("xch", "a,b");
4786 emitcode ("cpl", "a"); // msb
4787 emitcode ("addc","a,#0");
4788 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4789 emitcode ("setb","F0");
4790 emitcode ("","!tlabeldef",lbl->key+100);
4791 emitcode ("mov","ma,b");
4792 emitcode ("mov","ma,a");
4794 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4795 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4797 /* wait for multiplication to finish */
4798 lbl = newiTempLabel(NULL);
4799 emitcode("","!tlabeldef", lbl->key+100);
4800 emitcode("mov","a,mcnt1");
4801 emitcode("anl","a,#!constbyte",0x80);
4802 emitcode("jnz","!tlabel",lbl->key+100);
4804 freeAsmop (left, NULL, ic, TRUE);
4805 freeAsmop (right, NULL, ic,TRUE);
4806 aopOp(result, ic, TRUE, FALSE);
4808 /* if unsigned then simple */
4810 emitcode ("mov","a,ma");
4811 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4812 emitcode ("mov","a,ma");
4813 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4814 aopPut(AOP(result),"ma",1);
4815 aopPut(AOP(result),"ma",0);
4817 emitcode("push","ma");
4818 emitcode("push","ma");
4819 emitcode("push","ma");
4821 /* negate result if needed */
4822 lbl = newiTempLabel(NULL);
4823 emitcode("jnb","F0,!tlabel",lbl->key+100);
4824 emitcode("cpl","a");
4825 emitcode("add","a,#1");
4826 emitcode("","!tlabeldef", lbl->key+100);
4827 if (AOP_TYPE(result) == AOP_ACC)
4829 D(emitcode(";", "ACC special case."););
4830 /* We know result is the only live aop, and
4831 * it's obviously not a DPTR2, so AP is available.
4833 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4837 aopPut(AOP(result),"a",0);
4840 emitcode("pop","acc");
4841 lbl = newiTempLabel(NULL);
4842 emitcode("jnb","F0,!tlabel",lbl->key+100);
4843 emitcode("cpl","a");
4844 emitcode("addc","a,#0");
4845 emitcode("","!tlabeldef", lbl->key+100);
4846 aopPut(AOP(result),"a",1);
4847 emitcode("pop","acc");
4848 if (AOP_SIZE(result) >= 3) {
4849 lbl = newiTempLabel(NULL);
4850 emitcode("jnb","F0,!tlabel",lbl->key+100);
4851 emitcode("cpl","a");
4852 emitcode("addc","a,#0");
4853 emitcode("","!tlabeldef", lbl->key+100);
4854 aopPut(AOP(result),"a",2);
4856 emitcode("pop","acc");
4857 if (AOP_SIZE(result) >= 4) {
4858 lbl = newiTempLabel(NULL);
4859 emitcode("jnb","F0,!tlabel",lbl->key+100);
4860 emitcode("cpl","a");
4861 emitcode("addc","a,#0");
4862 emitcode("","!tlabeldef", lbl->key+100);
4863 aopPut(AOP(result),"a",3);
4865 if (AOP_TYPE(result) == AOP_ACC)
4867 /* We stashed the result away above. */
4868 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4872 freeAsmop (result, NULL, ic, TRUE);
4874 /* restore EA bit in F1 */
4875 lbl = newiTempLabel(NULL);
4876 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4877 emitcode ("setb","EA");
4878 emitcode("","!tlabeldef",lbl->key+100);
4882 /*-----------------------------------------------------------------*/
4883 /* genMult - generates code for multiplication */
4884 /*-----------------------------------------------------------------*/
4886 genMult (iCode * ic)
4888 operand *left = IC_LEFT (ic);
4889 operand *right = IC_RIGHT (ic);
4890 operand *result = IC_RESULT (ic);
4892 D (emitcode (";", "genMult "););
4894 /* assign the amsops */
4897 /* special cases first */
4899 if (AOP_TYPE (left) == AOP_CRY &&
4900 AOP_TYPE (right) == AOP_CRY)
4902 genMultbits (left, right, result, ic);
4906 /* if both are of size == 1 */
4907 if (AOP_SIZE (left) == 1 &&
4908 AOP_SIZE (right) == 1)
4910 genMultOneByte (left, right, result, ic);
4914 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4915 /* use the ds390 ARITHMETIC accel UNIT */
4916 genMultTwoByte (left, right, result, ic);
4919 /* should have been converted to function call */
4923 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4924 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4925 freeAsmop (result, NULL, ic, TRUE);
4928 /*-----------------------------------------------------------------*/
4929 /* genDivbits :- division of bits */
4930 /*-----------------------------------------------------------------*/
4932 genDivbits (operand * left,
4940 /* the result must be bit */
4941 LOAD_AB_FOR_DIV (left, right, l);
4942 emitcode ("div", "ab");
4943 emitcode ("rrc", "a");
4944 aopOp(result, ic, TRUE, FALSE);
4946 aopPut (AOP (result), "c", 0);
4949 /*-----------------------------------------------------------------*/
4950 /* genDivOneByte : 8 bit division */
4951 /*-----------------------------------------------------------------*/
4953 genDivOneByte (operand * left,
4958 sym_link *opetype = operandType (result);
4964 /* signed or unsigned */
4965 if (SPEC_USIGN (opetype))
4967 /* unsigned is easy */
4968 LOAD_AB_FOR_DIV (left, right, l);
4969 emitcode ("div", "ab");
4972 aopOp(result, ic, TRUE, FALSE);
4973 aopPut (AOP (result), "a", 0);
4976 size = AOP_SIZE (result) - 1;
4980 aopPut (AOP (result), zero, offset++);
4985 /* signed is a little bit more difficult */
4987 /* save the signs of the operands */
4988 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4989 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4990 emitcode ("push", "acc"); /* save it on the stack */
4992 /* now sign adjust for both left & right */
4993 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4994 lbl = newiTempLabel (NULL);
4995 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4996 emitcode ("cpl", "a");
4997 emitcode ("inc", "a");
4998 emitcode ("", "!tlabeldef", (lbl->key + 100));
4999 emitcode ("mov", "b,a");
5001 /* sign adjust left side */
5002 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5004 lbl = newiTempLabel (NULL);
5005 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5006 emitcode ("cpl", "a");
5007 emitcode ("inc", "a");
5008 emitcode ("", "!tlabeldef", (lbl->key + 100));
5010 /* now the division */
5011 emitcode ("nop", "; workaround for DS80C390 div bug.");
5012 emitcode ("div", "ab");
5013 /* we are interested in the lower order
5015 emitcode ("mov", "b,a");
5016 lbl = newiTempLabel (NULL);
5017 emitcode ("pop", "acc");
5018 /* if there was an over flow we don't
5019 adjust the sign of the result */
5020 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5021 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5023 emitcode ("clr", "a");
5024 emitcode ("subb", "a,b");
5025 emitcode ("mov", "b,a");
5026 emitcode ("", "!tlabeldef", (lbl->key + 100));
5028 /* now we are done */
5029 _G.accInUse++; _G.bInUse++;
5030 aopOp(result, ic, TRUE, FALSE);
5032 aopPut (AOP (result), "b", 0);
5034 size = AOP_SIZE (result) - 1;
5038 emitcode ("mov", "c,b.7");
5039 emitcode ("subb", "a,acc");
5043 aopPut (AOP (result), "a", offset++);
5045 _G.accInUse--; _G.bInUse--;
5049 /*-----------------------------------------------------------------*/
5050 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
5051 /*-----------------------------------------------------------------*/
5052 static void genDivTwoByte (operand *left, operand *right,
5053 operand *result, iCode *ic)
5055 sym_link *retype = getSpec(operandType(right));
5056 sym_link *letype = getSpec(operandType(left));
5057 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5060 /* save EA bit in F1 */
5061 lbl = newiTempLabel(NULL);
5062 emitcode ("setb","F1");
5063 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5064 emitcode ("clr","F1");
5065 emitcode("","!tlabeldef",lbl->key+100);
5067 /* load up MA with left */
5069 emitcode("clr","F0");
5070 lbl = newiTempLabel(NULL);
5071 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5072 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5073 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5074 emitcode ("xch", "a,b");
5075 emitcode ("cpl","a");
5076 emitcode ("add", "a,#1");
5077 emitcode ("xch", "a,b");
5078 emitcode ("cpl", "a"); // msb
5079 emitcode ("addc","a,#0");
5080 emitcode ("setb","F0");
5081 emitcode ("","!tlabeldef",lbl->key+100);
5082 emitcode ("mov","ma,b");
5083 emitcode ("mov","ma,a");
5085 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5086 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5089 /* load up MB with right */
5091 if (AOP_TYPE(right) == AOP_LIT) {
5092 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5094 lbl = newiTempLabel(NULL);
5095 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5096 emitcode("setb","F0");
5097 emitcode ("","!tlabeldef",lbl->key+100);
5100 emitcode ("mov","mb,#!constbyte",val & 0xff);
5101 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5103 lbl = newiTempLabel(NULL);
5104 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5105 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5106 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5107 emitcode ("xch", "a,b");
5108 emitcode ("cpl","a");
5109 emitcode ("add", "a,#1");
5110 emitcode ("xch", "a,b");
5111 emitcode ("cpl", "a"); // msb
5112 emitcode ("addc", "a,#0");
5113 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5114 emitcode ("setb","F0");
5115 emitcode ("","!tlabeldef",lbl->key+100);
5116 emitcode ("mov","mb,b");
5117 emitcode ("mov","mb,a");
5120 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5121 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5124 /* wait for multiplication to finish */
5125 lbl = newiTempLabel(NULL);
5126 emitcode("","!tlabeldef", lbl->key+100);
5127 emitcode("mov","a,mcnt1");
5128 emitcode("anl","a,#!constbyte",0x80);
5129 emitcode("jnz","!tlabel",lbl->key+100);
5131 freeAsmop (left, NULL, ic, TRUE);
5132 freeAsmop (right, NULL, ic,TRUE);
5133 aopOp(result, ic, TRUE, FALSE);
5135 /* if unsigned then simple */
5137 aopPut(AOP(result),"ma",1);
5138 aopPut(AOP(result),"ma",0);
5140 emitcode("push","ma");
5142 /* negate result if needed */
5143 lbl = newiTempLabel(NULL);
5144 emitcode("jnb","F0,!tlabel",lbl->key+100);
5145 emitcode("cpl","a");
5146 emitcode("add","a,#1");
5147 emitcode("","!tlabeldef", lbl->key+100);
5148 aopPut(AOP(result),"a",0);
5149 emitcode("pop","acc");
5150 lbl = newiTempLabel(NULL);
5151 emitcode("jnb","F0,!tlabel",lbl->key+100);
5152 emitcode("cpl","a");
5153 emitcode("addc","a,#0");
5154 emitcode("","!tlabeldef", lbl->key+100);
5155 aopPut(AOP(result),"a",1);
5157 freeAsmop (result, NULL, ic, TRUE);
5158 /* restore EA bit in F1 */
5159 lbl = newiTempLabel(NULL);
5160 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5161 emitcode ("setb","EA");
5162 emitcode("","!tlabeldef",lbl->key+100);
5166 /*-----------------------------------------------------------------*/
5167 /* genDiv - generates code for division */
5168 /*-----------------------------------------------------------------*/
5172 operand *left = IC_LEFT (ic);
5173 operand *right = IC_RIGHT (ic);
5174 operand *result = IC_RESULT (ic);
5176 D (emitcode (";", "genDiv "););
5178 /* assign the amsops */
5181 /* special cases first */
5183 if (AOP_TYPE (left) == AOP_CRY &&
5184 AOP_TYPE (right) == AOP_CRY)
5186 genDivbits (left, right, result, ic);
5190 /* if both are of size == 1 */
5191 if (AOP_SIZE (left) == 1 &&
5192 AOP_SIZE (right) == 1)
5194 genDivOneByte (left, right, result, ic);
5198 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5199 /* use the ds390 ARITHMETIC accel UNIT */
5200 genDivTwoByte (left, right, result, ic);
5203 /* should have been converted to function call */
5206 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5207 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5208 freeAsmop (result, NULL, ic, TRUE);
5211 /*-----------------------------------------------------------------*/
5212 /* genModbits :- modulus of bits */
5213 /*-----------------------------------------------------------------*/
5215 genModbits (operand * left,
5223 /* the result must be bit */
5224 LOAD_AB_FOR_DIV (left, right, l);
5225 emitcode ("div", "ab");
5226 emitcode ("mov", "a,b");
5227 emitcode ("rrc", "a");
5228 aopOp(result, ic, TRUE, FALSE);
5229 aopPut (AOP (result), "c", 0);
5232 /*-----------------------------------------------------------------*/
5233 /* genModOneByte : 8 bit modulus */
5234 /*-----------------------------------------------------------------*/
5236 genModOneByte (operand * left,
5241 sym_link *opetype = operandType (result);
5245 /* signed or unsigned */
5246 if (SPEC_USIGN (opetype))
5248 /* unsigned is easy */
5249 LOAD_AB_FOR_DIV (left, right, l);
5250 emitcode ("div", "ab");
5251 aopOp(result, ic, TRUE, FALSE);
5252 aopPut (AOP (result), "b", 0);
5256 /* signed is a little bit more difficult */
5258 /* save the signs of the operands */
5259 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5261 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5262 emitcode ("push", "acc"); /* save it on the stack */
5264 /* now sign adjust for both left & right */
5265 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5267 lbl = newiTempLabel (NULL);
5268 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5269 emitcode ("cpl", "a");
5270 emitcode ("inc", "a");
5271 emitcode ("", "!tlabeldef", (lbl->key + 100));
5272 emitcode ("mov", "b,a");
5274 /* sign adjust left side */
5275 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5277 lbl = newiTempLabel (NULL);
5278 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5279 emitcode ("cpl", "a");
5280 emitcode ("inc", "a");
5281 emitcode ("", "!tlabeldef", (lbl->key + 100));
5283 /* now the multiplication */
5284 emitcode ("nop", "; workaround for DS80C390 div bug.");
5285 emitcode ("div", "ab");
5286 /* we are interested in the lower order
5288 lbl = newiTempLabel (NULL);
5289 emitcode ("pop", "acc");
5290 /* if there was an over flow we don't
5291 adjust the sign of the result */
5292 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5293 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5295 emitcode ("clr", "a");
5296 emitcode ("subb", "a,b");
5297 emitcode ("mov", "b,a");
5298 emitcode ("", "!tlabeldef", (lbl->key + 100));
5301 /* now we are done */
5302 aopOp(result, ic, TRUE, FALSE);
5303 aopPut (AOP (result), "b", 0);
5308 /*-----------------------------------------------------------------*/
5309 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
5310 /*-----------------------------------------------------------------*/
5311 static void genModTwoByte (operand *left, operand *right,
5312 operand *result, iCode *ic)
5314 sym_link *retype = getSpec(operandType(right));
5315 sym_link *letype = getSpec(operandType(left));
5316 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5319 /* load up MA with left */
5320 /* save EA bit in F1 */
5321 lbl = newiTempLabel(NULL);
5322 emitcode ("setb","F1");
5323 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5324 emitcode ("clr","F1");
5325 emitcode("","!tlabeldef",lbl->key+100);
5328 lbl = newiTempLabel(NULL);
5329 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5330 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5331 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5332 emitcode ("xch", "a,b");
5333 emitcode ("cpl","a");
5334 emitcode ("add", "a,#1");
5335 emitcode ("xch", "a,b");
5336 emitcode ("cpl", "a"); // msb
5337 emitcode ("addc","a,#0");
5338 emitcode ("","!tlabeldef",lbl->key+100);
5339 emitcode ("mov","ma,b");
5340 emitcode ("mov","ma,a");
5342 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5343 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5346 /* load up MB with right */
5348 if (AOP_TYPE(right) == AOP_LIT) {
5349 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5353 emitcode ("mov","mb,#!constbyte",val & 0xff);
5354 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5356 lbl = newiTempLabel(NULL);
5357 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5358 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5359 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5360 emitcode ("xch", "a,b");
5361 emitcode ("cpl","a");
5362 emitcode ("add", "a,#1");
5363 emitcode ("xch", "a,b");
5364 emitcode ("cpl", "a"); // msb
5365 emitcode ("addc", "a,#0");
5366 emitcode ("","!tlabeldef",lbl->key+100);
5367 emitcode ("mov","mb,b");
5368 emitcode ("mov","mb,a");
5371 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5372 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5375 /* wait for multiplication to finish */
5376 lbl = newiTempLabel(NULL);
5377 emitcode("","!tlabeldef", lbl->key+100);
5378 emitcode("mov","a,mcnt1");
5379 emitcode("anl","a,#!constbyte",0x80);
5380 emitcode("jnz","!tlabel",lbl->key+100);
5382 freeAsmop (left, NULL, ic, TRUE);
5383 freeAsmop (right, NULL, ic,TRUE);
5384 aopOp(result, ic, TRUE, FALSE);
5386 aopPut(AOP(result),"mb",1);
5387 aopPut(AOP(result),"mb",0);
5388 freeAsmop (result, NULL, ic, TRUE);
5390 /* restore EA bit in F1 */
5391 lbl = newiTempLabel(NULL);
5392 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5393 emitcode ("setb","EA");
5394 emitcode("","!tlabeldef",lbl->key+100);
5398 /*-----------------------------------------------------------------*/
5399 /* genMod - generates code for division */
5400 /*-----------------------------------------------------------------*/
5404 operand *left = IC_LEFT (ic);
5405 operand *right = IC_RIGHT (ic);
5406 operand *result = IC_RESULT (ic);
5408 D (emitcode (";", "genMod "); );
5410 /* assign the amsops */
5413 /* special cases first */
5415 if (AOP_TYPE (left) == AOP_CRY &&
5416 AOP_TYPE (right) == AOP_CRY)
5418 genModbits (left, right, result, ic);
5422 /* if both are of size == 1 */
5423 if (AOP_SIZE (left) == 1 &&
5424 AOP_SIZE (right) == 1)
5426 genModOneByte (left, right, result, ic);
5430 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5431 /* use the ds390 ARITHMETIC accel UNIT */
5432 genModTwoByte (left, right, result, ic);
5436 /* should have been converted to function call */
5440 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5441 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5442 freeAsmop (result, NULL, ic, TRUE);
5445 /*-----------------------------------------------------------------*/
5446 /* genIfxJump :- will create a jump depending on the ifx */
5447 /*-----------------------------------------------------------------*/
5449 genIfxJump (iCode * ic, char *jval)
5452 symbol *tlbl = newiTempLabel (NULL);
5455 D (emitcode (";", "genIfxJump"););
5457 /* if true label then we jump if condition
5461 jlbl = IC_TRUE (ic);
5462 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5463 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5467 /* false label is present */
5468 jlbl = IC_FALSE (ic);
5469 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5470 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5472 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5473 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5475 emitcode (inst, "!tlabel", tlbl->key + 100);
5476 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5477 emitcode ("", "!tlabeldef", tlbl->key + 100);
5479 /* mark the icode as generated */
5483 /*-----------------------------------------------------------------*/
5484 /* genCmp :- greater or less than comparison */
5485 /*-----------------------------------------------------------------*/
5487 genCmp (operand * left, operand * right,
5488 iCode * ic, iCode * ifx, int sign)
5490 int size, offset = 0;
5491 unsigned long lit = 0L;
5494 D (emitcode (";", "genCmp"););
5496 result = IC_RESULT (ic);
5498 /* if left & right are bit variables */
5499 if (AOP_TYPE (left) == AOP_CRY &&
5500 AOP_TYPE (right) == AOP_CRY)
5502 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5503 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5507 /* subtract right from left if at the
5508 end the carry flag is set then we know that
5509 left is greater than right */
5510 size = max (AOP_SIZE (left), AOP_SIZE (right));
5512 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5513 if ((size == 1) && !sign
5514 && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5516 symbol *lbl = newiTempLabel (NULL);
5517 emitcode ("cjne", "%s,%s,!tlabel",
5518 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5519 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5521 emitcode ("", "!tlabeldef", lbl->key + 100);
5525 if (AOP_TYPE (right) == AOP_LIT)
5527 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5528 /* optimize if(x < 0) or if(x >= 0) */
5537 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5539 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5540 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5542 aopOp (result, ic, FALSE, FALSE);
5544 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5546 freeAsmop (result, NULL, ic, TRUE);
5547 genIfxJump (ifx, "acc.7");
5552 emitcode ("rlc", "a");
5554 goto release_freedLR;
5562 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5563 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5564 // emitcode (";", "genCmp #2");
5565 if (sign && (size == 0))
5567 // emitcode (";", "genCmp #3");
5568 emitcode ("xrl", "a,#!constbyte",0x80);
5569 if (AOP_TYPE (right) == AOP_LIT)
5571 unsigned long lit = (unsigned long)
5572 floatFromVal (AOP (right)->aopu.aop_lit);
5573 // emitcode (";", "genCmp #3.1");
5574 emitcode ("subb", "a,#!constbyte",
5575 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5579 // emitcode (";", "genCmp #3.2");
5581 MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5582 saveAccWarn = DEFAULT_ACC_WARNING;
5583 emitcode ("xrl", "b,#!constbyte",0x80);
5584 emitcode ("subb", "a,b");
5591 // emitcode (";", "genCmp #4");
5593 s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5594 saveAccWarn = DEFAULT_ACC_WARNING;
5596 emitcode ("subb", "a,%s", s);
5603 /* Don't need the left & right operands any more; do need the result. */
5604 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5605 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5607 aopOp (result, ic, FALSE, FALSE);
5611 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5617 /* if the result is used in the next
5618 ifx conditional branch then generate
5619 code a little differently */
5622 genIfxJump (ifx, "c");
5628 /* leave the result in acc */
5630 freeAsmop (result, NULL, ic, TRUE);
5633 /*-----------------------------------------------------------------*/
5634 /* genCmpGt :- greater than comparison */
5635 /*-----------------------------------------------------------------*/
5637 genCmpGt (iCode * ic, iCode * ifx)
5639 operand *left, *right;
5640 sym_link *letype, *retype;
5643 D (emitcode (";", "genCmpGt ");
5646 left = IC_LEFT (ic);
5647 right = IC_RIGHT (ic);
5649 letype = getSpec (operandType (left));
5650 retype = getSpec (operandType (right));
5651 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5653 /* assign the left & right amsops */
5656 genCmp (right, left, ic, ifx, sign);
5659 /*-----------------------------------------------------------------*/
5660 /* genCmpLt - less than comparisons */
5661 /*-----------------------------------------------------------------*/
5663 genCmpLt (iCode * ic, iCode * ifx)
5665 operand *left, *right;
5666 sym_link *letype, *retype;
5669 D (emitcode (";", "genCmpLt "););
5671 left = IC_LEFT (ic);
5672 right = IC_RIGHT (ic);
5674 letype = getSpec (operandType (left));
5675 retype = getSpec (operandType (right));
5676 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5678 /* assign the left & right amsops */
5681 genCmp (left, right, ic, ifx, sign);
5684 /*-----------------------------------------------------------------*/
5685 /* gencjneshort - compare and jump if not equal */
5686 /*-----------------------------------------------------------------*/
5688 gencjneshort (operand * left, operand * right, symbol * lbl)
5690 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5692 unsigned long lit = 0L;
5694 D (emitcode (";", "gencjneshort");
5697 /* if the left side is a literal or
5698 if the right is in a pointer register and left
5700 if ((AOP_TYPE (left) == AOP_LIT) ||
5701 (AOP_TYPE (left) == AOP_IMMD) ||
5702 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5709 if (AOP_TYPE (right) == AOP_LIT)
5710 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5712 if (opIsGptr (left) || opIsGptr (right))
5714 /* We are comparing a generic pointer to something.
5715 * Exclude the generic type byte from the comparison.
5718 D (emitcode (";", "cjneshort: generic ptr special case."););
5722 /* if the right side is a literal then anything goes */
5723 if (AOP_TYPE (right) == AOP_LIT &&
5724 AOP_TYPE (left) != AOP_DIR)
5728 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5729 emitcode ("cjne", "a,%s,!tlabel",
5730 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5736 /* if the right side is in a register or in direct space or
5737 if the left is a pointer register & right is not */
5738 else if (AOP_TYPE (right) == AOP_REG ||
5739 AOP_TYPE (right) == AOP_DIR ||
5740 AOP_TYPE (right) == AOP_LIT ||
5741 AOP_TYPE (right) == AOP_IMMD ||
5742 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5743 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5747 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5748 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5749 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5750 emitcode ("jnz", "!tlabel", lbl->key + 100);
5752 emitcode ("cjne", "a,%s,!tlabel",
5753 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5760 /* right is a pointer reg need both a & b */
5763 MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5764 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5765 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5771 /*-----------------------------------------------------------------*/
5772 /* gencjne - compare and jump if not equal */
5773 /*-----------------------------------------------------------------*/
5775 gencjne (operand * left, operand * right, symbol * lbl)
5777 symbol *tlbl = newiTempLabel (NULL);
5779 D (emitcode (";", "gencjne");
5782 gencjneshort (left, right, lbl);
5784 emitcode ("mov", "a,%s", one);
5785 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5786 emitcode ("", "!tlabeldef", lbl->key + 100);
5787 emitcode ("clr", "a");
5788 emitcode ("", "!tlabeldef", tlbl->key + 100);
5791 /*-----------------------------------------------------------------*/
5792 /* genCmpEq - generates code for equal to */
5793 /*-----------------------------------------------------------------*/
5795 genCmpEq (iCode * ic, iCode * ifx)
5797 operand *left, *right, *result;
5799 D (emitcode (";", "genCmpEq ");
5803 AOP_SET_LOCALS (ic);
5805 /* if literal, literal on the right or
5806 if the right is in a pointer register and left
5808 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5809 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5811 operand *t = IC_RIGHT (ic);
5812 IC_RIGHT (ic) = IC_LEFT (ic);
5816 if (ifx && /* !AOP_SIZE(result) */
5817 OP_SYMBOL (result) &&
5818 OP_SYMBOL (result)->regType == REG_CND)
5821 /* if they are both bit variables */
5822 if (AOP_TYPE (left) == AOP_CRY &&
5823 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5825 if (AOP_TYPE (right) == AOP_LIT)
5827 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5830 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5831 emitcode ("cpl", "c");
5835 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5839 emitcode ("clr", "c");
5841 /* AOP_TYPE(right) == AOP_CRY */
5845 symbol *lbl = newiTempLabel (NULL);
5846 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5847 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5848 emitcode ("cpl", "c");
5849 emitcode ("", "!tlabeldef", (lbl->key + 100));
5851 /* if true label then we jump if condition
5853 tlbl = newiTempLabel (NULL);
5856 emitcode ("jnc", "!tlabel", tlbl->key + 100);
5857 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5861 emitcode ("jc", "!tlabel", tlbl->key + 100);
5862 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5864 emitcode ("", "!tlabeldef", tlbl->key + 100);
5868 tlbl = newiTempLabel (NULL);
5869 gencjneshort (left, right, tlbl);
5872 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5873 emitcode ("", "!tlabeldef", tlbl->key + 100);
5877 symbol *lbl = newiTempLabel (NULL);
5878 emitcode ("sjmp", "!tlabel", lbl->key + 100);
5879 emitcode ("", "!tlabeldef", tlbl->key + 100);
5880 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5881 emitcode ("", "!tlabeldef", lbl->key + 100);
5884 /* mark the icode as generated */
5887 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5888 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5892 /* if they are both bit variables */
5893 if (AOP_TYPE (left) == AOP_CRY &&
5894 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5896 if (AOP_TYPE (right) == AOP_LIT)
5898 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5901 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5902 emitcode ("cpl", "c");
5906 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5910 emitcode ("clr", "c");
5912 /* AOP_TYPE(right) == AOP_CRY */
5916 symbol *lbl = newiTempLabel (NULL);
5917 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5918 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5919 emitcode ("cpl", "c");
5920 emitcode ("", "!tlabeldef", (lbl->key + 100));
5923 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5924 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5926 aopOp (result, ic, TRUE, FALSE);
5929 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5936 genIfxJump (ifx, "c");
5939 /* if the result is used in an arithmetic operation
5940 then put the result in place */
5945 gencjne (left, right, newiTempLabel (NULL));
5947 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5948 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5950 aopOp (result, ic, TRUE, FALSE);
5952 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5954 aopPut (AOP (result), "a", 0);
5959 genIfxJump (ifx, "a");
5962 /* if the result is used in an arithmetic operation
5963 then put the result in place */
5964 if (AOP_TYPE (result) != AOP_CRY)
5966 /* leave the result in acc */
5970 freeAsmop (result, NULL, ic, TRUE);
5973 /*-----------------------------------------------------------------*/
5974 /* ifxForOp - returns the icode containing the ifx for operand */
5975 /*-----------------------------------------------------------------*/
5977 ifxForOp (operand * op, iCode * ic)
5979 /* if true symbol then needs to be assigned */
5980 if (IS_TRUE_SYMOP (op))
5983 /* if this has register type condition and
5984 the next instruction is ifx with the same operand
5985 and live to of the operand is upto the ifx only then */
5987 ic->next->op == IFX &&
5988 IC_COND (ic->next)->key == op->key &&
5989 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5994 /*-----------------------------------------------------------------*/
5995 /* hasInc - operand is incremented before any other use */
5996 /*-----------------------------------------------------------------*/
5998 hasInc (operand *op, iCode *ic, int osize)
6000 sym_link *type = operandType(op);
6001 sym_link *retype = getSpec (type);
6002 iCode *lic = ic->next;
6005 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6006 if (!IS_SYMOP(op)) return NULL;
6008 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6009 if (IS_AGGREGATE(type->next)) return NULL;
6010 if (osize != (isize = getSize(type->next))) return NULL;
6013 /* if operand of the form op = op + <sizeof *op> */
6014 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6015 isOperandEqual(IC_RESULT(lic),op) &&
6016 isOperandLiteral(IC_RIGHT(lic)) &&
6017 operandLitValue(IC_RIGHT(lic)) == isize) {
6020 /* if the operand used or deffed */
6021 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
6024 /* if GOTO or IFX */
6025 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6031 /*-----------------------------------------------------------------*/
6032 /* genAndOp - for && operation */
6033 /*-----------------------------------------------------------------*/
6035 genAndOp (iCode * ic)
6037 operand *left, *right, *result;
6040 D (emitcode (";", "genAndOp "););
6042 /* note here that && operations that are in an
6043 if statement are taken away by backPatchLabels
6044 only those used in arthmetic operations remain */
6046 AOP_SET_LOCALS (ic);
6048 /* if both are bit variables */
6049 if (AOP_TYPE (left) == AOP_CRY &&
6050 AOP_TYPE (right) == AOP_CRY)
6052 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6053 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6054 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6055 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6057 aopOp (result,ic,FALSE, FALSE);
6062 tlbl = newiTempLabel (NULL);
6064 emitcode ("jz", "!tlabel", tlbl->key + 100);
6066 emitcode ("", "!tlabeldef", tlbl->key + 100);
6067 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6068 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6070 aopOp (result,ic,FALSE, FALSE);
6073 freeAsmop (result, NULL, ic, TRUE);
6077 /*-----------------------------------------------------------------*/
6078 /* genOrOp - for || operation */
6079 /*-----------------------------------------------------------------*/
6081 genOrOp (iCode * ic)
6083 operand *left, *right, *result;
6086 D (emitcode (";", "genOrOp "););
6088 /* note here that || operations that are in an
6089 if statement are taken away by backPatchLabels
6090 only those used in arthmetic operations remain */
6092 AOP_SET_LOCALS (ic);
6094 /* if both are bit variables */
6095 if (AOP_TYPE (left) == AOP_CRY &&
6096 AOP_TYPE (right) == AOP_CRY)
6098 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6099 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6100 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6101 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6103 aopOp (result,ic,FALSE, FALSE);
6109 tlbl = newiTempLabel (NULL);
6111 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6113 emitcode ("", "!tlabeldef", tlbl->key + 100);
6114 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6115 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6117 aopOp (result,ic,FALSE, FALSE);
6122 freeAsmop (result, NULL, ic, TRUE);
6125 /*-----------------------------------------------------------------*/
6126 /* isLiteralBit - test if lit == 2^n */
6127 /*-----------------------------------------------------------------*/
6129 isLiteralBit (unsigned long lit)
6131 unsigned long pw[32] =
6132 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6133 0x100L, 0x200L, 0x400L, 0x800L,
6134 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6135 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6136 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6137 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6138 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6141 for (idx = 0; idx < 32; idx++)
6147 /*-----------------------------------------------------------------*/
6148 /* continueIfTrue - */
6149 /*-----------------------------------------------------------------*/
6151 continueIfTrue (iCode * ic)
6154 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6158 /*-----------------------------------------------------------------*/
6160 /*-----------------------------------------------------------------*/
6162 jumpIfTrue (iCode * ic)
6165 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6169 /*-----------------------------------------------------------------*/
6170 /* jmpTrueOrFalse - */
6171 /*-----------------------------------------------------------------*/
6173 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6175 // ugly but optimized by peephole
6178 symbol *nlbl = newiTempLabel (NULL);
6179 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6180 emitcode ("", "!tlabeldef", tlbl->key + 100);
6181 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6182 emitcode ("", "!tlabeldef", nlbl->key + 100);
6186 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6187 emitcode ("", "!tlabeldef", tlbl->key + 100);
6192 // Generate code to perform a bit-wise logic operation
6193 // on two operands in far space (assumed to already have been
6194 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6195 // in far space. This requires pushing the result on the stack
6196 // then popping it into the result.
6198 genFarFarLogicOp(iCode *ic, char *logicOp)
6200 int size, resultSize, compSize;
6204 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6205 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
6206 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6208 _startLazyDPSEvaluation();
6209 for (size = compSize; (size--); offset++)
6211 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6212 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6213 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6215 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6216 emitcode ("push", "acc");
6218 _endLazyDPSEvaluation();
6220 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6221 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6222 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6224 resultSize = AOP_SIZE(IC_RESULT(ic));
6226 ADJUST_PUSHED_RESULT(compSize, resultSize);
6228 _startLazyDPSEvaluation();
6231 emitcode ("pop", "acc");
6232 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6234 _endLazyDPSEvaluation();
6235 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6239 /*-----------------------------------------------------------------*/
6240 /* genAnd - code for and */
6241 /*-----------------------------------------------------------------*/
6243 genAnd (iCode * ic, iCode * ifx)
6245 operand *left, *right, *result;
6246 int size, offset = 0;
6247 unsigned long lit = 0L;
6252 D (emitcode (";", "genAnd "););
6254 AOP_OP_3_NOFATAL (ic, pushResult);
6255 AOP_SET_LOCALS (ic);
6259 genFarFarLogicOp(ic, "anl");
6264 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6266 AOP_TYPE (left), AOP_TYPE (right));
6267 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6269 AOP_SIZE (left), AOP_SIZE (right));
6272 /* if left is a literal & right is not then exchange them */
6273 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6274 #ifdef LOGIC_OPS_BROKEN
6275 || AOP_NEEDSACC (left)
6279 operand *tmp = right;
6284 /* if result = right then exchange them */
6285 if (sameRegs (AOP (result), AOP (right)))
6287 operand *tmp = right;
6292 /* if right is bit then exchange them */
6293 if (AOP_TYPE (right) == AOP_CRY &&
6294 AOP_TYPE (left) != AOP_CRY)
6296 operand *tmp = right;
6300 if (AOP_TYPE (right) == AOP_LIT)
6301 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6303 size = AOP_SIZE (result);
6306 // result = bit & yy;
6307 if (AOP_TYPE (left) == AOP_CRY)
6309 // c = bit & literal;
6310 if (AOP_TYPE (right) == AOP_LIT)
6314 if (size && sameRegs (AOP (result), AOP (left)))
6317 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6322 if (size && (AOP_TYPE (result) == AOP_CRY))
6324 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6327 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6332 emitcode ("clr", "c");
6337 if (AOP_TYPE (right) == AOP_CRY)
6340 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6341 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6346 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6348 emitcode ("rrc", "a");
6349 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6357 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6358 genIfxJump (ifx, "c");
6362 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6363 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6364 if ((AOP_TYPE (right) == AOP_LIT) &&
6365 (AOP_TYPE (result) == AOP_CRY) &&
6366 (AOP_TYPE (left) != AOP_CRY))
6368 int posbit = isLiteralBit (lit);
6373 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6376 emitcode ("mov", "c,acc.%d", posbit & 0x07);
6382 SNPRINTF (buff, sizeof(buff),
6383 "acc.%d", posbit & 0x07);
6384 genIfxJump (ifx, buff);
6388 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6395 symbol *tlbl = newiTempLabel (NULL);
6396 int sizel = AOP_SIZE (left);
6398 emitcode ("setb", "c");
6401 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6403 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6405 if ((posbit = isLiteralBit (bytelit)) != 0)
6406 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6409 if (bytelit != 0x0FFL)
6410 emitcode ("anl", "a,%s",
6411 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6412 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6417 // bit = left & literal
6420 emitcode ("clr", "c");
6421 emitcode ("", "!tlabeldef", tlbl->key + 100);
6423 // if(left & literal)
6427 jmpTrueOrFalse (ifx, tlbl);
6429 emitcode ("", "!tlabeldef", tlbl->key + 100);
6437 /* if left is same as result */
6438 if (sameRegs (AOP (result), AOP (left)))
6440 for (; size--; offset++)
6442 if (AOP_TYPE (right) == AOP_LIT)
6444 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6446 else if (bytelit == 0)
6447 aopPut (AOP (result), zero, offset);
6448 else if (IS_AOP_PREG (result))
6450 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6451 emitcode ("anl", "a,%s",
6452 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6453 aopPut (AOP (result), "a", offset);
6456 emitcode ("anl", "%s,%s",
6457 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6458 aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6462 if (AOP_TYPE (left) == AOP_ACC)
6463 emitcode ("anl", "a,%s",
6464 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6467 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6468 if (IS_AOP_PREG (result))
6470 emitcode ("anl", "a,%s",
6471 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6472 aopPut (AOP (result), "a", offset);
6475 emitcode ("anl", "%s,a",
6476 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6483 // left & result in different registers
6484 if (AOP_TYPE (result) == AOP_CRY)
6487 // if(size), result in bit
6488 // if(!size && ifx), conditional oper: if(left & right)
6489 symbol *tlbl = newiTempLabel (NULL);
6490 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6492 emitcode ("setb", "c");
6495 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6496 emitcode ("anl", "a,%s",
6497 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6499 if (AOP_TYPE(left)==AOP_ACC) {
6500 emitcode("mov", "b,a");
6501 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6502 emitcode("anl", "a,b");
6504 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6505 emitcode ("anl", "a,%s",
6506 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6509 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6515 emitcode ("", "!tlabeldef", tlbl->key + 100);
6519 jmpTrueOrFalse (ifx, tlbl);
6521 emitcode ("", "!tlabeldef", tlbl->key + 100);
6525 for (; (size--); offset++)
6528 // result = left & right
6529 if (AOP_TYPE (right) == AOP_LIT)
6531 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6533 aopPut (AOP (result),
6534 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6538 else if (bytelit == 0)
6540 aopPut (AOP (result), zero, offset);
6543 D (emitcode (";", "better literal AND."););
6544 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6545 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6546 FALSE, FALSE, DP2_RESULT_REG));
6551 // faster than result <- left, anl result,right
6552 // and better if result is SFR
6553 if (AOP_TYPE (left) == AOP_ACC)
6555 emitcode ("anl", "a,%s",
6556 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6560 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6561 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6563 emitcode("mov", "b,a");
6567 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6568 emitcode ("anl", "a,%s", rOp);
6571 aopPut (AOP (result), "a", offset);
6577 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6578 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6579 freeAsmop (result, NULL, ic, TRUE);
6583 /*-----------------------------------------------------------------*/
6584 /* genOr - code for or */
6585 /*-----------------------------------------------------------------*/
6587 genOr (iCode * ic, iCode * ifx)
6589 operand *left, *right, *result;
6590 int size, offset = 0;
6591 unsigned long lit = 0L;
6594 D (emitcode (";", "genOr "););
6596 AOP_OP_3_NOFATAL (ic, pushResult);
6597 AOP_SET_LOCALS (ic);
6601 genFarFarLogicOp(ic, "orl");
6607 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6609 AOP_TYPE (left), AOP_TYPE (right));
6610 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6612 AOP_SIZE (left), AOP_SIZE (right));
6615 /* if left is a literal & right is not then exchange them */
6616 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6617 #ifdef LOGIC_OPS_BROKEN
6618 || AOP_NEEDSACC (left) // I think this is a net loss now.
6622 operand *tmp = right;
6627 /* if result = right then exchange them */
6628 if (sameRegs (AOP (result), AOP (right)))
6630 operand *tmp = right;
6635 /* if right is bit then exchange them */
6636 if (AOP_TYPE (right) == AOP_CRY &&
6637 AOP_TYPE (left) != AOP_CRY)
6639 operand *tmp = right;
6643 if (AOP_TYPE (right) == AOP_LIT)
6644 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6646 size = AOP_SIZE (result);
6650 if (AOP_TYPE (left) == AOP_CRY)
6652 if (AOP_TYPE (right) == AOP_LIT)
6654 // c = bit & literal;
6657 // lit != 0 => result = 1
6658 if (AOP_TYPE (result) == AOP_CRY)
6661 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6663 continueIfTrue (ifx);
6666 emitcode ("setb", "c");
6670 // lit == 0 => result = left
6671 if (size && sameRegs (AOP (result), AOP (left)))
6673 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6678 if (AOP_TYPE (right) == AOP_CRY)
6681 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6682 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6687 symbol *tlbl = newiTempLabel (NULL);
6688 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6689 emitcode ("setb", "c");
6690 emitcode ("jb", "%s,!tlabel",
6691 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6693 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6694 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6696 jmpTrueOrFalse (ifx, tlbl);
6702 emitcode ("", "!tlabeldef", tlbl->key + 100);
6711 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6712 genIfxJump (ifx, "c");
6716 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6717 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6718 if ((AOP_TYPE (right) == AOP_LIT) &&
6719 (AOP_TYPE (result) == AOP_CRY) &&
6720 (AOP_TYPE (left) != AOP_CRY))
6726 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6728 continueIfTrue (ifx);
6733 // lit = 0, result = boolean(left)
6735 emitcode ("setb", "c");
6739 symbol *tlbl = newiTempLabel (NULL);
6740 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6742 emitcode ("", "!tlabeldef", tlbl->key + 100);
6746 genIfxJump (ifx, "a");
6754 /* if left is same as result */
6755 if (sameRegs (AOP (result), AOP (left)))
6757 for (; size--; offset++)
6759 if (AOP_TYPE (right) == AOP_LIT)
6761 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6767 if (IS_AOP_PREG (left))
6769 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6770 emitcode ("orl", "a,%s",
6771 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6772 aopPut (AOP (result), "a", offset);
6776 emitcode ("orl", "%s,%s",
6777 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6778 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6784 if (AOP_TYPE (left) == AOP_ACC)
6786 emitcode ("orl", "a,%s",
6787 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6791 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6792 if (IS_AOP_PREG (left))
6794 emitcode ("orl", "a,%s",
6795 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6796 aopPut (AOP (result), "a", offset);
6800 emitcode ("orl", "%s,a",
6801 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6809 // left & result in different registers
6810 if (AOP_TYPE (result) == AOP_CRY)
6813 // if(size), result in bit
6814 // if(!size && ifx), conditional oper: if(left | right)
6815 symbol *tlbl = newiTempLabel (NULL);
6816 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6818 emitcode ("setb", "c");
6821 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6822 emitcode ("orl", "a,%s",
6823 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6825 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6826 emitcode ("orl", "a,%s",
6827 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6829 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6835 emitcode ("", "!tlabeldef", tlbl->key + 100);
6839 jmpTrueOrFalse (ifx, tlbl);
6841 emitcode ("", "!tlabeldef", tlbl->key + 100);
6845 _startLazyDPSEvaluation();
6846 for (; (size--); offset++)
6849 // result = left & right
6850 if (AOP_TYPE (right) == AOP_LIT)
6852 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6854 aopPut (AOP (result),
6855 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6859 D (emitcode (";", "better literal OR."););
6860 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6861 emitcode ("orl", "a, %s",
6862 aopGet (AOP (right), offset,
6863 FALSE, FALSE, DP2_RESULT_REG));
6868 // faster than result <- left, anl result,right
6869 // and better if result is SFR
6870 if (AOP_TYPE (left) == AOP_ACC)
6872 emitcode ("orl", "a,%s",
6873 aopGet (AOP (right), offset,
6874 FALSE, FALSE, DP2_RESULT_REG));
6878 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6880 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6882 emitcode("mov", "b,a");
6886 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6887 emitcode ("orl", "a,%s", rOp);
6890 aopPut (AOP (result), "a", offset);
6892 _endLazyDPSEvaluation();
6897 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6898 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6899 freeAsmop (result, NULL, ic, TRUE);
6902 /*-----------------------------------------------------------------*/
6903 /* genXor - code for xclusive or */
6904 /*-----------------------------------------------------------------*/
6906 genXor (iCode * ic, iCode * ifx)
6908 operand *left, *right, *result;
6909 int size, offset = 0;
6910 unsigned long lit = 0L;
6913 D (emitcode (";", "genXor "););
6915 AOP_OP_3_NOFATAL (ic, pushResult);
6916 AOP_SET_LOCALS (ic);
6920 genFarFarLogicOp(ic, "xrl");
6925 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6927 AOP_TYPE (left), AOP_TYPE (right));
6928 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6930 AOP_SIZE (left), AOP_SIZE (right));
6933 /* if left is a literal & right is not ||
6934 if left needs acc & right does not */
6935 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6936 #ifdef LOGIC_OPS_BROKEN
6937 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6941 operand *tmp = right;
6946 /* if result = right then exchange them */
6947 if (sameRegs (AOP (result), AOP (right)))
6949 operand *tmp = right;
6954 /* if right is bit then exchange them */
6955 if (AOP_TYPE (right) == AOP_CRY &&
6956 AOP_TYPE (left) != AOP_CRY)
6958 operand *tmp = right;
6962 if (AOP_TYPE (right) == AOP_LIT)
6963 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6965 size = AOP_SIZE (result);
6969 if (AOP_TYPE (left) == AOP_CRY)
6971 if (AOP_TYPE (right) == AOP_LIT)
6973 // c = bit & literal;
6976 // lit>>1 != 0 => result = 1
6977 if (AOP_TYPE (result) == AOP_CRY)
6980 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6982 continueIfTrue (ifx);
6985 emitcode ("setb", "c");
6992 // lit == 0, result = left
6993 if (size && sameRegs (AOP (result), AOP (left)))
6995 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6999 // lit == 1, result = not(left)
7000 if (size && sameRegs (AOP (result), AOP (left)))
7002 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7007 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7008 emitcode ("cpl", "c");
7017 symbol *tlbl = newiTempLabel (NULL);
7018 if (AOP_TYPE (right) == AOP_CRY)
7021 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7025 int sizer = AOP_SIZE (right);
7027 // if val>>1 != 0, result = 1
7028 emitcode ("setb", "c");
7031 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
7033 // test the msb of the lsb
7034 emitcode ("anl", "a,#!constbyte",0xfe);
7035 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7039 emitcode ("rrc", "a");
7041 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7042 emitcode ("cpl", "c");
7043 emitcode ("", "!tlabeldef", (tlbl->key + 100));
7050 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7051 genIfxJump (ifx, "c");
7055 if (sameRegs (AOP (result), AOP (left)))
7057 /* if left is same as result */
7058 for (; size--; offset++)
7060 if (AOP_TYPE (right) == AOP_LIT)
7062 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7064 else if (IS_AOP_PREG (left))
7066 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7067 emitcode ("xrl", "a,%s",
7068 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7069 aopPut (AOP (result), "a", offset);
7072 emitcode ("xrl", "%s,%s",
7073 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7074 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7078 if (AOP_TYPE (left) == AOP_ACC)
7079 emitcode ("xrl", "a,%s",
7080 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7083 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7084 if (IS_AOP_PREG (left))
7086 emitcode ("xrl", "a,%s",
7087 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7088 aopPut (AOP (result), "a", offset);
7091 emitcode ("xrl", "%s,a",
7092 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7099 // left & result in different registers
7100 if (AOP_TYPE (result) == AOP_CRY)
7103 // if(size), result in bit
7104 // if(!size && ifx), conditional oper: if(left ^ right)
7105 symbol *tlbl = newiTempLabel (NULL);
7106 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7109 emitcode ("setb", "c");
7112 if ((AOP_TYPE (right) == AOP_LIT) &&
7113 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7115 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7119 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7120 emitcode ("xrl", "a,%s",
7121 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7123 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7124 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7126 emitcode("mov", "b,a");
7130 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7131 emitcode ("xrl", "a,%s", rOp);
7134 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7140 emitcode ("", "!tlabeldef", tlbl->key + 100);
7144 jmpTrueOrFalse (ifx, tlbl);
7148 for (; (size--); offset++)
7151 // result = left & right
7152 if (AOP_TYPE (right) == AOP_LIT)
7154 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7156 aopPut (AOP (result),
7157 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7161 D (emitcode (";", "better literal XOR."););
7162 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7163 emitcode ("xrl", "a, %s",
7164 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7168 // faster than result <- left, anl result,right
7169 // and better if result is SFR
7170 if (AOP_TYPE (left) == AOP_ACC)
7172 emitcode ("xrl", "a,%s",
7173 aopGet (AOP (right), offset,
7174 FALSE, FALSE, DP2_RESULT_REG));
7178 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7179 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7181 emitcode("mov", "b,a");
7185 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7186 emitcode ("xrl", "a,%s", rOp);
7189 aopPut (AOP (result), "a", offset);
7196 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7197 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7198 freeAsmop (result, NULL, ic, TRUE);
7201 /*-----------------------------------------------------------------*/
7202 /* genInline - write the inline code out */
7203 /*-----------------------------------------------------------------*/
7205 genInline (iCode * ic)
7207 char *buffer, *bp, *bp1;
7209 D (emitcode (";", "genInline "); );
7211 _G.inLine += (!options.asmpeep);
7213 buffer = Safe_strdup(IC_INLINE(ic));
7217 /* emit each line as a code */
7242 /* emitcode("",buffer); */
7243 _G.inLine -= (!options.asmpeep);
7246 /*-----------------------------------------------------------------*/
7247 /* genRRC - rotate right with carry */
7248 /*-----------------------------------------------------------------*/
7252 operand *left, *result;
7255 D (emitcode (";", "genRRC "););
7257 /* rotate right with carry */
7258 left = IC_LEFT (ic);
7259 result = IC_RESULT (ic);
7260 aopOp (left, ic, FALSE, FALSE);
7261 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7263 /* move it to the result */
7264 size = AOP_SIZE (result);
7268 _startLazyDPSEvaluation ();
7271 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7272 emitcode ("rrc", "a");
7273 if (AOP_SIZE (result) > 1)
7274 aopPut (AOP (result), "a", offset--);
7276 _endLazyDPSEvaluation ();
7278 /* now we need to put the carry into the
7279 highest order byte of the result */
7280 if (AOP_SIZE (result) > 1)
7282 MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7284 emitcode ("mov", "acc.7,c");
7285 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7286 freeAsmop (left, NULL, ic, TRUE);
7287 freeAsmop (result, NULL, ic, TRUE);
7290 /*-----------------------------------------------------------------*/
7291 /* genRLC - generate code for rotate left with carry */
7292 /*-----------------------------------------------------------------*/
7296 operand *left, *result;
7300 D (emitcode (";", "genRLC "););
7302 /* rotate right with carry */
7303 left = IC_LEFT (ic);
7304 result = IC_RESULT (ic);
7305 aopOp (left, ic, FALSE, FALSE);
7306 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7308 /* move it to the result */
7309 size = AOP_SIZE (result);
7313 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7315 emitcode ("add", "a,acc");
7316 if (AOP_SIZE (result) > 1)
7318 aopPut (AOP (result), "a", offset++);
7321 _startLazyDPSEvaluation ();
7324 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7326 emitcode ("rlc", "a");
7327 if (AOP_SIZE (result) > 1)
7328 aopPut (AOP (result), "a", offset++);
7330 _endLazyDPSEvaluation ();
7332 /* now we need to put the carry into the
7333 highest order byte of the result */
7334 if (AOP_SIZE (result) > 1)
7336 l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7339 emitcode ("mov", "acc.0,c");
7340 aopPut (AOP (result), "a", 0);
7341 freeAsmop (left, NULL, ic, TRUE);
7342 freeAsmop (result, NULL, ic, TRUE);
7345 /*-----------------------------------------------------------------*/
7346 /* genGetHbit - generates code get highest order bit */
7347 /*-----------------------------------------------------------------*/
7349 genGetHbit (iCode * ic)
7351 operand *left, *result;
7352 left = IC_LEFT (ic);
7353 result = IC_RESULT (ic);
7354 aopOp (left, ic, FALSE, FALSE);
7355 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7357 D (emitcode (";", "genGetHbit "););
7359 /* get the highest order byte into a */
7360 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7361 if (AOP_TYPE (result) == AOP_CRY)
7363 emitcode ("rlc", "a");
7368 emitcode ("rl", "a");
7369 emitcode ("anl", "a,#1");
7374 freeAsmop (left, NULL, ic, TRUE);
7375 freeAsmop (result, NULL, ic, TRUE);
7378 /*-----------------------------------------------------------------*/
7379 /* genSwap - generates code to swap nibbles or bytes */
7380 /*-----------------------------------------------------------------*/
7382 genSwap (iCode * ic)
7384 operand *left, *result;
7386 D(emitcode ("; genSwap",""));
7388 left = IC_LEFT (ic);
7389 result = IC_RESULT (ic);
7390 aopOp (left, ic, FALSE, FALSE);
7391 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7393 _startLazyDPSEvaluation ();
7394 switch (AOP_SIZE (left))
7396 case 1: /* swap nibbles in byte */
7397 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7398 emitcode ("swap", "a");
7399 aopPut (AOP (result), "a", 0);
7401 case 2: /* swap bytes in word */
7402 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7404 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7405 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7406 aopPut (AOP (result), "a", 1);
7408 else if (operandsEqu (left, result))
7411 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7412 if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
7414 emitcode ("mov", "b,a");
7418 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7419 aopPut (AOP (result), reg, 1);
7424 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7425 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE, NULL), 1);
7429 wassertl(FALSE, "unsupported SWAP operand size");
7431 _endLazyDPSEvaluation ();
7433 freeAsmop (left, NULL, ic, TRUE);
7434 freeAsmop (result, NULL, ic, TRUE);
7437 /*-----------------------------------------------------------------*/
7438 /* AccRol - rotate left accumulator by known count */
7439 /*-----------------------------------------------------------------*/
7441 AccRol (int shCount)
7443 shCount &= 0x0007; // shCount : 0..7
7450 emitcode ("rl", "a");
7453 emitcode ("rl", "a");
7454 emitcode ("rl", "a");
7457 emitcode ("swap", "a");
7458 emitcode ("rr", "a");
7461 emitcode ("swap", "a");
7464 emitcode ("swap", "a");
7465 emitcode ("rl", "a");
7468 emitcode ("rr", "a");
7469 emitcode ("rr", "a");
7472 emitcode ("rr", "a");
7477 /*-----------------------------------------------------------------*/
7478 /* AccLsh - left shift accumulator by known count */
7479 /*-----------------------------------------------------------------*/
7481 AccLsh (int shCount)
7486 emitcode ("add", "a,acc");
7487 else if (shCount == 2)
7489 emitcode ("add", "a,acc");
7490 emitcode ("add", "a,acc");
7494 /* rotate left accumulator */
7496 /* and kill the lower order bits */
7497 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7502 /*-----------------------------------------------------------------*/
7503 /* AccRsh - right shift accumulator by known count */
7504 /*-----------------------------------------------------------------*/
7506 AccRsh (int shCount)
7513 emitcode ("rrc", "a");
7517 /* rotate right accumulator */
7518 AccRol (8 - shCount);
7519 /* and kill the higher order bits */
7520 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7525 #ifdef BETTER_LITERAL_SHIFT
7526 /*-----------------------------------------------------------------*/
7527 /* AccSRsh - signed right shift accumulator by known count */
7528 /*-----------------------------------------------------------------*/
7530 AccSRsh (int shCount)
7537 emitcode ("mov", "c,acc.7");
7538 emitcode ("rrc", "a");
7540 else if (shCount == 2)
7542 emitcode ("mov", "c,acc.7");
7543 emitcode ("rrc", "a");
7544 emitcode ("mov", "c,acc.7");
7545 emitcode ("rrc", "a");
7549 tlbl = newiTempLabel (NULL);
7550 /* rotate right accumulator */
7551 AccRol (8 - shCount);
7552 /* and kill the higher order bits */
7553 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7554 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7555 emitcode ("orl", "a,#!constbyte",
7556 (unsigned char) ~SRMask[shCount]);
7557 emitcode ("", "!tlabeldef", tlbl->key + 100);
7563 #ifdef BETTER_LITERAL_SHIFT
7564 /*-----------------------------------------------------------------*/
7565 /* shiftR1Left2Result - shift right one byte from left to result */
7566 /*-----------------------------------------------------------------*/
7568 shiftR1Left2Result (operand * left, int offl,
7569 operand * result, int offr,
7570 int shCount, int sign)
7572 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7573 /* shift right accumulator */
7578 aopPut (AOP (result), "a", offr);
7582 #ifdef BETTER_LITERAL_SHIFT
7583 /*-----------------------------------------------------------------*/
7584 /* shiftL1Left2Result - shift left one byte from left to result */
7585 /*-----------------------------------------------------------------*/
7587 shiftL1Left2Result (operand * left, int offl,
7588 operand * result, int offr, int shCount)
7590 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7591 /* shift left accumulator */
7593 aopPut (AOP (result), "a", offr);
7597 #ifdef BETTER_LITERAL_SHIFT
7598 /*-----------------------------------------------------------------*/
7599 /* movLeft2Result - move byte from left to result */
7600 /*-----------------------------------------------------------------*/
7602 movLeft2Result (operand * left, int offl,
7603 operand * result, int offr, int sign)
7606 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7608 l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7610 if (*l == '@' && (IS_AOP_PREG (result)))
7612 emitcode ("mov", "a,%s", l);
7613 aopPut (AOP (result), "a", offr);
7619 aopPut (AOP (result), l, offr);
7623 /* MSB sign in acc.7 ! */
7624 if (getDataSize (left) == offl + 1)
7626 emitcode ("mov", "a,%s", l);
7627 aopPut (AOP (result), "a", offr);
7635 #ifdef BETTER_LITERAL_SHIFT
7636 /*-----------------------------------------------------------------*/
7637 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7638 /*-----------------------------------------------------------------*/
7642 emitcode ("rrc", "a");
7643 emitcode ("xch", "a,%s", x);
7644 emitcode ("rrc", "a");
7645 emitcode ("xch", "a,%s", x);
7649 #ifdef BETTER_LITERAL_SHIFT
7651 /*-----------------------------------------------------------------*/
7652 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7653 /*-----------------------------------------------------------------*/
7657 emitcode ("xch", "a,%s", x);
7658 emitcode ("rlc", "a");
7659 emitcode ("xch", "a,%s", x);
7660 emitcode ("rlc", "a");
7664 #ifdef BETTER_LITERAL_SHIFT
7665 /*-----------------------------------------------------------------*/
7666 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7667 /*-----------------------------------------------------------------*/
7671 emitcode ("xch", "a,%s", x);
7672 emitcode ("add", "a,acc");
7673 emitcode ("xch", "a,%s", x);
7674 emitcode ("rlc", "a");
7678 #ifdef BETTER_LITERAL_SHIFT
7679 /*-----------------------------------------------------------------*/
7680 /* AccAXLsh - left shift a:x by known count (0..7) */
7681 /*-----------------------------------------------------------------*/
7683 AccAXLsh (char *x, int shCount)
7698 case 5: // AAAAABBB:CCCCCDDD
7700 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7702 emitcode ("anl", "a,#!constbyte",
7703 SLMask[shCount]); // BBB00000:CCCCCDDD
7705 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7707 AccRol (shCount); // DDDCCCCC:BBB00000
7709 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7711 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7713 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7715 emitcode ("anl", "a,#!constbyte",
7716 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7718 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7720 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7723 case 6: // AAAAAABB:CCCCCCDD
7724 emitcode ("anl", "a,#!constbyte",
7725 SRMask[shCount]); // 000000BB:CCCCCCDD
7726 emitcode ("mov", "c,acc.0"); // c = B
7727 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7729 AccAXRrl1 (x); // BCCCCCCD:D000000B
7730 AccAXRrl1 (x); // BBCCCCCC:DD000000
7732 emitcode("rrc","a");
7733 emitcode("xch","a,%s", x);
7734 emitcode("rrc","a");
7735 emitcode("mov","c,acc.0"); //<< get correct bit
7736 emitcode("xch","a,%s", x);
7738 emitcode("rrc","a");
7739 emitcode("xch","a,%s", x);
7740 emitcode("rrc","a");
7741 emitcode("xch","a,%s", x);
7744 case 7: // a:x <<= 7
7746 emitcode ("anl", "a,#!constbyte",
7747 SRMask[shCount]); // 0000000B:CCCCCCCD
7749 emitcode ("mov", "c,acc.0"); // c = B
7751 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7753 AccAXRrl1 (x); // BCCCCCCC:D0000000
7762 #ifdef BETTER_LITERAL_SHIFT
7764 /*-----------------------------------------------------------------*/
7765 /* AccAXRsh - right shift a:x known count (0..7) */
7766 /*-----------------------------------------------------------------*/
7768 AccAXRsh (char *x, int shCount)
7776 AccAXRrl1 (x); // 0->a:x
7781 AccAXRrl1 (x); // 0->a:x
7784 AccAXRrl1 (x); // 0->a:x
7789 case 5: // AAAAABBB:CCCCCDDD = a:x
7791 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7793 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7795 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7797 emitcode ("anl", "a,#!constbyte",
7798 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7800 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7802 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7804 emitcode ("anl", "a,#!constbyte",
7805 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7807 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7809 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7811 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7814 case 6: // AABBBBBB:CCDDDDDD
7816 emitcode ("mov", "c,acc.7");
7817 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7819 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7821 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7823 emitcode ("anl", "a,#!constbyte",
7824 SRMask[shCount]); // 000000AA:BBBBBBCC
7827 case 7: // ABBBBBBB:CDDDDDDD
7829 emitcode ("mov", "c,acc.7"); // c = A
7831 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7833 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7835 emitcode ("anl", "a,#!constbyte",
7836 SRMask[shCount]); // 0000000A:BBBBBBBC
7845 #ifdef BETTER_LITERAL_SHIFT
7846 /*-----------------------------------------------------------------*/
7847 /* AccAXRshS - right shift signed a:x known count (0..7) */
7848 /*-----------------------------------------------------------------*/
7850 AccAXRshS (char *x, int shCount)
7858 emitcode ("mov", "c,acc.7");
7859 AccAXRrl1 (x); // s->a:x
7863 emitcode ("mov", "c,acc.7");
7864 AccAXRrl1 (x); // s->a:x
7866 emitcode ("mov", "c,acc.7");
7867 AccAXRrl1 (x); // s->a:x
7872 case 5: // AAAAABBB:CCCCCDDD = a:x
7874 tlbl = newiTempLabel (NULL);
7875 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7877 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7879 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7881 emitcode ("anl", "a,#!constbyte",
7882 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7884 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7886 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7888 emitcode ("anl", "a,#!constbyte",
7889 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7891 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7893 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7895 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7897 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7898 emitcode ("orl", "a,#!constbyte",
7899 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7901 emitcode ("", "!tlabeldef", tlbl->key + 100);
7902 break; // SSSSAAAA:BBBCCCCC
7904 case 6: // AABBBBBB:CCDDDDDD
7906 tlbl = newiTempLabel (NULL);
7907 emitcode ("mov", "c,acc.7");
7908 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7910 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7912 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7914 emitcode ("anl", "a,#!constbyte",
7915 SRMask[shCount]); // 000000AA:BBBBBBCC
7917 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7918 emitcode ("orl", "a,#!constbyte",
7919 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7921 emitcode ("", "!tlabeldef", tlbl->key + 100);
7923 case 7: // ABBBBBBB:CDDDDDDD
7925 tlbl = newiTempLabel (NULL);
7926 emitcode ("mov", "c,acc.7"); // c = A
7928 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7930 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7932 emitcode ("anl", "a,#!constbyte",
7933 SRMask[shCount]); // 0000000A:BBBBBBBC
7935 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7936 emitcode ("orl", "a,#!constbyte",
7937 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7939 emitcode ("", "!tlabeldef", tlbl->key + 100);
7947 #ifdef BETTER_LITERAL_SHIFT
7949 _loadLeftIntoAx(char **lsb,
7955 // Get the initial value from left into a pair of registers.
7956 // MSB must be in A, LSB can be any register.
7958 // If the result is held in registers, it is an optimization
7959 // if the LSB can be held in the register which will hold the,
7960 // result LSB since this saves us from having to copy it into
7961 // the result following AccAXLsh.
7963 // If the result is addressed indirectly, this is not a gain.
7964 if (AOP_NEEDSACC(result))
7968 _startLazyDPSEvaluation();
7969 if (AOP_TYPE(left) == AOP_DPTR2)
7972 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7973 // get LSB in DP2_RESULT_REG.
7974 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7975 assert(!strcmp(leftByte, DP2_RESULT_REG));
7979 // get LSB into DP2_RESULT_REG
7980 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7981 if (strcmp(leftByte, DP2_RESULT_REG))
7984 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7987 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7988 assert(strcmp(leftByte, DP2_RESULT_REG));
7991 _endLazyDPSEvaluation();
7992 *lsb = DP2_RESULT_REG;
7996 if (sameRegs (AOP (result), AOP (left)) &&
7997 ((offl + MSB16) == offr))
7999 /* don't crash result[offr] */
8000 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
8001 emitcode ("xch", "a,%s",
8002 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
8006 movLeft2Result (left, offl, result, offr, 0);
8007 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
8009 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
8010 assert(strcmp(*lsb,"a"));
8015 _storeAxResults(char *lsb,
8019 _startLazyDPSEvaluation();
8020 if (AOP_NEEDSACC(result))
8022 /* We have to explicitly update the result LSB.
8024 emitcode("xch","a,%s", lsb);
8025 aopPut(AOP(result), "a", offr);
8026 emitcode("mov","a,%s", lsb);
8028 if (getDataSize (result) > 1)
8030 aopPut (AOP (result), "a", offr + MSB16);
8032 _endLazyDPSEvaluation();
8035 /*-----------------------------------------------------------------*/
8036 /* shiftL2Left2Result - shift left two bytes from left to result */
8037 /*-----------------------------------------------------------------*/
8039 shiftL2Left2Result (operand * left, int offl,
8040 operand * result, int offr, int shCount)
8044 _loadLeftIntoAx(&lsb, left, result, offl, offr);
8046 AccAXLsh (lsb, shCount);
8048 _storeAxResults(lsb, result, offr);
8052 #ifdef BETTER_LITERAL_SHIFT
8053 /*-----------------------------------------------------------------*/
8054 /* shiftR2Left2Result - shift right two bytes from left to result */
8055 /*-----------------------------------------------------------------*/
8057 shiftR2Left2Result (operand * left, int offl,
8058 operand * result, int offr,
8059 int shCount, int sign)
8063 _loadLeftIntoAx(&lsb, left, result, offl, offr);
8065 /* a:x >> shCount (x = lsb(result)) */
8068 AccAXRshS(lsb, shCount);
8072 AccAXRsh(lsb, shCount);
8075 _storeAxResults(lsb, result, offr);
8079 /*-----------------------------------------------------------------*/
8080 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8081 /*-----------------------------------------------------------------*/
8083 shiftLLeftOrResult (operand * left, int offl,
8084 operand * result, int offr, int shCount)
8086 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8087 /* shift left accumulator */
8089 /* or with result */
8090 emitcode ("orl", "a,%s",
8091 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8092 /* back to result */
8093 aopPut (AOP (result), "a", offr);
8098 /*-----------------------------------------------------------------*/
8099 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8100 /*-----------------------------------------------------------------*/
8102 shiftRLeftOrResult (operand * left, int offl,
8103 operand * result, int offr, int shCount)
8105 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8106 /* shift right accumulator */
8108 /* or with result */
8109 emitcode ("orl", "a,%s",
8110 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8111 /* back to result */
8112 aopPut (AOP (result), "a", offr);
8116 #ifdef BETTER_LITERAL_SHIFT
8117 /*-----------------------------------------------------------------*/
8118 /* genlshOne - left shift a one byte quantity by known count */
8119 /*-----------------------------------------------------------------*/
8121 genlshOne (operand * result, operand * left, int shCount)
8123 D (emitcode (";", "genlshOne "););
8124 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8128 #ifdef BETTER_LITERAL_SHIFT
8129 /*-----------------------------------------------------------------*/
8130 /* genlshTwo - left shift two bytes by known amount != 0 */
8131 /*-----------------------------------------------------------------*/
8133 genlshTwo (operand * result, operand * left, int shCount)
8137 D (emitcode (";", "genlshTwo "););
8139 size = getDataSize (result);
8141 /* if shCount >= 8 */
8146 _startLazyDPSEvaluation();
8152 _endLazyDPSEvaluation();
8153 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8154 aopPut (AOP (result), zero, LSB);
8158 movLeft2Result (left, LSB, result, MSB16, 0);
8159 aopPut (AOP (result), zero, LSB);
8160 _endLazyDPSEvaluation();
8165 aopPut (AOP (result), zero, LSB);
8166 _endLazyDPSEvaluation();
8170 /* 1 <= shCount <= 7 */
8175 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8179 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8187 /*-----------------------------------------------------------------*/
8188 /* shiftLLong - shift left one long from left to result */
8189 /* offl = LSB or MSB16 */
8190 /*-----------------------------------------------------------------*/
8192 shiftLLong (operand * left, operand * result, int offr)
8195 int size = AOP_SIZE (result);
8197 if (size >= LSB + offr)
8199 l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8201 emitcode ("add", "a,acc");
8202 if (sameRegs (AOP (left), AOP (result)) &&
8203 size >= MSB16 + offr && offr != LSB)
8204 emitcode ("xch", "a,%s",
8205 aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8207 aopPut (AOP (result), "a", LSB + offr);
8210 if (size >= MSB16 + offr)
8212 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8214 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8216 emitcode ("rlc", "a");
8217 if (sameRegs (AOP (left), AOP (result)) &&
8218 size >= MSB24 + offr && offr != LSB)
8219 emitcode ("xch", "a,%s",
8220 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8222 aopPut (AOP (result), "a", MSB16 + offr);
8225 if (size >= MSB24 + offr)
8227 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8229 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8231 emitcode ("rlc", "a");
8232 if (sameRegs (AOP (left), AOP (result)) &&
8233 size >= MSB32 + offr && offr != LSB)
8234 emitcode ("xch", "a,%s",
8235 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8237 aopPut (AOP (result), "a", MSB24 + offr);
8240 if (size > MSB32 + offr)
8242 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8244 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8246 emitcode ("rlc", "a");
8247 aopPut (AOP (result), "a", MSB32 + offr);
8250 aopPut (AOP (result), zero, LSB);
8256 /*-----------------------------------------------------------------*/
8257 /* genlshFour - shift four byte by a known amount != 0 */
8258 /*-----------------------------------------------------------------*/
8260 genlshFour (operand * result, operand * left, int shCount)
8264 D (emitcode (";", "genlshFour ");
8267 size = AOP_SIZE (result);
8269 /* if shifting more that 3 bytes */
8274 /* lowest order of left goes to the highest
8275 order of the destination */
8276 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8278 movLeft2Result (left, LSB, result, MSB32, 0);
8279 aopPut (AOP (result), zero, LSB);
8280 aopPut (AOP (result), zero, MSB16);
8281 aopPut (AOP (result), zero, MSB24);
8285 /* more than two bytes */
8286 else if (shCount >= 16)
8288 /* lower order two bytes goes to higher order two bytes */
8290 /* if some more remaining */
8292 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8295 movLeft2Result (left, MSB16, result, MSB32, 0);
8296 movLeft2Result (left, LSB, result, MSB24, 0);
8298 aopPut (AOP (result), zero, MSB16);
8299 aopPut (AOP (result), zero, LSB);
8303 /* if more than 1 byte */
8304 else if (shCount >= 8)
8306 /* lower order three bytes goes to higher order three bytes */
8311 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8313 movLeft2Result (left, LSB, result, MSB16, 0);
8319 movLeft2Result (left, MSB24, result, MSB32, 0);
8320 movLeft2Result (left, MSB16, result, MSB24, 0);
8321 movLeft2Result (left, LSB, result, MSB16, 0);
8322 aopPut (AOP (result), zero, LSB);
8324 else if (shCount == 1)
8325 shiftLLong (left, result, MSB16);
8328 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8329 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8330 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8331 aopPut (AOP (result), zero, LSB);
8336 /* 1 <= shCount <= 7 */
8337 else if (shCount <= 2)
8339 shiftLLong (left, result, LSB);
8341 shiftLLong (result, result, LSB);
8343 /* 3 <= shCount <= 7, optimize */
8346 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8347 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8348 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8353 #ifdef BETTER_LITERAL_SHIFT
8354 /*-----------------------------------------------------------------*/
8355 /* genLeftShiftLiteral - left shifting by known count */
8356 /*-----------------------------------------------------------------*/
8358 genLeftShiftLiteral (operand * left,
8363 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8366 size = getSize (operandType (result));
8368 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8370 /* We only handle certain easy cases so far. */
8372 && (shCount < (size * 8))
8376 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8380 freeAsmop (right, NULL, ic, TRUE);
8382 aopOp(left, ic, FALSE, FALSE);
8383 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8386 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8388 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8389 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8391 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8394 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8396 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8397 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8399 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8405 emitcode ("; shift left ", "result %d, left %d", size,
8409 /* I suppose that the left size >= result size */
8412 _startLazyDPSEvaluation();
8415 movLeft2Result (left, size, result, size, 0);
8417 _endLazyDPSEvaluation();
8419 else if (shCount >= (size * 8))
8421 _startLazyDPSEvaluation();
8424 aopPut (AOP (result), zero, size);
8426 _endLazyDPSEvaluation();
8433 genlshOne (result, left, shCount);
8437 genlshTwo (result, left, shCount);
8441 genlshFour (result, left, shCount);
8445 fprintf(stderr, "*** ack! mystery literal shift!\n");
8449 freeAsmop (left, NULL, ic, TRUE);
8450 freeAsmop (result, NULL, ic, TRUE);
8455 /*-----------------------------------------------------------------*/
8456 /* genLeftShift - generates code for left shifting */
8457 /*-----------------------------------------------------------------*/
8459 genLeftShift (iCode * ic)
8461 operand *left, *right, *result;
8464 symbol *tlbl, *tlbl1;
8466 D (emitcode (";", "genLeftShift "););
8468 right = IC_RIGHT (ic);
8469 left = IC_LEFT (ic);
8470 result = IC_RESULT (ic);
8472 aopOp (right, ic, FALSE, FALSE);
8475 #ifdef BETTER_LITERAL_SHIFT
8476 /* if the shift count is known then do it
8477 as efficiently as possible */
8478 if (AOP_TYPE (right) == AOP_LIT)
8480 if (genLeftShiftLiteral (left, right, result, ic))
8487 /* shift count is unknown then we have to form
8488 a loop get the loop count in B : Note: we take
8489 only the lower order byte since shifting
8490 more that 32 bits make no sense anyway, ( the
8491 largest size of an object can be only 32 bits ) */
8493 if (AOP_TYPE (right) == AOP_LIT)
8495 /* Really should be handled by genLeftShiftLiteral,
8496 * but since I'm too lazy to fix that today, at least we can make
8497 * some small improvement.
8499 emitcode("mov", "b,#!constbyte",
8500 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8504 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8505 emitcode ("inc", "b");
8507 freeAsmop (right, NULL, ic, TRUE);
8508 aopOp (left, ic, FALSE, FALSE);
8509 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8511 /* now move the left to the result if they are not the
8513 if (!sameRegs (AOP (left), AOP (result)) &&
8514 AOP_SIZE (result) > 1)
8517 size = AOP_SIZE (result);
8519 _startLazyDPSEvaluation ();
8522 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8523 if (*l == '@' && (IS_AOP_PREG (result)))
8526 emitcode ("mov", "a,%s", l);
8527 aopPut (AOP (result), "a", offset);
8530 aopPut (AOP (result), l, offset);
8533 _endLazyDPSEvaluation ();
8536 tlbl = newiTempLabel (NULL);
8537 size = AOP_SIZE (result);
8539 tlbl1 = newiTempLabel (NULL);
8541 /* if it is only one byte then */
8544 symbol *tlbl1 = newiTempLabel (NULL);
8546 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8547 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8548 emitcode ("", "!tlabeldef", tlbl->key + 100);
8549 emitcode ("add", "a,acc");
8550 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8551 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8552 aopPut (AOP (result), "a", 0);
8556 reAdjustPreg (AOP (result));
8558 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8559 emitcode ("", "!tlabeldef", tlbl->key + 100);
8560 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8561 emitcode ("add", "a,acc");
8562 aopPut (AOP (result), "a", offset++);
8563 _startLazyDPSEvaluation ();
8566 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8567 emitcode ("rlc", "a");
8568 aopPut (AOP (result), "a", offset++);
8570 _endLazyDPSEvaluation ();
8571 reAdjustPreg (AOP (result));
8573 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8574 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8576 freeAsmop (left, NULL, ic, TRUE);
8577 freeAsmop (result, NULL, ic, TRUE);
8580 #ifdef BETTER_LITERAL_SHIFT
8581 /*-----------------------------------------------------------------*/
8582 /* genrshOne - right shift a one byte quantity by known count */
8583 /*-----------------------------------------------------------------*/
8585 genrshOne (operand * result, operand * left,
8586 int shCount, int sign)
8588 D (emitcode (";", "genrshOne"););
8589 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8593 #ifdef BETTER_LITERAL_SHIFT
8594 /*-----------------------------------------------------------------*/
8595 /* genrshTwo - right shift two bytes by known amount != 0 */
8596 /*-----------------------------------------------------------------*/
8598 genrshTwo (operand * result, operand * left,
8599 int shCount, int sign)
8601 D (emitcode (";", "genrshTwo"););
8603 /* if shCount >= 8 */
8607 _startLazyDPSEvaluation();
8610 shiftR1Left2Result (left, MSB16, result, LSB,
8615 movLeft2Result (left, MSB16, result, LSB, sign);
8617 addSign (result, MSB16, sign);
8618 _endLazyDPSEvaluation();
8621 /* 1 <= shCount <= 7 */
8624 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8629 /*-----------------------------------------------------------------*/
8630 /* shiftRLong - shift right one long from left to result */
8631 /* offl = LSB or MSB16 */
8632 /*-----------------------------------------------------------------*/
8634 shiftRLong (operand * left, int offl,
8635 operand * result, int sign)
8637 int isSameRegs=sameRegs(AOP(left),AOP(result));
8639 if (isSameRegs && offl>1) {
8640 // we are in big trouble, but this shouldn't happen
8641 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8644 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8649 emitcode ("rlc", "a");
8650 emitcode ("subb", "a,acc");
8651 emitcode ("xch", "a,%s",
8652 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
8654 aopPut (AOP(result), zero, MSB32);
8659 emitcode ("clr", "c");
8661 emitcode ("mov", "c,acc.7");
8664 emitcode ("rrc", "a");
8666 if (isSameRegs && offl==MSB16) {
8668 "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
8670 aopPut (AOP (result), "a", MSB32);
8671 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8674 emitcode ("rrc", "a");
8675 if (isSameRegs && offl==1) {
8676 emitcode ("xch", "a,%s",
8677 aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
8679 aopPut (AOP (result), "a", MSB24);
8680 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
8682 emitcode ("rrc", "a");
8683 aopPut (AOP (result), "a", MSB16 - offl);
8687 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
8688 emitcode ("rrc", "a");
8689 aopPut (AOP (result), "a", LSB);
8693 /*-----------------------------------------------------------------*/
8694 /* genrshFour - shift four byte by a known amount != 0 */
8695 /*-----------------------------------------------------------------*/
8697 genrshFour (operand * result, operand * left,
8698 int shCount, int sign)
8700 D (emitcode (";", "genrshFour"););
8702 /* if shifting more that 3 bytes */
8706 _startLazyDPSEvaluation();
8708 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8710 movLeft2Result (left, MSB32, result, LSB, sign);
8711 addSign (result, MSB16, sign);
8712 _endLazyDPSEvaluation();
8714 else if (shCount >= 16)
8717 _startLazyDPSEvaluation();
8719 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8722 movLeft2Result (left, MSB24, result, LSB, 0);
8723 movLeft2Result (left, MSB32, result, MSB16, sign);
8725 addSign (result, MSB24, sign);
8726 _endLazyDPSEvaluation();
8728 else if (shCount >= 8)
8731 _startLazyDPSEvaluation();
8734 shiftRLong (left, MSB16, result, sign);
8736 else if (shCount == 0)
8738 movLeft2Result (left, MSB16, result, LSB, 0);
8739 movLeft2Result (left, MSB24, result, MSB16, 0);
8740 movLeft2Result (left, MSB32, result, MSB24, sign);
8741 addSign (result, MSB32, sign);
8745 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8746 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8747 /* the last shift is signed */
8748 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8749 addSign (result, MSB32, sign);
8751 _endLazyDPSEvaluation();
8755 /* 1 <= shCount <= 7 */
8758 shiftRLong (left, LSB, result, sign);
8760 shiftRLong (result, LSB, result, sign);
8764 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8765 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8766 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8771 #ifdef BETTER_LITERAL_SHIFT
8772 /*-----------------------------------------------------------------*/
8773 /* genRightShiftLiteral - right shifting by known count */
8774 /*-----------------------------------------------------------------*/
8776 genRightShiftLiteral (operand * left,
8782 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8785 size = getSize (operandType (result));
8787 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8789 /* We only handle certain easy cases so far. */
8791 && (shCount < (size * 8))
8796 D(emitcode (";", "genRightShiftLiteral wimping out"););
8800 freeAsmop (right, NULL, ic, TRUE);
8802 aopOp (left, ic, FALSE, FALSE);
8803 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8806 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8810 /* test the LEFT size !!! */
8812 /* I suppose that the left size >= result size */
8815 size = getDataSize (result);
8816 _startLazyDPSEvaluation();
8819 movLeft2Result (left, size, result, size, 0);
8821 _endLazyDPSEvaluation();
8823 else if (shCount >= (size * 8))
8827 /* get sign in acc.7 */
8828 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8830 addSign (result, LSB, sign);
8837 genrshOne (result, left, shCount, sign);
8841 genrshTwo (result, left, shCount, sign);
8845 genrshFour (result, left, shCount, sign);
8852 freeAsmop (left, NULL, ic, TRUE);
8853 freeAsmop (result, NULL, ic, TRUE);
8859 /*-----------------------------------------------------------------*/
8860 /* genSignedRightShift - right shift of signed number */
8861 /*-----------------------------------------------------------------*/
8863 genSignedRightShift (iCode * ic)
8865 operand *right, *left, *result;
8868 symbol *tlbl, *tlbl1;
8870 D (emitcode (";", "genSignedRightShift "););
8872 /* we do it the hard way put the shift count in b
8873 and loop thru preserving the sign */
8875 right = IC_RIGHT (ic);
8876 left = IC_LEFT (ic);
8877 result = IC_RESULT (ic);
8879 aopOp (right, ic, FALSE, FALSE);
8881 #ifdef BETTER_LITERAL_SHIFT
8882 if (AOP_TYPE (right) == AOP_LIT)
8884 if (genRightShiftLiteral (left, right, result, ic, 1))
8890 /* shift count is unknown then we have to form
8891 a loop get the loop count in B : Note: we take
8892 only the lower order byte since shifting
8893 more that 32 bits make no sense anyway, ( the
8894 largest size of an object can be only 32 bits ) */
8896 if (AOP_TYPE (right) == AOP_LIT)
8898 /* Really should be handled by genRightShiftLiteral,
8899 * but since I'm too lazy to fix that today, at least we can make
8900 * some small improvement.
8902 emitcode("mov", "b,#!constbyte",
8903 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8907 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8908 emitcode ("inc", "b");
8910 freeAsmop (right, NULL, ic, TRUE);
8911 aopOp (left, ic, FALSE, FALSE);
8912 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8914 /* now move the left to the result if they are not the
8916 if (!sameRegs (AOP (left), AOP (result)) &&
8917 AOP_SIZE (result) > 1)
8920 size = AOP_SIZE (result);
8922 _startLazyDPSEvaluation ();
8925 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8926 if (*l == '@' && IS_AOP_PREG (result))
8929 emitcode ("mov", "a,%s", l);
8930 aopPut (AOP (result), "a", offset);
8933 aopPut (AOP (result), l, offset);
8936 _endLazyDPSEvaluation ();
8939 /* mov the highest order bit to OVR */
8940 tlbl = newiTempLabel (NULL);
8941 tlbl1 = newiTempLabel (NULL);
8943 size = AOP_SIZE (result);
8945 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8946 emitcode ("rlc", "a");
8947 emitcode ("mov", "ov,c");
8948 /* if it is only one byte then */
8951 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8952 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8953 emitcode ("", "!tlabeldef", tlbl->key + 100);
8954 emitcode ("mov", "c,ov");
8955 emitcode ("rrc", "a");
8956 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8957 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8958 aopPut (AOP (result), "a", 0);
8962 reAdjustPreg (AOP (result));
8963 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8964 emitcode ("", "!tlabeldef", tlbl->key + 100);
8965 emitcode ("mov", "c,ov");
8966 _startLazyDPSEvaluation ();
8969 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8970 emitcode ("rrc", "a");
8971 aopPut (AOP (result), "a", offset--);
8973 _endLazyDPSEvaluation ();
8974 reAdjustPreg (AOP (result));
8975 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8976 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8979 freeAsmop (left, NULL, ic, TRUE);
8980 freeAsmop (result, NULL, ic, TRUE);
8983 /*-----------------------------------------------------------------*/
8984 /* genRightShift - generate code for right shifting */
8985 /*-----------------------------------------------------------------*/
8987 genRightShift (iCode * ic)
8989 operand *right, *left, *result;
8993 symbol *tlbl, *tlbl1;
8995 D (emitcode (";", "genRightShift "););
8997 /* if signed then we do it the hard way preserve the
8998 sign bit moving it inwards */
8999 letype = getSpec (operandType (IC_LEFT (ic)));
9001 if (!SPEC_USIGN (letype))
9003 genSignedRightShift (ic);
9007 /* signed & unsigned types are treated the same : i.e. the
9008 signed is NOT propagated inwards : quoting from the
9009 ANSI - standard : "for E1 >> E2, is equivalent to division
9010 by 2**E2 if unsigned or if it has a non-negative value,
9011 otherwise the result is implementation defined ", MY definition
9012 is that the sign does not get propagated */
9014 right = IC_RIGHT (ic);
9015 left = IC_LEFT (ic);
9016 result = IC_RESULT (ic);
9018 aopOp (right, ic, FALSE, FALSE);
9020 #ifdef BETTER_LITERAL_SHIFT
9021 /* if the shift count is known then do it
9022 as efficiently as possible */
9023 if (AOP_TYPE (right) == AOP_LIT)
9025 if (genRightShiftLiteral (left, right, result, ic, 0))
9032 /* shift count is unknown then we have to form
9033 a loop get the loop count in B : Note: we take
9034 only the lower order byte since shifting
9035 more that 32 bits make no sense anyway, ( the
9036 largest size of an object can be only 32 bits ) */
9038 if (AOP_TYPE (right) == AOP_LIT)
9040 /* Really should be handled by genRightShiftLiteral,
9041 * but since I'm too lazy to fix that today, at least we can make
9042 * some small improvement.
9044 emitcode("mov", "b,#!constbyte",
9045 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9049 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9050 emitcode ("inc", "b");
9052 freeAsmop (right, NULL, ic, TRUE);
9053 aopOp (left, ic, FALSE, FALSE);
9054 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9056 /* now move the left to the result if they are not the
9058 if (!sameRegs (AOP (left), AOP (result)) &&
9059 AOP_SIZE (result) > 1)
9062 size = AOP_SIZE (result);
9064 _startLazyDPSEvaluation ();
9067 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9068 if (*l == '@' && IS_AOP_PREG (result))
9071 emitcode ("mov", "a,%s", l);
9072 aopPut (AOP (result), "a", offset);
9075 aopPut (AOP (result), l, offset);
9078 _endLazyDPSEvaluation ();
9081 tlbl = newiTempLabel (NULL);
9082 tlbl1 = newiTempLabel (NULL);
9083 size = AOP_SIZE (result);
9086 /* if it is only one byte then */
9089 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9090 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9091 emitcode ("", "!tlabeldef", tlbl->key + 100);
9093 emitcode ("rrc", "a");
9094 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9095 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9096 aopPut (AOP (result), "a", 0);
9100 reAdjustPreg (AOP (result));
9101 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9102 emitcode ("", "!tlabeldef", tlbl->key + 100);
9104 _startLazyDPSEvaluation ();
9107 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9108 emitcode ("rrc", "a");
9109 aopPut (AOP (result), "a", offset--);
9111 _endLazyDPSEvaluation ();
9112 reAdjustPreg (AOP (result));
9114 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9115 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9118 freeAsmop (left, NULL, ic, TRUE);
9119 freeAsmop (result, NULL, ic, TRUE);
9123 /*-----------------------------------------------------------------*/
9124 /* emitPtrByteGet - emits code to get a byte into A through a */
9125 /* pointer register (R0, R1, or DPTR). The */
9126 /* original value of A can be preserved in B. */
9127 /*-----------------------------------------------------------------*/
9129 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9136 emitcode ("mov", "b,a");
9137 emitcode ("mov", "a,@%s", rname);
9142 emitcode ("mov", "b,a");
9143 emitcode ("movx", "a,@%s", rname);
9148 emitcode ("mov", "b,a");
9149 emitcode ("movx", "a,@dptr");
9154 emitcode ("mov", "b,a");
9155 emitcode ("clr", "a");
9156 emitcode ("movc", "a,@a+dptr");
9162 emitcode ("push", "b");
9163 emitcode ("push", "acc");
9165 emitcode ("lcall", "__gptrget");
9167 emitcode ("pop", "b");
9172 /*-----------------------------------------------------------------*/
9173 /* emitPtrByteSet - emits code to set a byte from src through a */
9174 /* pointer register (R0, R1, or DPTR). */
9175 /*-----------------------------------------------------------------*/
9177 emitPtrByteSet (char *rname, int p_type, char *src)
9186 emitcode ("mov", "@%s,a", rname);
9189 emitcode ("mov", "@%s,%s", rname, src);
9194 emitcode ("movx", "@%s,a", rname);
9199 emitcode ("movx", "@dptr,a");
9204 emitcode ("lcall", "__gptrput");
9209 /*-----------------------------------------------------------------*/
9210 /* genUnpackBits - generates code for unpacking bits */
9211 /*-----------------------------------------------------------------*/
9213 genUnpackBits (operand * result, char *rname, int ptype)
9215 int offset = 0; /* result byte offset */
9216 int rsize; /* result size */
9217 int rlen = 0; /* remaining bitfield length */
9218 sym_link *etype; /* bitfield type information */
9219 int blen; /* bitfield length */
9220 int bstr; /* bitfield starting bit within byte */
9222 D(emitcode ("; genUnpackBits",""));
9224 etype = getSpec (operandType (result));
9225 rsize = getSize (operandType (result));
9226 blen = SPEC_BLEN (etype);
9227 bstr = SPEC_BSTR (etype);
9229 /* If the bitfield length is less than a byte */
9232 emitPtrByteGet (rname, ptype, FALSE);
9234 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9235 aopPut (AOP (result), "a", offset++);
9239 /* Bit field did not fit in a byte. Copy all
9240 but the partial byte at the end. */
9241 for (rlen=blen;rlen>=8;rlen-=8)
9243 emitPtrByteGet (rname, ptype, FALSE);
9244 aopPut (AOP (result), "a", offset++);
9246 emitcode ("inc", "%s", rname);
9249 /* Handle the partial byte at the end */
9252 emitPtrByteGet (rname, ptype, FALSE);
9253 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9254 aopPut (AOP (result), "a", offset++);
9262 aopPut (AOP (result), zero, offset++);
9267 /*-----------------------------------------------------------------*/
9268 /* genDataPointerGet - generates code when ptr offset is known */
9269 /*-----------------------------------------------------------------*/
9271 genDataPointerGet (operand * left,
9277 int size, offset = 0;
9278 aopOp (result, ic, TRUE, FALSE);
9280 /* get the string representation of the name */
9281 l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9282 size = AOP_SIZE (result);
9283 _startLazyDPSEvaluation ();
9288 SNPRINTF (buff, sizeof(buff),
9289 "(%s + %d)", l + 1, offset);
9293 SNPRINTF (buff, sizeof(buff),
9296 aopPut (AOP (result), buff, offset++);
9298 _endLazyDPSEvaluation ();
9300 freeAsmop (left, NULL, ic, TRUE);
9301 freeAsmop (result, NULL, ic, TRUE);
9304 /*-----------------------------------------------------------------*/
9305 /* genNearPointerGet - emitcode for near pointer fetch */
9306 /*-----------------------------------------------------------------*/
9308 genNearPointerGet (operand * left,
9316 sym_link *rtype, *retype, *letype;
9317 sym_link *ltype = operandType (left);
9320 rtype = operandType (result);
9321 retype = getSpec (rtype);
9322 letype = getSpec (ltype);
9324 aopOp (left, ic, FALSE, FALSE);
9326 /* if left is rematerialisable and
9327 result is not bit variable type and
9328 the left is pointer to data space i.e
9329 lower 128 bytes of space */
9330 if (AOP_TYPE (left) == AOP_IMMD &&
9331 !IS_BITVAR (retype) &&
9332 !IS_BITVAR (letype) &&
9333 DCL_TYPE (ltype) == POINTER)
9335 genDataPointerGet (left, result, ic);
9339 /* if the value is already in a pointer register
9340 then don't need anything more */
9341 if (!AOP_INPREG (AOP (left)))
9343 /* otherwise get a free pointer register */
9345 preg = getFreePtr (ic, &aop, FALSE);
9346 emitcode ("mov", "%s,%s",
9348 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9352 rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9354 freeAsmop (left, NULL, ic, TRUE);
9355 aopOp (result, ic, FALSE, FALSE);
9357 /* if bitfield then unpack the bits */
9358 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9359 genUnpackBits (result, rname, POINTER);
9362 /* we have can just get the values */
9363 int size = AOP_SIZE (result);
9368 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9371 emitcode ("mov", "a,@%s", rname);
9372 aopPut (AOP (result), "a", offset);
9376 SNPRINTF (buff, sizeof(buff), "@%s", rname);
9377 aopPut (AOP (result), buff, offset);
9382 emitcode ("inc", "%s", rname);
9387 /* now some housekeeping stuff */
9390 /* we had to allocate for this iCode */
9391 if (pi) { /* post increment present */
9392 aopPut(AOP ( left ),rname,0);
9394 freeAsmop (NULL, aop, ic, TRUE);
9398 /* we did not allocate which means left
9399 already in a pointer register, then
9400 if size > 0 && this could be used again
9401 we have to point it back to where it
9403 if (AOP_SIZE (result) > 1 &&
9404 !OP_SYMBOL (left)->remat &&
9405 (OP_SYMBOL (left)->liveTo > ic->seq ||
9409 int size = AOP_SIZE (result) - 1;
9411 emitcode ("dec", "%s", rname);
9416 freeAsmop (result, NULL, ic, TRUE);
9417 if (pi) pi->generated = 1;
9420 /*-----------------------------------------------------------------*/
9421 /* genPagedPointerGet - emitcode for paged pointer fetch */
9422 /*-----------------------------------------------------------------*/
9424 genPagedPointerGet (operand * left,
9432 sym_link *rtype, *retype, *letype;
9434 rtype = operandType (result);
9435 retype = getSpec (rtype);
9436 letype = getSpec (operandType (left));
9437 aopOp (left, ic, FALSE, FALSE);
9439 /* if the value is already in a pointer register
9440 then don't need anything more */
9441 if (!AOP_INPREG (AOP (left)))
9443 /* otherwise get a free pointer register */
9445 preg = getFreePtr (ic, &aop, FALSE);
9446 emitcode ("mov", "%s,%s",
9448 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9452 rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9454 freeAsmop (left, NULL, ic, TRUE);
9455 aopOp (result, ic, FALSE, FALSE);
9457 /* if bitfield then unpack the bits */
9458 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9459 genUnpackBits (result, rname, PPOINTER);
9462 /* we have can just get the values */
9463 int size = AOP_SIZE (result);
9469 emitcode ("movx", "a,@%s", rname);
9470 aopPut (AOP (result), "a", offset);
9475 emitcode ("inc", "%s", rname);
9479 /* now some housekeeping stuff */
9482 /* we had to allocate for this iCode */
9483 if (pi) aopPut ( AOP (left), rname, 0);
9484 freeAsmop (NULL, aop, ic, TRUE);
9488 /* we did not allocate which means left
9489 already in a pointer register, then
9490 if size > 0 && this could be used again
9491 we have to point it back to where it
9493 if (AOP_SIZE (result) > 1 &&
9494 !OP_SYMBOL (left)->remat &&
9495 (OP_SYMBOL (left)->liveTo > ic->seq ||
9499 int size = AOP_SIZE (result) - 1;
9501 emitcode ("dec", "%s", rname);
9506 freeAsmop (result, NULL, ic, TRUE);
9507 if (pi) pi->generated = 1;
9510 /*-----------------------------------------------------------------*/
9511 /* genFarPointerGet - gget value from far space */
9512 /*-----------------------------------------------------------------*/
9514 genFarPointerGet (operand * left,
9515 operand * result, iCode * ic, iCode *pi)
9517 int size, offset, dopi=1;
9518 sym_link *retype = getSpec (operandType (result));
9519 sym_link *letype = getSpec (operandType (left));
9520 D (emitcode (";", "genFarPointerGet"););
9522 aopOp (left, ic, FALSE, FALSE);
9524 /* if the operand is already in dptr
9525 then we do nothing else we move the value to dptr */
9526 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9528 /* if this is remateriazable */
9529 if (AOP_TYPE (left) == AOP_IMMD)
9531 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9535 /* we need to get it byte by byte */
9536 _startLazyDPSEvaluation ();
9537 if (AOP_TYPE (left) != AOP_DPTR)
9539 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9540 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9541 if (options.model == MODEL_FLAT24)
9542 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9546 /* We need to generate a load to DPTR indirect through DPTR. */
9547 D (emitcode (";", "genFarPointerGet -- indirection special case."););
9548 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9549 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9550 if (options.model == MODEL_FLAT24)
9551 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9552 emitcode ("pop", "dph");
9553 emitcode ("pop", "dpl");
9556 _endLazyDPSEvaluation ();
9559 /* so dptr know contains the address */
9560 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9562 /* if bit then unpack */
9563 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9564 if (AOP_INDPTRn(left)) {
9565 genSetDPTR(AOP(left)->aopu.dptr);
9567 genUnpackBits (result, "dptr", FPOINTER);
9568 if (AOP_INDPTRn(left)) {
9573 size = AOP_SIZE (result);
9576 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9578 genSetDPTR(AOP(left)->aopu.dptr);
9579 emitcode ("movx", "a,@dptr");
9580 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9581 emitcode ("inc", "dptr");
9583 aopPut (AOP (result), "a", offset++);
9586 _startLazyDPSEvaluation ();
9588 if (AOP_INDPTRn(left)) {
9589 genSetDPTR(AOP(left)->aopu.dptr);
9595 emitcode ("movx", "a,@dptr");
9596 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9597 emitcode ("inc", "dptr");
9599 aopPut (AOP (result), "a", offset++);
9601 _endLazyDPSEvaluation ();
9604 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9605 if (!AOP_INDPTRn(left)) {
9606 _startLazyDPSEvaluation ();
9607 aopPut ( AOP (left), "dpl", 0);
9608 aopPut ( AOP (left), "dph", 1);
9609 if (options.model == MODEL_FLAT24)
9610 aopPut ( AOP (left), "dpx", 2);
9611 _endLazyDPSEvaluation ();
9614 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
9615 AOP_SIZE(result) > 1 &&
9617 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9619 size = AOP_SIZE (result) - 1;
9620 if (AOP_INDPTRn(left)) {
9621 genSetDPTR(AOP(left)->aopu.dptr);
9623 while (size--) emitcode ("lcall","__decdptr");
9624 if (AOP_INDPTRn(left)) {
9629 freeAsmop (left, NULL, ic, TRUE);
9630 freeAsmop (result, NULL, ic, TRUE);
9633 /*-----------------------------------------------------------------*/
9634 /* genCodePointerGet - get value from code space */
9635 /*-----------------------------------------------------------------*/
9637 genCodePointerGet (operand * left,
9638 operand * result, iCode * ic, iCode *pi)
9640 int size, offset, dopi=1;
9641 sym_link *retype = getSpec (operandType (result));
9643 aopOp (left, ic, FALSE, FALSE);
9645 /* if the operand is already in dptr
9646 then we do nothing else we move the value to dptr */
9647 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9649 /* if this is remateriazable */
9650 if (AOP_TYPE (left) == AOP_IMMD)
9652 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9655 { /* we need to get it byte by byte */
9656 _startLazyDPSEvaluation ();
9657 if (AOP_TYPE (left) != AOP_DPTR)
9659 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9660 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9661 if (options.model == MODEL_FLAT24)
9662 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9666 /* We need to generate a load to DPTR indirect through DPTR. */
9667 D (emitcode (";", "gencodePointerGet -- indirection special case."););
9668 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9669 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9670 if (options.model == MODEL_FLAT24)
9671 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9672 emitcode ("pop", "dph");
9673 emitcode ("pop", "dpl");
9676 _endLazyDPSEvaluation ();
9679 /* so dptr know contains the address */
9680 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9682 /* if bit then unpack */
9683 if (IS_BITVAR (retype)) {
9684 if (AOP_INDPTRn(left)) {
9685 genSetDPTR(AOP(left)->aopu.dptr);
9687 genUnpackBits (result, "dptr", CPOINTER);
9688 if (AOP_INDPTRn(left)) {
9693 size = AOP_SIZE (result);
9695 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9697 genSetDPTR(AOP(left)->aopu.dptr);
9698 emitcode ("clr", "a");
9699 emitcode ("movc", "a,@a+dptr");
9700 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9701 emitcode ("inc", "dptr");
9703 aopPut (AOP (result), "a", offset++);
9706 _startLazyDPSEvaluation ();
9709 if (AOP_INDPTRn(left)) {
9710 genSetDPTR(AOP(left)->aopu.dptr);
9716 emitcode ("clr", "a");
9717 emitcode ("movc", "a,@a+dptr");
9718 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9719 emitcode ("inc", "dptr");
9720 aopPut (AOP (result), "a", offset++);
9722 _endLazyDPSEvaluation ();
9725 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9726 if (!AOP_INDPTRn(left)) {
9727 _startLazyDPSEvaluation ();
9729 aopPut ( AOP (left), "dpl", 0);
9730 aopPut ( AOP (left), "dph", 1);
9731 if (options.model == MODEL_FLAT24)
9732 aopPut ( AOP (left), "dpx", 2);
9734 _endLazyDPSEvaluation ();
9737 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9738 AOP_SIZE(result) > 1 &&
9739 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9741 size = AOP_SIZE (result) - 1;
9742 if (AOP_INDPTRn(left)) {
9743 genSetDPTR(AOP(left)->aopu.dptr);
9745 while (size--) emitcode ("lcall","__decdptr");
9746 if (AOP_INDPTRn(left)) {
9751 freeAsmop (left, NULL, ic, TRUE);
9752 freeAsmop (result, NULL, ic, TRUE);
9755 /*-----------------------------------------------------------------*/
9756 /* genGenPointerGet - gget value from generic pointer space */
9757 /*-----------------------------------------------------------------*/
9759 genGenPointerGet (operand * left,
9760 operand * result, iCode * ic, iCode * pi)
9763 sym_link *retype = getSpec (operandType (result));
9764 sym_link *letype = getSpec (operandType (left));
9766 D (emitcode (";", "genGenPointerGet "); );
9768 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9770 /* if the operand is already in dptr
9771 then we do nothing else we move the value to dptr */
9772 if (AOP_TYPE (left) != AOP_STR)
9774 /* if this is remateriazable */
9775 if (AOP_TYPE (left) == AOP_IMMD)
9777 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9778 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9780 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9784 emitcode ("mov", "b,#%d", pointerCode (retype));
9788 { /* we need to get it byte by byte */
9789 _startLazyDPSEvaluation ();
9790 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9791 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9792 if (options.model == MODEL_FLAT24) {
9793 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9794 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9796 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9798 _endLazyDPSEvaluation ();
9802 /* so dptr-b now contains the address */
9804 aopOp (result, ic, FALSE, TRUE);
9807 /* if bit then unpack */
9808 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9810 genUnpackBits (result, "dptr", GPOINTER);
9814 size = AOP_SIZE (result);
9821 // Get two bytes at a time, results in _AP & A.
9822 // dptr will be incremented ONCE by __gptrgetWord.
9824 // Note: any change here must be coordinated
9825 // with the implementation of __gptrgetWord
9826 // in device/lib/_gptrget.c
9827 emitcode ("lcall", "__gptrgetWord");
9828 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9829 aopPut (AOP (result), "a", offset++);
9834 // Only one byte to get.
9835 emitcode ("lcall", "__gptrget");
9836 aopPut (AOP (result), "a", offset++);
9839 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9841 emitcode ("inc", "dptr");
9846 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9847 _startLazyDPSEvaluation ();
9849 aopPut ( AOP (left), "dpl", 0);
9850 aopPut ( AOP (left), "dph", 1);
9851 if (options.model == MODEL_FLAT24) {
9852 aopPut ( AOP (left), "dpx", 2);
9853 aopPut ( AOP (left), "b", 3);
9854 } else aopPut ( AOP (left), "b", 2);
9856 _endLazyDPSEvaluation ();
9859 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9860 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9862 size = AOP_SIZE (result) - 1;
9863 while (size--) emitcode ("lcall","__decdptr");
9866 freeAsmop (left, NULL, ic, TRUE);
9867 freeAsmop (result, NULL, ic, TRUE);
9870 /*-----------------------------------------------------------------*/
9871 /* genPointerGet - generate code for pointer get */
9872 /*-----------------------------------------------------------------*/
9874 genPointerGet (iCode * ic, iCode *pi)
9876 operand *left, *result;
9877 sym_link *type, *etype;
9880 D (emitcode (";", "genPointerGet ");
9883 left = IC_LEFT (ic);
9884 result = IC_RESULT (ic);
9886 /* depending on the type of pointer we need to
9887 move it to the correct pointer register */
9888 type = operandType (left);
9889 etype = getSpec (type);
9890 /* if left is of type of pointer then it is simple */
9891 if (IS_PTR (type) && !IS_FUNC (type->next))
9892 p_type = DCL_TYPE (type);
9895 /* we have to go by the storage class */
9896 p_type = PTR_TYPE (SPEC_OCLS (etype));
9898 /* special case when cast remat */
9899 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9900 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9901 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9902 type = operandType (left);
9903 p_type = DCL_TYPE (type);
9905 /* now that we have the pointer type we assign
9906 the pointer values */
9912 genNearPointerGet (left, result, ic, pi);
9916 genPagedPointerGet (left, result, ic, pi);
9920 genFarPointerGet (left, result, ic, pi);
9924 genCodePointerGet (left, result, ic, pi);
9928 genGenPointerGet (left, result, ic, pi);
9934 /*-----------------------------------------------------------------*/
9935 /* genPackBits - generates code for packed bit storage */
9936 /*-----------------------------------------------------------------*/
9938 genPackBits (sym_link * etype,
9940 char *rname, int p_type)
9942 int offset = 0; /* source byte offset */
9943 int rlen = 0; /* remaining bitfield length */
9944 int blen; /* bitfield length */
9945 int bstr; /* bitfield starting bit within byte */
9946 int litval; /* source literal value (if AOP_LIT) */
9947 unsigned char mask; /* bitmask within current byte */
9949 D(emitcode ("; genPackBits",""));
9951 blen = SPEC_BLEN (etype);
9952 bstr = SPEC_BSTR (etype);
9954 /* If the bitfield length is less than a byte */
9957 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9958 (unsigned char) (0xFF >> (8 - bstr)));
9960 if (AOP_TYPE (right) == AOP_LIT)
9962 /* Case with a bitfield length <8 and literal source
9964 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9966 litval &= (~mask) & 0xff;
9967 emitPtrByteGet (rname, p_type, FALSE);
9968 if ((mask|litval)!=0xff)
9969 emitcode ("anl","a,#!constbyte", mask);
9971 emitcode ("orl","a,#!constbyte", litval);
9975 if ((blen==1) && (p_type!=GPOINTER))
9977 /* Case with a bitfield length == 1 and no generic pointer
9979 if (AOP_TYPE (right) == AOP_CRY)
9980 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9983 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9984 emitcode ("rrc","a");
9986 emitPtrByteGet (rname, p_type, FALSE);
9987 emitcode ("mov","acc.%d,c",bstr);
9991 /* Case with a bitfield length < 8 and arbitrary source
9993 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9994 /* shift and mask source value */
9996 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9998 /* transfer A to B and get next byte */
9999 emitPtrByteGet (rname, p_type, TRUE);
10001 emitcode ("anl", "a,#!constbyte", mask);
10002 emitcode ("orl", "a,b");
10003 if (p_type == GPOINTER)
10004 emitcode ("pop", "b");
10008 emitPtrByteSet (rname, p_type, "a");
10012 /* Bit length is greater than 7 bits. In this case, copy */
10013 /* all except the partial byte at the end */
10014 for (rlen=blen;rlen>=8;rlen-=8)
10016 emitPtrByteSet (rname, p_type,
10017 aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
10019 emitcode ("inc", "%s", rname);
10022 /* If there was a partial byte at the end */
10025 mask = (((unsigned char) -1 << rlen) & 0xff);
10027 if (AOP_TYPE (right) == AOP_LIT)
10029 /* Case with partial byte and literal source
10031 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10032 litval >>= (blen-rlen);
10033 litval &= (~mask) & 0xff;
10034 emitPtrByteGet (rname, p_type, FALSE);
10035 if ((mask|litval)!=0xff)
10036 emitcode ("anl","a,#!constbyte", mask);
10038 emitcode ("orl","a,#!constbyte", litval);
10042 /* Case with partial byte and arbitrary source
10044 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10045 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10047 /* transfer A to B and get next byte */
10048 emitPtrByteGet (rname, p_type, TRUE);
10050 emitcode ("anl", "a,#!constbyte", mask);
10051 emitcode ("orl", "a,b");
10052 if (p_type == GPOINTER)
10053 emitcode ("pop", "b");
10055 emitPtrByteSet (rname, p_type, "a");
10061 /*-----------------------------------------------------------------*/
10062 /* genDataPointerSet - remat pointer to data space */
10063 /*-----------------------------------------------------------------*/
10065 genDataPointerSet (operand * right,
10069 int size, offset = 0;
10070 char *l, buff[256];
10072 aopOp (right, ic, FALSE, FALSE);
10074 l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
10075 size = AOP_SIZE (right);
10080 SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
10084 SNPRINTF (buff, sizeof(buff), "%s", l + 1);
10087 emitcode ("mov", "%s,%s", buff,
10088 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10091 freeAsmop (right, NULL, ic, TRUE);
10092 freeAsmop (result, NULL, ic, TRUE);
10095 /*-----------------------------------------------------------------*/
10096 /* genNearPointerSet - emitcode for near pointer put */
10097 /*-----------------------------------------------------------------*/
10099 genNearPointerSet (operand * right,
10106 sym_link *retype, *letype;
10107 sym_link *ptype = operandType (result);
10109 retype = getSpec (operandType (right));
10110 letype = getSpec (ptype);
10112 aopOp (result, ic, FALSE, FALSE);
10114 /* if the result is rematerializable &
10115 in data space & not a bit variable */
10116 if (AOP_TYPE (result) == AOP_IMMD &&
10117 DCL_TYPE (ptype) == POINTER &&
10118 !IS_BITVAR (retype) &&
10119 !IS_BITVAR (letype))
10121 genDataPointerSet (right, result, ic);
10125 /* if the value is already in a pointer register
10126 then don't need anything more */
10127 if (!AOP_INPREG (AOP (result)))
10129 /* otherwise get a free pointer register */
10132 aop = newAsmop (0);
10133 preg = getFreePtr (ic, &aop, FALSE);
10134 emitcode ("mov", "%s,%s",
10136 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10137 rname = preg->name;
10140 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10142 aopOp (right, ic, FALSE, FALSE);
10144 /* if bitfield then unpack the bits */
10145 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10146 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
10149 /* we have can just get the values */
10150 int size = AOP_SIZE (right);
10155 l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10159 emitcode ("mov", "@%s,a", rname);
10162 emitcode ("mov", "@%s,%s", rname, l);
10164 emitcode ("inc", "%s", rname);
10169 /* now some housekeeping stuff */
10172 /* we had to allocate for this iCode */
10173 if (pi) aopPut (AOP (result),rname,0);
10174 freeAsmop (NULL, aop, ic, TRUE);
10178 /* we did not allocate which means left
10179 already in a pointer register, then
10180 if size > 0 && this could be used again
10181 we have to point it back to where it
10183 if (AOP_SIZE (right) > 1 &&
10184 !OP_SYMBOL (result)->remat &&
10185 (OP_SYMBOL (result)->liveTo > ic->seq ||
10189 int size = AOP_SIZE (right) - 1;
10191 emitcode ("dec", "%s", rname);
10196 if (pi) pi->generated = 1;
10197 freeAsmop (result, NULL, ic, TRUE);
10198 freeAsmop (right, NULL, ic, TRUE);
10203 /*-----------------------------------------------------------------*/
10204 /* genPagedPointerSet - emitcode for Paged pointer put */
10205 /*-----------------------------------------------------------------*/
10207 genPagedPointerSet (operand * right,
10214 sym_link *retype, *letype;
10216 retype = getSpec (operandType (right));
10217 letype = getSpec (operandType (result));
10219 aopOp (result, ic, FALSE, FALSE);
10221 /* if the value is already in a pointer register
10222 then don't need anything more */
10223 if (!AOP_INPREG (AOP (result)))
10225 /* otherwise get a free pointer register */
10228 aop = newAsmop (0);
10229 preg = getFreePtr (ic, &aop, FALSE);
10230 emitcode ("mov", "%s,%s",
10232 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10233 rname = preg->name;
10236 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10238 aopOp (right, ic, FALSE, FALSE);
10240 /* if bitfield then unpack the bits */
10241 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10242 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10245 /* we have can just get the values */
10246 int size = AOP_SIZE (right);
10251 MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10253 emitcode ("movx", "@%s,a", rname);
10256 emitcode ("inc", "%s", rname);
10262 /* now some housekeeping stuff */
10265 if (pi) aopPut (AOP (result),rname,0);
10266 /* we had to allocate for this iCode */
10267 freeAsmop (NULL, aop, ic, TRUE);
10271 /* we did not allocate which means left
10272 already in a pointer register, then
10273 if size > 0 && this could be used again
10274 we have to point it back to where it
10276 if (AOP_SIZE (right) > 1 &&
10277 !OP_SYMBOL (result)->remat &&
10278 (OP_SYMBOL (result)->liveTo > ic->seq ||
10282 int size = AOP_SIZE (right) - 1;
10284 emitcode ("dec", "%s", rname);
10289 if (pi) pi->generated = 1;
10290 freeAsmop (result, NULL, ic, TRUE);
10291 freeAsmop (right, NULL, ic, TRUE);
10296 /*-----------------------------------------------------------------*/
10297 /* genFarPointerSet - set value from far space */
10298 /*-----------------------------------------------------------------*/
10300 genFarPointerSet (operand * right,
10301 operand * result, iCode * ic, iCode *pi)
10303 int size, offset, dopi=1;
10304 sym_link *retype = getSpec (operandType (right));
10305 sym_link *letype = getSpec (operandType (result));
10307 aopOp (result, ic, FALSE, FALSE);
10309 /* if the operand is already in dptr
10310 then we do nothing else we move the value to dptr */
10311 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10313 /* if this is remateriazable */
10314 if (AOP_TYPE (result) == AOP_IMMD)
10315 emitcode ("mov", "dptr,%s",
10316 aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10319 /* we need to get it byte by byte */
10320 _startLazyDPSEvaluation ();
10321 if (AOP_TYPE (result) != AOP_DPTR)
10323 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10324 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10325 if (options.model == MODEL_FLAT24)
10326 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10330 /* We need to generate a load to DPTR indirect through DPTR. */
10331 D (emitcode (";", "genFarPointerSet -- indirection special case."););
10333 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10334 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10335 if (options.model == MODEL_FLAT24)
10336 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10337 emitcode ("pop", "dph");
10338 emitcode ("pop", "dpl");
10341 _endLazyDPSEvaluation ();
10344 /* so dptr know contains the address */
10345 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10347 /* if bit then unpack */
10348 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10349 if (AOP_INDPTRn(result)) {
10350 genSetDPTR(AOP(result)->aopu.dptr);
10352 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10353 if (AOP_INDPTRn(result)) {
10357 size = AOP_SIZE (right);
10359 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10361 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10363 genSetDPTR(AOP(result)->aopu.dptr);
10364 emitcode ("movx", "@dptr,a");
10365 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10366 emitcode ("inc", "dptr");
10370 _startLazyDPSEvaluation ();
10372 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10374 if (AOP_INDPTRn(result)) {
10375 genSetDPTR(AOP(result)->aopu.dptr);
10381 emitcode ("movx", "@dptr,a");
10382 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10383 emitcode ("inc", "dptr");
10385 _endLazyDPSEvaluation ();
10389 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10390 if (!AOP_INDPTRn(result)) {
10391 _startLazyDPSEvaluation ();
10393 aopPut (AOP(result),"dpl",0);
10394 aopPut (AOP(result),"dph",1);
10395 if (options.model == MODEL_FLAT24)
10396 aopPut (AOP(result),"dpx",2);
10398 _endLazyDPSEvaluation ();
10401 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10402 AOP_SIZE(right) > 1 &&
10403 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10405 size = AOP_SIZE (right) - 1;
10406 if (AOP_INDPTRn(result)) {
10407 genSetDPTR(AOP(result)->aopu.dptr);
10409 while (size--) emitcode ("lcall","__decdptr");
10410 if (AOP_INDPTRn(result)) {
10414 freeAsmop (result, NULL, ic, TRUE);
10415 freeAsmop (right, NULL, ic, TRUE);
10418 /*-----------------------------------------------------------------*/
10419 /* genGenPointerSet - set value from generic pointer space */
10420 /*-----------------------------------------------------------------*/
10422 genGenPointerSet (operand * right,
10423 operand * result, iCode * ic, iCode *pi)
10426 sym_link *retype = getSpec (operandType (right));
10427 sym_link *letype = getSpec (operandType (result));
10429 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10431 /* if the operand is already in dptr
10432 then we do nothing else we move the value to dptr */
10433 if (AOP_TYPE (result) != AOP_STR)
10435 _startLazyDPSEvaluation ();
10436 /* if this is remateriazable */
10437 if (AOP_TYPE (result) == AOP_IMMD)
10439 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10440 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10442 MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10447 "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10451 { /* we need to get it byte by byte */
10452 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10453 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10454 if (options.model == MODEL_FLAT24) {
10455 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10456 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10458 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10461 _endLazyDPSEvaluation ();
10463 /* so dptr + b now contains the address */
10465 aopOp (right, ic, FALSE, TRUE);
10469 /* if bit then unpack */
10470 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10472 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10476 size = AOP_SIZE (right);
10479 _startLazyDPSEvaluation ();
10484 // Set two bytes at a time, passed in _AP & A.
10485 // dptr will be incremented ONCE by __gptrputWord.
10487 // Note: any change here must be coordinated
10488 // with the implementation of __gptrputWord
10489 // in device/lib/_gptrput.c
10490 emitcode("mov", "_ap, %s",
10491 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10492 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10496 emitcode ("lcall", "__gptrputWord");
10501 // Only one byte to put.
10502 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10506 emitcode ("lcall", "__gptrput");
10509 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10511 emitcode ("inc", "dptr");
10514 _endLazyDPSEvaluation ();
10517 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10518 _startLazyDPSEvaluation ();
10520 aopPut (AOP(result),"dpl",0);
10521 aopPut (AOP(result),"dph",1);
10522 if (options.model == MODEL_FLAT24) {
10523 aopPut (AOP(result),"dpx",2);
10524 aopPut (AOP(result),"b",3);
10526 aopPut (AOP(result),"b",2);
10528 _endLazyDPSEvaluation ();
10531 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10532 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10534 size = AOP_SIZE (right) - 1;
10535 while (size--) emitcode ("lcall","__decdptr");
10537 freeAsmop (result, NULL, ic, TRUE);
10538 freeAsmop (right, NULL, ic, TRUE);
10541 /*-----------------------------------------------------------------*/
10542 /* genPointerSet - stores the value into a pointer location */
10543 /*-----------------------------------------------------------------*/
10545 genPointerSet (iCode * ic, iCode *pi)
10547 operand *right, *result;
10548 sym_link *type, *etype;
10551 D (emitcode (";", "genPointerSet "););
10553 right = IC_RIGHT (ic);
10554 result = IC_RESULT (ic);
10556 /* depending on the type of pointer we need to
10557 move it to the correct pointer register */
10558 type = operandType (result);
10559 etype = getSpec (type);
10560 /* if left is of type of pointer then it is simple */
10561 if (IS_PTR (type) && !IS_FUNC (type->next))
10563 p_type = DCL_TYPE (type);
10567 /* we have to go by the storage class */
10568 p_type = PTR_TYPE (SPEC_OCLS (etype));
10570 /* special case when cast remat */
10571 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10572 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10573 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10574 type = operandType (result);
10575 p_type = DCL_TYPE (type);
10578 /* now that we have the pointer type we assign
10579 the pointer values */
10585 genNearPointerSet (right, result, ic, pi);
10589 genPagedPointerSet (right, result, ic, pi);
10593 genFarPointerSet (right, result, ic, pi);
10597 genGenPointerSet (right, result, ic, pi);
10601 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10602 "genPointerSet: illegal pointer type");
10607 /*-----------------------------------------------------------------*/
10608 /* genIfx - generate code for Ifx statement */
10609 /*-----------------------------------------------------------------*/
10611 genIfx (iCode * ic, iCode * popIc)
10613 operand *cond = IC_COND (ic);
10616 D (emitcode (";", "genIfx "););
10618 aopOp (cond, ic, FALSE, FALSE);
10620 /* get the value into acc */
10621 if (AOP_TYPE (cond) != AOP_CRY)
10630 /* the result is now in the accumulator */
10631 freeAsmop (cond, NULL, ic, TRUE);
10633 /* if there was something to be popped then do it */
10637 /* if the condition is a bit variable */
10638 if (isbit && IS_ITEMP (cond) &&
10641 genIfxJump (ic, SPIL_LOC (cond)->rname);
10643 else if (isbit && !IS_ITEMP (cond))
10645 genIfxJump (ic, OP_SYMBOL (cond)->rname);
10649 genIfxJump (ic, "a");
10655 /*-----------------------------------------------------------------*/
10656 /* genAddrOf - generates code for address of */
10657 /*-----------------------------------------------------------------*/
10659 genAddrOf (iCode * ic)
10661 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10664 D (emitcode (";", "genAddrOf ");
10667 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10669 /* if the operand is on the stack then we
10670 need to get the stack offset of this
10672 if (sym->onStack) {
10674 /* if 10 bit stack */
10675 if (options.stack10bit) {
10679 tsprintf(buff, sizeof(buff),
10680 "#!constbyte",(options.stack_loc >> 16) & 0xff);
10681 /* if it has an offset then we need to compute it */
10682 /* emitcode ("subb", "a,#!constbyte", */
10683 /* -((sym->stack < 0) ? */
10684 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10685 /* ((short) sym->stack)) & 0xff); */
10686 /* emitcode ("mov","b,a"); */
10687 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10688 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10689 /* ((short) sym->stack)) >> 8) & 0xff); */
10691 emitcode ("mov", "a,_bpx");
10692 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
10693 ((char) (sym->stack - _G.nRegsSaved)) :
10694 ((char) sym->stack )) & 0xff);
10695 emitcode ("mov", "b,a");
10696 emitcode ("mov", "a,_bpx+1");
10698 offset = (((sym->stack < 0) ?
10699 ((short) (sym->stack - _G.nRegsSaved)) :
10700 ((short) sym->stack )) >> 8) & 0xff;
10702 emitcode ("addc","a,#!constbyte", offset);
10704 aopPut (AOP (IC_RESULT (ic)), "b", 0);
10705 aopPut (AOP (IC_RESULT (ic)), "a", 1);
10706 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10708 /* we can just move _bp */
10709 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10710 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10711 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10714 /* if it has an offset then we need to compute it */
10716 emitcode ("mov", "a,_bp");
10717 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10718 aopPut (AOP (IC_RESULT (ic)), "a", 0);
10720 /* we can just move _bp */
10721 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10723 /* fill the result with zero */
10724 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10727 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10729 "*** warning: pointer to stack var truncated.\n");
10734 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10740 /* object not on stack then we need the name */
10741 size = AOP_SIZE (IC_RESULT (ic));
10746 char s[SDCC_NAME_MAX];
10750 tsprintf(s, sizeof(s), "#!his",sym->rname);
10753 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
10756 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
10758 default: /* should not need this (just in case) */
10759 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10766 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10769 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10773 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10777 #if 0 // obsolete, and buggy for != xdata
10778 /*-----------------------------------------------------------------*/
10779 /* genArrayInit - generates code for address of */
10780 /*-----------------------------------------------------------------*/
10782 genArrayInit (iCode * ic)
10784 literalList *iLoop;
10786 int elementSize = 0, eIndex;
10787 unsigned val, lastVal;
10789 operand *left=IC_LEFT(ic);
10791 D (emitcode (";", "genArrayInit "););
10793 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10795 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10797 // Load immediate value into DPTR.
10798 emitcode("mov", "dptr, %s",
10799 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10801 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10804 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10805 "Unexpected operand to genArrayInit.\n");
10808 // a regression because of SDCCcse.c:1.52
10809 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10810 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10811 if (options.model == MODEL_FLAT24)
10812 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10816 type = operandType(IC_LEFT(ic));
10818 if (type && type->next)
10820 elementSize = getSize(type->next);
10824 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10825 "can't determine element size in genArrayInit.\n");
10829 iLoop = IC_ARRAYILIST(ic);
10834 bool firstpass = TRUE;
10836 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10837 iLoop->count, (int)iLoop->literalValue, elementSize);
10843 symbol *tlbl = NULL;
10845 count = ix > 256 ? 256 : ix;
10849 tlbl = newiTempLabel (NULL);
10850 if (firstpass || (count & 0xff))
10852 emitcode("mov", "b, #!constbyte", count & 0xff);
10855 emitcode ("", "!tlabeldef", tlbl->key + 100);
10860 for (eIndex = 0; eIndex < elementSize; eIndex++)
10862 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10863 if (val != lastVal)
10865 emitcode("mov", "a, #!constbyte", val);
10869 emitcode("movx", "@dptr, a");
10870 emitcode("inc", "dptr");
10875 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10881 iLoop = iLoop->next;
10884 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10888 /*-----------------------------------------------------------------*/
10889 /* genFarFarAssign - assignment when both are in far space */
10890 /*-----------------------------------------------------------------*/
10892 genFarFarAssign (operand * result, operand * right, iCode * ic)
10894 int size = AOP_SIZE (right);
10896 symbol *rSym = NULL;
10900 /* quick & easy case. */
10901 D(emitcode(";","genFarFarAssign (1 byte case)"););
10902 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10903 freeAsmop (right, NULL, ic, FALSE);
10904 /* now assign DPTR to result */
10906 aopOp(result, ic, FALSE, FALSE);
10908 aopPut(AOP(result), "a", 0);
10909 freeAsmop(result, NULL, ic, FALSE);
10913 /* See if we've got an underlying symbol to abuse. */
10914 if (IS_SYMOP(result) && OP_SYMBOL(result))
10916 if (IS_TRUE_SYMOP(result))
10918 rSym = OP_SYMBOL(result);
10920 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10922 rSym = OP_SYMBOL(result)->usl.spillLoc;
10926 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10928 /* We can use the '390 auto-toggle feature to good effect here. */
10930 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10931 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10932 emitcode ("mov", "dptr,#%s", rSym->rname);
10933 /* DP2 = result, DP1 = right, DP1 is current. */
10936 emitcode("movx", "a,@dptr");
10937 emitcode("movx", "@dptr,a");
10940 emitcode("inc", "dptr");
10941 emitcode("inc", "dptr");
10944 emitcode("mov", "dps,#0");
10945 freeAsmop (right, NULL, ic, FALSE);
10947 some alternative code for processors without auto-toggle
10948 no time to test now, so later well put in...kpb
10949 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10950 emitcode("mov", "dps,#1"); /* Select DPTR2. */
10951 emitcode ("mov", "dptr,#%s", rSym->rname);
10952 /* DP2 = result, DP1 = right, DP1 is current. */
10956 emitcode("movx", "a,@dptr");
10958 emitcode("inc", "dptr");
10959 emitcode("inc", "dps");
10960 emitcode("movx", "@dptr,a");
10962 emitcode("inc", "dptr");
10963 emitcode("inc", "dps");
10965 emitcode("mov", "dps,#0");
10966 freeAsmop (right, NULL, ic, FALSE);
10971 D (emitcode (";", "genFarFarAssign"););
10972 aopOp (result, ic, TRUE, TRUE);
10974 _startLazyDPSEvaluation ();
10978 aopPut (AOP (result),
10979 aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10982 _endLazyDPSEvaluation ();
10983 freeAsmop (result, NULL, ic, FALSE);
10984 freeAsmop (right, NULL, ic, FALSE);
10988 /*-----------------------------------------------------------------*/
10989 /* genAssign - generate code for assignment */
10990 /*-----------------------------------------------------------------*/
10992 genAssign (iCode * ic)
10994 operand *result, *right;
10996 unsigned long lit = 0L;
10998 D (emitcode (";", "genAssign ");
11001 result = IC_RESULT (ic);
11002 right = IC_RIGHT (ic);
11004 /* if they are the same */
11005 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11008 aopOp (right, ic, FALSE, FALSE);
11010 emitcode (";", "genAssign: resultIsFar = %s",
11011 isOperandInFarSpace (result) ?
11014 /* special case both in far space */
11015 if ((AOP_TYPE (right) == AOP_DPTR ||
11016 AOP_TYPE (right) == AOP_DPTR2) &&
11017 /* IS_TRUE_SYMOP(result) && */
11018 isOperandInFarSpace (result))
11020 genFarFarAssign (result, right, ic);
11024 aopOp (result, ic, TRUE, FALSE);
11026 /* if they are the same registers */
11027 if (sameRegs (AOP (right), AOP (result)))
11030 /* if the result is a bit */
11031 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
11033 /* if the right size is a literal then
11034 we know what the value is */
11035 if (AOP_TYPE (right) == AOP_LIT)
11037 if (((int) operandLitValue (right)))
11038 aopPut (AOP (result), one, 0);
11040 aopPut (AOP (result), zero, 0);
11044 /* the right is also a bit variable */
11045 if (AOP_TYPE (right) == AOP_CRY)
11047 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11048 aopPut (AOP (result), "c", 0);
11052 /* we need to or */
11054 aopPut (AOP (result), "a", 0);
11058 /* bit variables done */
11060 size = AOP_SIZE (result);
11062 if (AOP_TYPE (right) == AOP_LIT)
11063 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11066 (AOP_TYPE (result) != AOP_REG) &&
11067 (AOP_TYPE (right) == AOP_LIT) &&
11068 !IS_FLOAT (operandType (right)))
11070 _startLazyDPSEvaluation ();
11071 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
11073 aopPut (AOP (result),
11074 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11079 /* And now fill the rest with zeros. */
11082 emitcode ("clr", "a");
11086 aopPut (AOP (result), "a", offset++);
11088 _endLazyDPSEvaluation ();
11092 _startLazyDPSEvaluation ();
11095 aopPut (AOP (result),
11096 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11100 _endLazyDPSEvaluation ();
11104 freeAsmop (right, NULL, ic, FALSE);
11105 freeAsmop (result, NULL, ic, TRUE);
11108 /*-----------------------------------------------------------------*/
11109 /* genJumpTab - generates code for jump table */
11110 /*-----------------------------------------------------------------*/
11112 genJumpTab (iCode * ic)
11117 D (emitcode (";", "genJumpTab ");
11120 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11121 /* get the condition into accumulator */
11122 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11124 /* multiply by four! */
11125 emitcode ("add", "a,acc");
11126 emitcode ("add", "a,acc");
11127 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11129 jtab = newiTempLabel (NULL);
11130 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11131 emitcode ("jmp", "@a+dptr");
11132 emitcode ("", "!tlabeldef", jtab->key + 100);
11133 /* now generate the jump labels */
11134 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11135 jtab = setNextItem (IC_JTLABELS (ic)))
11136 emitcode ("ljmp", "!tlabel", jtab->key + 100);
11140 /*-----------------------------------------------------------------*/
11141 /* genCast - gen code for casting */
11142 /*-----------------------------------------------------------------*/
11144 genCast (iCode * ic)
11146 operand *result = IC_RESULT (ic);
11147 sym_link *ctype = operandType (IC_LEFT (ic));
11148 sym_link *rtype = operandType (IC_RIGHT (ic));
11149 operand *right = IC_RIGHT (ic);
11152 D (emitcode (";", "genCast "););
11154 /* if they are equivalent then do nothing */
11155 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11158 aopOp (right, ic, FALSE, FALSE);
11159 aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
11161 /* if the result is a bit */
11162 if (IS_BITVAR (OP_SYMBOL (result)->type)
11163 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11165 /* if the right size is a literal then
11166 we know what the value is */
11167 if (AOP_TYPE (right) == AOP_LIT)
11169 if (((int) operandLitValue (right)))
11170 aopPut (AOP (result), one, 0);
11172 aopPut (AOP (result), zero, 0);
11177 /* the right is also a bit variable */
11178 if (AOP_TYPE (right) == AOP_CRY)
11180 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11181 aopPut (AOP (result), "c", 0);
11185 /* we need to or */
11187 aopPut (AOP (result), "a", 0);
11191 /* if they are the same size : or less */
11192 if (AOP_SIZE (result) <= AOP_SIZE (right))
11195 /* if they are in the same place */
11196 if (sameRegs (AOP (right), AOP (result)))
11199 /* if they in different places then copy */
11200 size = AOP_SIZE (result);
11202 _startLazyDPSEvaluation ();
11205 aopPut (AOP (result),
11206 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11210 _endLazyDPSEvaluation ();
11215 /* if the result is of type pointer */
11216 if (IS_PTR (ctype))
11220 sym_link *type = operandType (right);
11222 /* pointer to generic pointer */
11223 if (IS_GENPTR (ctype))
11227 p_type = DCL_TYPE (type);
11231 #if OLD_CAST_BEHAVIOR
11232 /* KV: we are converting a non-pointer type to
11233 * a generic pointer. This (ifdef'd out) code
11234 * says that the resulting generic pointer
11235 * should have the same class as the storage
11236 * location of the non-pointer variable.
11238 * For example, converting an int (which happens
11239 * to be stored in DATA space) to a pointer results
11240 * in a DATA generic pointer; if the original int
11241 * in XDATA space, so will be the resulting pointer.
11243 * I don't like that behavior, and thus this change:
11244 * all such conversions will be forced to XDATA and
11245 * throw a warning. If you want some non-XDATA
11246 * type, or you want to suppress the warning, you
11247 * must go through an intermediate cast, like so:
11249 * char _generic *gp = (char _xdata *)(intVar);
11251 sym_link *etype = getSpec (type);
11253 /* we have to go by the storage class */
11254 if (SPEC_OCLS (etype) != generic)
11256 p_type = PTR_TYPE (SPEC_OCLS (etype));
11261 /* Converting unknown class (i.e. register variable)
11262 * to generic pointer. This is not good, but
11263 * we'll make a guess (and throw a warning).
11266 werror (W_INT_TO_GEN_PTR_CAST);
11270 /* the first two bytes are known */
11271 size = GPTRSIZE - 1;
11273 _startLazyDPSEvaluation ();
11276 aopPut (AOP (result),
11277 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11281 _endLazyDPSEvaluation ();
11283 /* the last byte depending on type */
11285 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11290 // pointerTypeToGPByte will have bitched.
11294 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11295 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11300 /* just copy the pointers */
11301 size = AOP_SIZE (result);
11303 _startLazyDPSEvaluation ();
11306 aopPut (AOP (result),
11307 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11311 _endLazyDPSEvaluation ();
11315 /* so we now know that the size of destination is greater
11316 than the size of the source */
11317 /* we move to result for the size of source */
11318 size = AOP_SIZE (right);
11320 _startLazyDPSEvaluation ();
11323 aopPut (AOP (result),
11324 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11328 _endLazyDPSEvaluation ();
11330 /* now depending on the sign of the source && destination */
11331 size = AOP_SIZE (result) - AOP_SIZE (right);
11332 /* if unsigned or not an integral type */
11333 /* also, if the source is a bit, we don't need to sign extend, because
11334 * it can't possibly have set the sign bit.
11336 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11340 aopPut (AOP (result), zero, offset++);
11345 /* we need to extend the sign :{ */
11346 MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11347 FALSE, FALSE, NULL));
11348 emitcode ("rlc", "a");
11349 emitcode ("subb", "a,acc");
11351 aopPut (AOP (result), "a", offset++);
11354 /* we are done hurray !!!! */
11357 freeAsmop (right, NULL, ic, TRUE);
11358 freeAsmop (result, NULL, ic, TRUE);
11362 /*-----------------------------------------------------------------*/
11363 /* genDjnz - generate decrement & jump if not zero instrucion */
11364 /*-----------------------------------------------------------------*/
11366 genDjnz (iCode * ic, iCode * ifx)
11368 symbol *lbl, *lbl1;
11372 /* if the if condition has a false label
11373 then we cannot save */
11374 if (IC_FALSE (ifx))
11377 /* if the minus is not of the form
11379 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11380 !IS_OP_LITERAL (IC_RIGHT (ic)))
11383 if (operandLitValue (IC_RIGHT (ic)) != 1)
11386 /* if the size of this greater than one then no
11388 if (getSize (operandType (IC_RESULT (ic))) > 1)
11391 /* otherwise we can save BIG */
11392 D(emitcode(";", "genDjnz"););
11394 lbl = newiTempLabel (NULL);
11395 lbl1 = newiTempLabel (NULL);
11397 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11399 if (AOP_NEEDSACC(IC_RESULT(ic)))
11401 /* If the result is accessed indirectly via
11402 * the accumulator, we must explicitly write
11403 * it back after the decrement.
11405 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11407 if (strcmp(rByte, "a"))
11409 /* Something is hopelessly wrong */
11410 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11411 __FILE__, __LINE__);
11412 /* We can just give up; the generated code will be inefficient,
11413 * but what the hey.
11415 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11418 emitcode ("dec", "%s", rByte);
11419 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11420 emitcode ("jnz", "!tlabel", lbl->key + 100);
11422 else if (IS_AOP_PREG (IC_RESULT (ic)))
11424 emitcode ("dec", "%s",
11425 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11426 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11427 emitcode ("jnz", "!tlabel", lbl->key + 100);
11431 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11434 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11435 emitcode ("", "!tlabeldef", lbl->key + 100);
11436 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11437 emitcode ("", "!tlabeldef", lbl1->key + 100);
11439 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11440 ifx->generated = 1;
11444 /*-----------------------------------------------------------------*/
11445 /* genReceive - generate code for a receive iCode */
11446 /*-----------------------------------------------------------------*/
11448 genReceive (iCode * ic)
11450 int size = getSize (operandType (IC_RESULT (ic)));
11454 D (emitcode (";", "genReceive "););
11456 if (ic->argreg == 1)
11458 /* first parameter */
11459 if (AOP_IS_STR(IC_RESULT(ic)))
11461 /* Nothing to do: it's already in the proper place. */
11468 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11469 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11470 IS_TRUE_SYMOP (IC_RESULT (ic)));
11473 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11476 /* Sanity checking... */
11477 if (AOP_USESDPTR(IC_RESULT(ic)))
11479 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11480 "genReceive got unexpected DPTR.");
11482 assignResultValue (IC_RESULT (ic));
11487 /* second receive onwards */
11488 /* this gets a little tricky since unused recevies will be
11489 eliminated, we have saved the reg in the type field . and
11490 we use that to figure out which register to use */
11491 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11492 rb1off = ic->argreg;
11495 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11498 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11501 /*-----------------------------------------------------------------*/
11502 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11503 /*-----------------------------------------------------------------*/
11504 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11506 operand *from , *to , *count;
11511 /* we know it has to be 3 parameters */
11512 assert (nparms == 3);
11514 rsave = newBitVect(16);
11515 /* save DPTR if it needs to be saved */
11516 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11517 if (bitVectBitValue(ic->rMask,i))
11518 rsave = bitVectSetBit(rsave,i);
11520 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11521 ds390_rUmaskForOp (IC_RESULT(ic))));
11528 aopOp (from, ic->next, FALSE, FALSE);
11530 /* get from into DPTR1 */
11531 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11532 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11533 if (options.model == MODEL_FLAT24) {
11534 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11537 freeAsmop (from, NULL, ic, FALSE);
11538 aopOp (to, ic, FALSE, FALSE);
11539 /* get "to" into DPTR */
11540 /* if the operand is already in dptr
11541 then we do nothing else we move the value to dptr */
11542 if (AOP_TYPE (to) != AOP_STR) {
11543 /* if already in DPTR then we need to push */
11544 if (AOP_TYPE(to) == AOP_DPTR) {
11545 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11546 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11547 if (options.model == MODEL_FLAT24)
11548 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11549 emitcode ("pop", "dph");
11550 emitcode ("pop", "dpl");
11552 _startLazyDPSEvaluation ();
11553 /* if this is remateriazable */
11554 if (AOP_TYPE (to) == AOP_IMMD) {
11555 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11556 } else { /* we need to get it byte by byte */
11557 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11558 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11559 if (options.model == MODEL_FLAT24) {
11560 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11563 _endLazyDPSEvaluation ();
11566 freeAsmop (to, NULL, ic, FALSE);
11567 _G.dptrInUse = _G.dptr1InUse = 1;
11568 aopOp (count, ic->next->next, FALSE,FALSE);
11569 lbl =newiTempLabel(NULL);
11571 /* now for the actual copy */
11572 if (AOP_TYPE(count) == AOP_LIT &&
11573 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11574 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11576 emitcode ("lcall","__bi_memcpyc2x_s");
11578 emitcode ("lcall","__bi_memcpyx2x_s");
11580 freeAsmop (count, NULL, ic, FALSE);
11582 symbol *lbl1 = newiTempLabel(NULL);
11584 emitcode (";"," Auto increment but no djnz");
11585 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11586 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11587 freeAsmop (count, NULL, ic, FALSE);
11588 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11589 emitcode ("","!tlabeldef",lbl->key+100);
11591 emitcode ("clr","a");
11592 emitcode ("movc", "a,@a+dptr");
11594 emitcode ("movx", "a,@dptr");
11595 emitcode ("movx", "@dptr,a");
11596 emitcode ("inc", "dptr");
11597 emitcode ("inc", "dptr");
11598 emitcode ("mov","a,b");
11599 emitcode ("orl","a,_ap");
11600 emitcode ("jz","!tlabel",lbl1->key+100);
11601 emitcode ("mov","a,_ap");
11602 emitcode ("add","a,#!constbyte",0xFF);
11603 emitcode ("mov","_ap,a");
11604 emitcode ("mov","a,b");
11605 emitcode ("addc","a,#!constbyte",0xFF);
11606 emitcode ("mov","b,a");
11607 emitcode ("sjmp","!tlabel",lbl->key+100);
11608 emitcode ("","!tlabeldef",lbl1->key+100);
11610 emitcode ("mov", "dps,#0");
11611 _G.dptrInUse = _G.dptr1InUse = 0;
11612 unsavermask(rsave);
11616 /*-----------------------------------------------------------------*/
11617 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
11618 /*-----------------------------------------------------------------*/
11619 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11621 operand *from , *to , *count;
11626 /* we know it has to be 3 parameters */
11627 assert (nparms == 3);
11629 rsave = newBitVect(16);
11630 /* save DPTR if it needs to be saved */
11631 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11632 if (bitVectBitValue(ic->rMask,i))
11633 rsave = bitVectSetBit(rsave,i);
11635 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11636 ds390_rUmaskForOp (IC_RESULT(ic))));
11643 aopOp (from, ic->next, FALSE, FALSE);
11645 /* get from into DPTR1 */
11646 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11647 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11648 if (options.model == MODEL_FLAT24) {
11649 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11652 freeAsmop (from, NULL, ic, FALSE);
11653 aopOp (to, ic, FALSE, FALSE);
11654 /* get "to" into DPTR */
11655 /* if the operand is already in dptr
11656 then we do nothing else we move the value to dptr */
11657 if (AOP_TYPE (to) != AOP_STR) {
11658 /* if already in DPTR then we need to push */
11659 if (AOP_TYPE(to) == AOP_DPTR) {
11660 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11661 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11662 if (options.model == MODEL_FLAT24)
11663 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11664 emitcode ("pop", "dph");
11665 emitcode ("pop", "dpl");
11667 _startLazyDPSEvaluation ();
11668 /* if this is remateriazable */
11669 if (AOP_TYPE (to) == AOP_IMMD) {
11670 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11671 } else { /* we need to get it byte by byte */
11672 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11673 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11674 if (options.model == MODEL_FLAT24) {
11675 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11678 _endLazyDPSEvaluation ();
11681 freeAsmop (to, NULL, ic, FALSE);
11682 _G.dptrInUse = _G.dptr1InUse = 1;
11683 aopOp (count, ic->next->next, FALSE,FALSE);
11684 lbl =newiTempLabel(NULL);
11685 lbl2 =newiTempLabel(NULL);
11687 /* now for the actual compare */
11688 if (AOP_TYPE(count) == AOP_LIT &&
11689 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11690 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11692 emitcode("lcall","__bi_memcmpc2x_s");
11694 emitcode("lcall","__bi_memcmpx2x_s");
11695 freeAsmop (count, NULL, ic, FALSE);
11696 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11697 aopPut(AOP(IC_RESULT(ic)),"a",0);
11698 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11700 symbol *lbl1 = newiTempLabel(NULL);
11702 emitcode("push","ar0");
11703 emitcode (";"," Auto increment but no djnz");
11704 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11705 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11706 freeAsmop (count, NULL, ic, FALSE);
11707 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11708 emitcode ("","!tlabeldef",lbl->key+100);
11710 emitcode ("clr","a");
11711 emitcode ("movc", "a,@a+dptr");
11713 emitcode ("movx", "a,@dptr");
11714 emitcode ("mov","r0,a");
11715 emitcode ("movx", "a,@dptr");
11716 emitcode ("clr","c");
11717 emitcode ("subb","a,r0");
11718 emitcode ("jnz","!tlabel",lbl2->key+100);
11719 emitcode ("inc", "dptr");
11720 emitcode ("inc", "dptr");
11721 emitcode ("mov","a,b");
11722 emitcode ("orl","a,_ap");
11723 emitcode ("jz","!tlabel",lbl1->key+100);
11724 emitcode ("mov","a,_ap");
11725 emitcode ("add","a,#!constbyte",0xFF);
11726 emitcode ("mov","_ap,a");
11727 emitcode ("mov","a,b");
11728 emitcode ("addc","a,#!constbyte",0xFF);
11729 emitcode ("mov","b,a");
11730 emitcode ("sjmp","!tlabel",lbl->key+100);
11731 emitcode ("","!tlabeldef",lbl1->key+100);
11732 emitcode ("clr","a");
11733 emitcode ("","!tlabeldef",lbl2->key+100);
11734 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11735 aopPut(AOP(IC_RESULT(ic)),"a",0);
11736 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11737 emitcode("pop","ar0");
11738 emitcode ("mov", "dps,#0");
11740 _G.dptrInUse = _G.dptr1InUse = 0;
11741 unsavermask(rsave);
11745 /*-----------------------------------------------------------------*/
11746 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11747 /* port, first parameter output area second parameter pointer to */
11748 /* port third parameter count */
11749 /*-----------------------------------------------------------------*/
11750 static void genInp( iCode *ic, int nparms, operand **parms)
11752 operand *from , *to , *count;
11757 /* we know it has to be 3 parameters */
11758 assert (nparms == 3);
11760 rsave = newBitVect(16);
11761 /* save DPTR if it needs to be saved */
11762 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11763 if (bitVectBitValue(ic->rMask,i))
11764 rsave = bitVectSetBit(rsave,i);
11766 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11767 ds390_rUmaskForOp (IC_RESULT(ic))));
11774 aopOp (from, ic->next, FALSE, FALSE);
11776 /* get from into DPTR1 */
11777 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11778 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11779 if (options.model == MODEL_FLAT24) {
11780 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11783 freeAsmop (from, NULL, ic, FALSE);
11784 aopOp (to, ic, FALSE, FALSE);
11785 /* get "to" into DPTR */
11786 /* if the operand is already in dptr
11787 then we do nothing else we move the value to dptr */
11788 if (AOP_TYPE (to) != AOP_STR) {
11789 /* if already in DPTR then we need to push */
11790 if (AOP_TYPE(to) == AOP_DPTR) {
11791 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11792 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11793 if (options.model == MODEL_FLAT24)
11794 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11795 emitcode ("pop", "dph");
11796 emitcode ("pop", "dpl");
11798 _startLazyDPSEvaluation ();
11799 /* if this is remateriazable */
11800 if (AOP_TYPE (to) == AOP_IMMD) {
11801 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11802 } else { /* we need to get it byte by byte */
11803 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11804 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11805 if (options.model == MODEL_FLAT24) {
11806 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11809 _endLazyDPSEvaluation ();
11812 freeAsmop (to, NULL, ic, FALSE);
11814 _G.dptrInUse = _G.dptr1InUse = 1;
11815 aopOp (count, ic->next->next, FALSE,FALSE);
11816 lbl =newiTempLabel(NULL);
11818 /* now for the actual copy */
11819 if (AOP_TYPE(count) == AOP_LIT &&
11820 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11821 emitcode (";","OH JOY auto increment with djnz (very fast)");
11822 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11823 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11824 freeAsmop (count, NULL, ic, FALSE);
11825 emitcode ("","!tlabeldef",lbl->key+100);
11826 emitcode ("movx", "a,@dptr"); /* read data from port */
11827 emitcode ("dec","dps"); /* switch to DPTR */
11828 emitcode ("movx", "@dptr,a"); /* save into location */
11829 emitcode ("inc", "dptr"); /* point to next area */
11830 emitcode ("inc","dps"); /* switch to DPTR2 */
11831 emitcode ("djnz","b,!tlabel",lbl->key+100);
11833 symbol *lbl1 = newiTempLabel(NULL);
11835 emitcode (";"," Auto increment but no djnz");
11836 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11837 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11838 freeAsmop (count, NULL, ic, FALSE);
11839 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11840 emitcode ("","!tlabeldef",lbl->key+100);
11841 emitcode ("movx", "a,@dptr");
11842 emitcode ("dec","dps"); /* switch to DPTR */
11843 emitcode ("movx", "@dptr,a");
11844 emitcode ("inc", "dptr");
11845 emitcode ("inc","dps"); /* switch to DPTR2 */
11846 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
11847 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11848 emitcode ("mov","a,b");
11849 emitcode ("orl","a,_ap");
11850 emitcode ("jz","!tlabel",lbl1->key+100);
11851 emitcode ("mov","a,_ap");
11852 emitcode ("add","a,#!constbyte",0xFF);
11853 emitcode ("mov","_ap,a");
11854 emitcode ("mov","a,b");
11855 emitcode ("addc","a,#!constbyte",0xFF);
11856 emitcode ("mov","b,a");
11857 emitcode ("sjmp","!tlabel",lbl->key+100);
11858 emitcode ("","!tlabeldef",lbl1->key+100);
11860 emitcode ("mov", "dps,#0");
11861 _G.dptrInUse = _G.dptr1InUse = 0;
11862 unsavermask(rsave);
11866 /*-----------------------------------------------------------------*/
11867 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11868 /* port, first parameter output area second parameter pointer to */
11869 /* port third parameter count */
11870 /*-----------------------------------------------------------------*/
11871 static void genOutp( iCode *ic, int nparms, operand **parms)
11873 operand *from , *to , *count;
11878 /* we know it has to be 3 parameters */
11879 assert (nparms == 3);
11881 rsave = newBitVect(16);
11882 /* save DPTR if it needs to be saved */
11883 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11884 if (bitVectBitValue(ic->rMask,i))
11885 rsave = bitVectSetBit(rsave,i);
11887 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11888 ds390_rUmaskForOp (IC_RESULT(ic))));
11895 aopOp (from, ic->next, FALSE, FALSE);
11897 /* get from into DPTR1 */
11898 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11899 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11900 if (options.model == MODEL_FLAT24) {
11901 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11904 freeAsmop (from, NULL, ic, FALSE);
11905 aopOp (to, ic, FALSE, FALSE);
11906 /* get "to" into DPTR */
11907 /* if the operand is already in dptr
11908 then we do nothing else we move the value to dptr */
11909 if (AOP_TYPE (to) != AOP_STR) {
11910 /* if already in DPTR then we need to push */
11911 if (AOP_TYPE(to) == AOP_DPTR) {
11912 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11913 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11914 if (options.model == MODEL_FLAT24)
11915 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11916 emitcode ("pop", "dph");
11917 emitcode ("pop", "dpl");
11919 _startLazyDPSEvaluation ();
11920 /* if this is remateriazable */
11921 if (AOP_TYPE (to) == AOP_IMMD) {
11922 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11923 } else { /* we need to get it byte by byte */
11924 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11925 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11926 if (options.model == MODEL_FLAT24) {
11927 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11930 _endLazyDPSEvaluation ();
11933 freeAsmop (to, NULL, ic, FALSE);
11935 _G.dptrInUse = _G.dptr1InUse = 1;
11936 aopOp (count, ic->next->next, FALSE,FALSE);
11937 lbl =newiTempLabel(NULL);
11939 /* now for the actual copy */
11940 if (AOP_TYPE(count) == AOP_LIT &&
11941 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11942 emitcode (";","OH JOY auto increment with djnz (very fast)");
11943 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11944 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11945 emitcode ("","!tlabeldef",lbl->key+100);
11946 emitcode ("movx", "a,@dptr"); /* read data from port */
11947 emitcode ("inc","dps"); /* switch to DPTR2 */
11948 emitcode ("movx", "@dptr,a"); /* save into location */
11949 emitcode ("inc", "dptr"); /* point to next area */
11950 emitcode ("dec","dps"); /* switch to DPTR */
11951 emitcode ("djnz","b,!tlabel",lbl->key+100);
11952 freeAsmop (count, NULL, ic, FALSE);
11954 symbol *lbl1 = newiTempLabel(NULL);
11956 emitcode (";"," Auto increment but no djnz");
11957 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11958 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11959 freeAsmop (count, NULL, ic, FALSE);
11960 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11961 emitcode ("","!tlabeldef",lbl->key+100);
11962 emitcode ("movx", "a,@dptr");
11963 emitcode ("inc", "dptr");
11964 emitcode ("inc","dps"); /* switch to DPTR2 */
11965 emitcode ("movx", "@dptr,a");
11966 emitcode ("dec","dps"); /* switch to DPTR */
11967 emitcode ("mov","a,b");
11968 emitcode ("orl","a,_ap");
11969 emitcode ("jz","!tlabel",lbl1->key+100);
11970 emitcode ("mov","a,_ap");
11971 emitcode ("add","a,#!constbyte",0xFF);
11972 emitcode ("mov","_ap,a");
11973 emitcode ("mov","a,b");
11974 emitcode ("addc","a,#!constbyte",0xFF);
11975 emitcode ("mov","b,a");
11976 emitcode ("sjmp","!tlabel",lbl->key+100);
11977 emitcode ("","!tlabeldef",lbl1->key+100);
11979 emitcode ("mov", "dps,#0");
11980 _G.dptrInUse = _G.dptr1InUse = 0;
11981 unsavermask(rsave);
11985 /*-----------------------------------------------------------------*/
11986 /* genSwapW - swap lower & high order bytes */
11987 /*-----------------------------------------------------------------*/
11988 static void genSwapW(iCode *ic, int nparms, operand **parms)
11992 assert (nparms==1);
11995 dest=IC_RESULT(ic);
11997 assert(getSize(operandType(src))==2);
11999 aopOp (src, ic, FALSE, FALSE);
12000 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
12002 MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
12004 freeAsmop (src, NULL, ic, FALSE);
12006 aopOp (dest,ic, FALSE, FALSE);
12007 aopPut(AOP(dest),"b",0);
12008 aopPut(AOP(dest),"a",1);
12009 freeAsmop (dest, NULL, ic, FALSE);
12012 /*-----------------------------------------------------------------*/
12013 /* genMemsetX - gencode for memSetX data */
12014 /*-----------------------------------------------------------------*/
12015 static void genMemsetX(iCode *ic, int nparms, operand **parms)
12017 operand *to , *val , *count;
12023 /* we know it has to be 3 parameters */
12024 assert (nparms == 3);
12030 /* save DPTR if it needs to be saved */
12031 rsave = newBitVect(16);
12032 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12033 if (bitVectBitValue(ic->rMask,i))
12034 rsave = bitVectSetBit(rsave,i);
12036 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12037 ds390_rUmaskForOp (IC_RESULT(ic))));
12040 aopOp (to, ic, FALSE, FALSE);
12041 /* get "to" into DPTR */
12042 /* if the operand is already in dptr
12043 then we do nothing else we move the value to dptr */
12044 if (AOP_TYPE (to) != AOP_STR) {
12045 /* if already in DPTR then we need to push */
12046 if (AOP_TYPE(to) == AOP_DPTR) {
12047 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12048 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12049 if (options.model == MODEL_FLAT24)
12050 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12051 emitcode ("pop", "dph");
12052 emitcode ("pop", "dpl");
12054 _startLazyDPSEvaluation ();
12055 /* if this is remateriazable */
12056 if (AOP_TYPE (to) == AOP_IMMD) {
12057 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12058 } else { /* we need to get it byte by byte */
12059 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12060 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12061 if (options.model == MODEL_FLAT24) {
12062 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12065 _endLazyDPSEvaluation ();
12068 freeAsmop (to, NULL, ic, FALSE);
12070 aopOp (val, ic->next->next, FALSE,FALSE);
12071 aopOp (count, ic->next->next, FALSE,FALSE);
12072 lbl =newiTempLabel(NULL);
12073 /* now for the actual copy */
12074 if (AOP_TYPE(count) == AOP_LIT &&
12075 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12076 l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
12077 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12079 emitcode ("","!tlabeldef",lbl->key+100);
12080 emitcode ("movx", "@dptr,a");
12081 emitcode ("inc", "dptr");
12082 emitcode ("djnz","b,!tlabel",lbl->key+100);
12084 symbol *lbl1 = newiTempLabel(NULL);
12086 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12087 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12088 emitcode ("","!tlabeldef",lbl->key+100);
12089 MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
12090 emitcode ("movx", "@dptr,a");
12091 emitcode ("inc", "dptr");
12092 emitcode ("mov","a,b");
12093 emitcode ("orl","a,_ap");
12094 emitcode ("jz","!tlabel",lbl1->key+100);
12095 emitcode ("mov","a,_ap");
12096 emitcode ("add","a,#!constbyte",0xFF);
12097 emitcode ("mov","_ap,a");
12098 emitcode ("mov","a,b");
12099 emitcode ("addc","a,#!constbyte",0xFF);
12100 emitcode ("mov","b,a");
12101 emitcode ("sjmp","!tlabel",lbl->key+100);
12102 emitcode ("","!tlabeldef",lbl1->key+100);
12104 freeAsmop (count, NULL, ic, FALSE);
12105 unsavermask(rsave);
12108 /*-----------------------------------------------------------------*/
12109 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12110 /*-----------------------------------------------------------------*/
12111 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12114 operand *pnum, *result;
12117 assert (nparms==1);
12118 /* save registers that need to be saved */
12119 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12120 ds390_rUmaskForOp (IC_RESULT(ic))));
12123 aopOp (pnum, ic, FALSE, FALSE);
12124 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12125 freeAsmop (pnum, NULL, ic, FALSE);
12126 emitcode ("lcall","NatLib_LoadPrimitive");
12127 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12128 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
12129 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12130 for (i = (size-1) ; i >= 0 ; i-- ) {
12131 emitcode ("push","a%s",javaRet[i]);
12133 for (i=0; i < size ; i++ ) {
12134 emitcode ("pop","a%s",
12135 aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12138 for (i = 0 ; i < size ; i++ ) {
12139 aopPut(AOP(result),javaRet[i],i);
12142 freeAsmop (result, NULL, ic, FALSE);
12143 unsavermask(rsave);
12146 /*-----------------------------------------------------------------*/
12147 /* genNatLibLoadPointer - calls TINI api function to load pointer */
12148 /*-----------------------------------------------------------------*/
12149 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12152 operand *pnum, *result;
12156 assert (nparms==1);
12157 /* save registers that need to be saved */
12158 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12159 ds390_rUmaskForOp (IC_RESULT(ic))));
12162 aopOp (pnum, ic, FALSE, FALSE);
12163 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12164 freeAsmop (pnum, NULL, ic, FALSE);
12165 emitcode ("lcall","NatLib_LoadPointer");
12166 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12167 if (AOP_TYPE(result)!=AOP_STR) {
12168 for (i = 0 ; i < size ; i++ ) {
12169 aopPut(AOP(result),fReturn[i],i);
12172 freeAsmop (result, NULL, ic, FALSE);
12173 unsavermask(rsave);
12176 /*-----------------------------------------------------------------*/
12177 /* genNatLibInstallStateBlock - */
12178 /*-----------------------------------------------------------------*/
12179 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
12180 operand **parms, const char *name)
12183 operand *psb, *handle;
12184 assert (nparms==2);
12186 /* save registers that need to be saved */
12187 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12188 ds390_rUmaskForOp (IC_RESULT(ic))));
12192 /* put pointer to state block into DPTR1 */
12193 aopOp (psb, ic, FALSE, FALSE);
12194 if (AOP_TYPE (psb) == AOP_IMMD) {
12195 emitcode ("mov","dps,#1");
12196 emitcode ("mov", "dptr,%s",
12197 aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12198 emitcode ("mov","dps,#0");
12200 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12201 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12202 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12204 freeAsmop (psb, NULL, ic, FALSE);
12206 /* put libraryID into DPTR */
12207 emitcode ("mov","dptr,#LibraryID");
12209 /* put handle into r3:r2 */
12210 aopOp (handle, ic, FALSE, FALSE);
12211 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12212 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12213 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12214 emitcode ("pop","ar3");
12215 emitcode ("pop","ar2");
12217 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12218 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12220 freeAsmop (psb, NULL, ic, FALSE);
12222 /* make the call */
12223 emitcode ("lcall","NatLib_Install%sStateBlock",name);
12225 /* put return value into place*/
12227 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12229 aopPut(AOP(IC_RESULT(ic)),"a",0);
12230 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12231 unsavermask(rsave);
12234 /*-----------------------------------------------------------------*/
12235 /* genNatLibRemoveStateBlock - */
12236 /*-----------------------------------------------------------------*/
12237 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12243 /* save registers that need to be saved */
12244 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12245 ds390_rUmaskForOp (IC_RESULT(ic))));
12247 /* put libraryID into DPTR */
12248 emitcode ("mov","dptr,#LibraryID");
12249 /* make the call */
12250 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12251 unsavermask(rsave);
12254 /*-----------------------------------------------------------------*/
12255 /* genNatLibGetStateBlock - */
12256 /*-----------------------------------------------------------------*/
12257 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12258 operand **parms,const char *name)
12261 symbol *lbl = newiTempLabel(NULL);
12264 /* save registers that need to be saved */
12265 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12266 ds390_rUmaskForOp (IC_RESULT(ic))));
12268 /* put libraryID into DPTR */
12269 emitcode ("mov","dptr,#LibraryID");
12270 /* make the call */
12271 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12272 emitcode ("jnz","!tlabel",lbl->key+100);
12274 /* put return value into place */
12275 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12276 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12277 emitcode ("push","ar3");
12278 emitcode ("push","ar2");
12279 emitcode ("pop","%s",
12280 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12281 emitcode ("pop","%s",
12282 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12284 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12285 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12287 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12288 emitcode ("","!tlabeldef",lbl->key+100);
12289 unsavermask(rsave);
12292 /*-----------------------------------------------------------------*/
12293 /* genMMMalloc - */
12294 /*-----------------------------------------------------------------*/
12295 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12296 int size, const char *name)
12301 symbol *lbl = newiTempLabel(NULL);
12303 assert (nparms == 1);
12304 /* save registers that need to be saved */
12305 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12306 ds390_rUmaskForOp (IC_RESULT(ic))));
12309 aopOp (bsize,ic,FALSE,FALSE);
12311 /* put the size in R4-R2 */
12312 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12313 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12314 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12316 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12317 emitcode("pop","ar4");
12319 emitcode("pop","ar3");
12320 emitcode("pop","ar2");
12322 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12323 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12325 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12328 freeAsmop (bsize, NULL, ic, FALSE);
12330 /* make the call */
12331 emitcode ("lcall","MM_%s",name);
12332 emitcode ("jz","!tlabel",lbl->key+100);
12333 emitcode ("mov","r2,#!constbyte",0xff);
12334 emitcode ("mov","r3,#!constbyte",0xff);
12335 emitcode ("","!tlabeldef",lbl->key+100);
12336 /* we don't care about the pointer : we just save the handle */
12337 rsym = OP_SYMBOL(IC_RESULT(ic));
12338 if (rsym->liveFrom != rsym->liveTo) {
12339 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12340 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12341 emitcode ("push","ar3");
12342 emitcode ("push","ar2");
12343 emitcode ("pop","%s",
12344 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12345 emitcode ("pop","%s",
12346 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12348 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12349 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12351 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12353 unsavermask(rsave);
12356 /*-----------------------------------------------------------------*/
12358 /*-----------------------------------------------------------------*/
12359 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12364 assert (nparms == 1);
12365 /* save registers that need to be saved */
12366 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12367 ds390_rUmaskForOp (IC_RESULT(ic))));
12370 aopOp (handle,ic,FALSE,FALSE);
12372 /* put the size in R4-R2 */
12373 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12374 emitcode("push","%s",
12375 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12376 emitcode("push","%s",
12377 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12378 emitcode("pop","ar3");
12379 emitcode("pop","ar2");
12381 emitcode ("mov","r2,%s",
12382 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12383 emitcode ("mov","r3,%s",
12384 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12386 freeAsmop (handle, NULL, ic, FALSE);
12388 /* make the call */
12389 emitcode ("lcall","MM_Deref");
12392 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12393 if (rsym->liveFrom != rsym->liveTo) {
12394 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12395 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12396 _startLazyDPSEvaluation ();
12398 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12399 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12400 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12402 _endLazyDPSEvaluation ();
12407 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12408 unsavermask(rsave);
12411 /*-----------------------------------------------------------------*/
12412 /* genMMUnrestrictedPersist - */
12413 /*-----------------------------------------------------------------*/
12414 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12419 assert (nparms == 1);
12420 /* save registers that need to be saved */
12421 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12422 ds390_rUmaskForOp (IC_RESULT(ic))));
12425 aopOp (handle,ic,FALSE,FALSE);
12427 /* put the size in R3-R2 */
12428 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12429 emitcode("push","%s",
12430 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12431 emitcode("push","%s",
12432 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12433 emitcode("pop","ar3");
12434 emitcode("pop","ar2");
12436 emitcode ("mov","r2,%s",
12437 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12438 emitcode ("mov","r3,%s",
12439 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12441 freeAsmop (handle, NULL, ic, FALSE);
12443 /* make the call */
12444 emitcode ("lcall","MM_UnrestrictedPersist");
12447 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12448 if (rsym->liveFrom != rsym->liveTo) {
12449 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12450 aopPut(AOP(IC_RESULT(ic)),"a",0);
12451 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12454 unsavermask(rsave);
12457 /*-----------------------------------------------------------------*/
12458 /* genSystemExecJavaProcess - */
12459 /*-----------------------------------------------------------------*/
12460 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12463 operand *handle, *pp;
12465 assert (nparms==2);
12466 /* save registers that need to be saved */
12467 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12468 ds390_rUmaskForOp (IC_RESULT(ic))));
12473 /* put the handle in R3-R2 */
12474 aopOp (handle,ic,FALSE,FALSE);
12475 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12476 emitcode("push","%s",
12477 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12478 emitcode("push","%s",
12479 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12480 emitcode("pop","ar3");
12481 emitcode("pop","ar2");
12483 emitcode ("mov","r2,%s",
12484 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12485 emitcode ("mov","r3,%s",
12486 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12488 freeAsmop (handle, NULL, ic, FALSE);
12490 /* put pointer in DPTR */
12491 aopOp (pp,ic,FALSE,FALSE);
12492 if (AOP_TYPE(pp) == AOP_IMMD) {
12493 emitcode ("mov", "dptr,%s",
12494 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12495 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12496 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12497 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12498 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12500 freeAsmop (handle, NULL, ic, FALSE);
12502 /* make the call */
12503 emitcode ("lcall","System_ExecJavaProcess");
12505 /* put result in place */
12507 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12508 if (rsym->liveFrom != rsym->liveTo) {
12509 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12510 aopPut(AOP(IC_RESULT(ic)),"a",0);
12511 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12515 unsavermask(rsave);
12518 /*-----------------------------------------------------------------*/
12519 /* genSystemRTCRegisters - */
12520 /*-----------------------------------------------------------------*/
12521 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12527 assert (nparms==1);
12528 /* save registers that need to be saved */
12529 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12530 ds390_rUmaskForOp (IC_RESULT(ic))));
12533 /* put pointer in DPTR */
12534 aopOp (pp,ic,FALSE,FALSE);
12535 if (AOP_TYPE (pp) == AOP_IMMD) {
12536 emitcode ("mov","dps,#1");
12537 emitcode ("mov", "dptr,%s",
12538 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12539 emitcode ("mov","dps,#0");
12541 emitcode ("mov","dpl1,%s",
12542 aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12543 emitcode ("mov","dph1,%s",
12544 aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12545 emitcode ("mov","dpx1,%s",
12546 aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12548 freeAsmop (pp, NULL, ic, FALSE);
12550 /* make the call */
12551 emitcode ("lcall","System_%sRTCRegisters",name);
12553 unsavermask(rsave);
12556 /*-----------------------------------------------------------------*/
12557 /* genSystemThreadSleep - */
12558 /*-----------------------------------------------------------------*/
12559 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12564 assert (nparms==1);
12565 /* save registers that need to be saved */
12566 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12567 ds390_rUmaskForOp (IC_RESULT(ic))));
12570 aopOp(to,ic,FALSE,FALSE);
12571 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12572 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12573 emitcode ("push","%s",
12574 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12575 emitcode ("push","%s",
12576 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12577 emitcode ("push","%s",
12578 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12579 emitcode ("push","%s",
12580 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12581 emitcode ("pop","ar3");
12582 emitcode ("pop","ar2");
12583 emitcode ("pop","ar1");
12584 emitcode ("pop","ar0");
12586 emitcode ("mov","r0,%s",
12587 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12588 emitcode ("mov","r1,%s",
12589 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12590 emitcode ("mov","r2,%s",
12591 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12592 emitcode ("mov","r3,%s",
12593 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12595 freeAsmop (to, NULL, ic, FALSE);
12597 /* suspend in acc */
12599 aopOp(s,ic,FALSE,FALSE);
12600 emitcode ("mov","a,%s",
12601 aopGet(AOP(s),0,FALSE,TRUE,NULL));
12602 freeAsmop (s, NULL, ic, FALSE);
12604 /* make the call */
12605 emitcode ("lcall","System_%s",name);
12607 unsavermask(rsave);
12610 /*-----------------------------------------------------------------*/
12611 /* genSystemThreadResume - */
12612 /*-----------------------------------------------------------------*/
12613 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12618 assert (nparms==2);
12619 /* save registers that need to be saved */
12620 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12621 ds390_rUmaskForOp (IC_RESULT(ic))));
12627 aopOp(pid,ic,FALSE,FALSE);
12628 emitcode ("mov","r0,%s",
12629 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12630 freeAsmop (pid, NULL, ic, FALSE);
12633 aopOp(tid,ic,FALSE,FALSE);
12634 emitcode ("mov","a,%s",
12635 aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12636 freeAsmop (tid, NULL, ic, FALSE);
12638 emitcode ("lcall","System_ThreadResume");
12640 /* put result into place */
12642 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12643 if (rsym->liveFrom != rsym->liveTo) {
12644 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12645 aopPut(AOP(IC_RESULT(ic)),"a",0);
12646 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12649 unsavermask(rsave);
12652 /*-----------------------------------------------------------------*/
12653 /* genSystemProcessResume - */
12654 /*-----------------------------------------------------------------*/
12655 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12660 assert (nparms==1);
12661 /* save registers that need to be saved */
12662 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12663 ds390_rUmaskForOp (IC_RESULT(ic))));
12668 aopOp(pid,ic,FALSE,FALSE);
12669 emitcode ("mov","a,%s",
12670 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12671 freeAsmop (pid, NULL, ic, FALSE);
12673 emitcode ("lcall","System_ProcessResume");
12675 unsavermask(rsave);
12678 /*-----------------------------------------------------------------*/
12680 /*-----------------------------------------------------------------*/
12681 static void genSystem (iCode *ic,int nparms,char *name)
12683 assert(nparms == 0);
12685 emitcode ("lcall","System_%s",name);
12688 /*-----------------------------------------------------------------*/
12689 /* genSystemPoll - */
12690 /*-----------------------------------------------------------------*/
12691 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12696 assert (nparms==1);
12697 /* save registers that need to be saved */
12698 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12699 ds390_rUmaskForOp (IC_RESULT(ic))));
12702 aopOp (fp,ic,FALSE,FALSE);
12703 if (AOP_TYPE (fp) == AOP_IMMD) {
12704 emitcode ("mov", "dptr,%s",
12705 aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12706 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12707 emitcode ("mov","dpl,%s",
12708 aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12709 emitcode ("mov","dph,%s",
12710 aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12711 emitcode ("mov","dpx,%s",
12712 aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12714 freeAsmop (fp, NULL, ic, FALSE);
12716 emitcode ("lcall","System_%sPoll",name);
12718 /* put result into place */
12720 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12721 if (rsym->liveFrom != rsym->liveTo) {
12722 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12723 aopPut(AOP(IC_RESULT(ic)),"a",0);
12724 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12727 unsavermask(rsave);
12730 /*-----------------------------------------------------------------*/
12731 /* genSystemGetCurrentID - */
12732 /*-----------------------------------------------------------------*/
12733 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12735 assert (nparms==0);
12737 emitcode ("lcall","System_GetCurrent%sId",name);
12738 /* put result into place */
12740 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12741 if (rsym->liveFrom != rsym->liveTo) {
12742 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12743 aopPut(AOP(IC_RESULT(ic)),"a",0);
12744 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12749 /*-----------------------------------------------------------------*/
12750 /* genDummyRead - generate code for dummy read of volatiles */
12751 /*-----------------------------------------------------------------*/
12753 genDummyRead (iCode * ic)
12758 D(emitcode("; genDummyRead",""));
12760 op = IC_RIGHT (ic);
12761 if (op && IS_SYMOP (op))
12763 aopOp (op, ic, FALSE, FALSE);
12765 /* if the result is a bit */
12766 if (AOP_TYPE (op) == AOP_CRY)
12767 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
12770 /* bit variables done */
12772 size = AOP_SIZE (op);
12776 MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
12781 freeAsmop (op, NULL, ic, TRUE);
12785 if (op && IS_SYMOP (op))
12787 aopOp (op, ic, FALSE, FALSE);
12789 /* if the result is a bit */
12790 if (AOP_TYPE (op) == AOP_CRY)
12791 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
12794 /* bit variables done */
12796 size = AOP_SIZE (op);
12800 MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
12805 freeAsmop (op, NULL, ic, TRUE);
12810 /*-----------------------------------------------------------------*/
12811 /* genCritical - generate code for start of a critical sequence */
12812 /*-----------------------------------------------------------------*/
12814 genCritical (iCode *ic)
12816 symbol *tlbl = newiTempLabel (NULL);
12818 D(emitcode("; genCritical",""));
12820 if (IC_RESULT (ic))
12821 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
12823 emitcode ("setb", "c");
12824 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
12825 emitcode ("clr", "c");
12826 emitcode ("", "%05d$:", (tlbl->key + 100));
12828 if (IC_RESULT (ic))
12829 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
12831 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
12833 if (IC_RESULT (ic))
12834 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
12837 /*-----------------------------------------------------------------*/
12838 /* genEndCritical - generate code for end of a critical sequence */
12839 /*-----------------------------------------------------------------*/
12841 genEndCritical (iCode *ic)
12843 D(emitcode("; genEndCritical",""));
12847 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
12848 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
12850 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
12851 emitcode ("mov", "ea,c");
12855 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE));
12856 emitcode ("rrc", "a");
12857 emitcode ("mov", "ea,c");
12859 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
12863 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
12864 emitcode ("mov", "ea,c");
12870 /*-----------------------------------------------------------------*/
12871 /* genBuiltIn - calls the appropriate function to generating code */
12872 /* for a built in function */
12873 /*-----------------------------------------------------------------*/
12874 static void genBuiltIn (iCode *ic)
12876 operand *bi_parms[MAX_BUILTIN_ARGS];
12881 /* get all the arguments for a built in function */
12882 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12884 /* which function is it */
12885 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12886 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12887 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12888 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12889 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12890 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12891 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12892 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12893 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12894 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12895 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12896 } else if (strcmp(bif->name,"__builtin_inp")==0) {
12897 genInp(bi_iCode,nbi_parms,bi_parms);
12898 } else if (strcmp(bif->name,"__builtin_outp")==0) {
12899 genOutp(bi_iCode,nbi_parms,bi_parms);
12900 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12901 genSwapW(bi_iCode,nbi_parms,bi_parms);
12902 /* JavaNative builtIns */
12903 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12904 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12905 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12906 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12907 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12908 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12909 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12910 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12911 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12912 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12913 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12914 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12915 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12916 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12917 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12918 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12919 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12920 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12921 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12922 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12923 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12924 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12925 } else if (strcmp(bif->name,"MM_Malloc")==0) {
12926 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12927 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12928 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12929 } else if (strcmp(bif->name,"MM_Free")==0) {
12930 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12931 } else if (strcmp(bif->name,"MM_Deref")==0) {
12932 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12933 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12934 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12935 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12936 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12937 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12938 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12939 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12940 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12941 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12942 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12943 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12944 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12945 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12946 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12947 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12948 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12949 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12950 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12951 } else if (strcmp(bif->name,"System_SaveThread")==0) {
12952 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12953 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12954 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12955 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12956 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12957 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12958 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12959 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12960 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12961 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12962 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12963 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12964 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12965 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12966 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12967 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12968 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12969 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12970 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12971 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12972 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12974 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12980 /*-----------------------------------------------------------------*/
12981 /* gen390Code - generate code for Dallas 390 based controllers */
12982 /*-----------------------------------------------------------------*/
12984 gen390Code (iCode * lic)
12989 lineHead = lineCurr = NULL;
12990 dptrn[1][0] = "dpl1";
12991 dptrn[1][1] = "dph1";
12992 dptrn[1][2] = "dpx1";
12994 if (options.model == MODEL_FLAT24) {
12995 fReturnSizeDS390 = 5;
12996 fReturn = fReturn24;
12998 fReturnSizeDS390 = 4;
12999 fReturn = fReturn16;
13000 options.stack10bit=0;
13003 /* print the allocation information */
13004 if (allocInfo && currFunc)
13005 printAllocInfo (currFunc, codeOutFile);
13007 /* if debug information required */
13008 if (options.debug && currFunc)
13010 debugFile->writeFunction(currFunc);
13012 if (IS_STATIC (currFunc->etype))
13013 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
13015 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
13018 /* stack pointer name */
13019 if (options.useXstack)
13025 for (ic = lic; ic; ic = ic->next)
13028 if (ic->lineno && cln != ic->lineno)
13033 emitcode ("", "C$%s$%d$%d$%d ==.",
13034 FileBaseName (ic->filename), ic->lineno,
13035 ic->level, ic->block);
13038 if (!options.noCcodeInAsm) {
13039 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
13040 printCLine(ic->filename, ic->lineno));
13044 if (options.iCodeInAsm) {
13045 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
13047 /* if the result is marked as
13048 spilt and rematerializable or code for
13049 this has already been generated then
13051 if (resultRemat (ic) || ic->generated)
13054 /* depending on the operation */
13074 /* IPOP happens only when trying to restore a
13075 spilt live range, if there is an ifx statement
13076 following this pop then the if statement might
13077 be using some of the registers being popped which
13078 would destory the contents of the register so
13079 we need to check for this condition and handle it */
13081 ic->next->op == IFX &&
13082 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
13083 genIfx (ic->next, ic);
13101 genEndFunction (ic);
13121 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
13138 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
13142 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
13149 /* note these two are xlated by algebraic equivalence
13150 during parsing SDCC.y */
13151 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13152 "got '>=' or '<=' shouldn't have come here");
13156 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
13168 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
13172 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
13176 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
13200 genRightShift (ic);
13203 case GET_VALUE_AT_ADDRESS:
13204 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13208 if (POINTER_SET (ic))
13209 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13235 if (ic->builtinSEND) genBuiltIn(ic);
13236 else addSet (&_G.sendSet, ic);
13239 case DUMMY_READ_VOLATILE:
13248 genEndCritical (ic);
13255 #if 0 // obsolete, and buggy for != xdata
13267 /* now we are ready to call the
13268 peep hole optimizer */
13269 if (!options.nopeep)
13270 peepHole (&lineHead);
13272 /* now do the actual printing */
13273 printLine (lineHead, codeOutFile);