1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for DS80C390
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 DS390 adaptation by Kevin Vigor <kevin@vigor.nu>
9 This program is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 In other words, you are welcome to use, share and improve this program.
24 You are forbidden to forbid anyone else to use, share and improve
25 what you give them. Help stamp out software-hoarding!
26 -------------------------------------------------------------------------*/
36 #include "SDCCglobl.h"
39 #define BETTER_LITERAL_SHIFT
41 char *aopLiteral (value * val, int offset);
44 /* this is the down and dirty file with all kinds of
45 kludgy & hacky stuff. This is what it is all about
46 CODE GENERATION for a specific MCU . some of the
47 routines may be reusable, will have to see */
49 static char *zero = "#0";
50 static char *one = "#1";
55 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
56 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
58 unsigned fReturnSizeDS390 = 5; /* shared with ralloc.c */
59 static char *fReturn24[] =
60 {"dpl", "dph", "dpx", "b", "a"};
61 static char *fReturn16[] =
62 {"dpl", "dph", "b", "a"};
63 static char **fReturn = fReturn24;
64 static char *accUse[] =
66 static char *dptrn[2][3];
67 static char *javaRet[] = { "r0","r1","r2","r3"};
68 static short rbank = -1;
85 static char *rb1regs[] = {
86 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
89 static void saveRBank (int, iCode *, bool);
91 #define RESULTONSTACK(x) \
92 (IC_RESULT(x) && IC_RESULT(x)->aop && \
93 IC_RESULT(x)->aop->type == AOP_STK )
95 #define MOVA(x) _movA(x)
96 #define MOVB(x) _movB(x)
98 #define CLRC emitcode("clr","c")
99 #define SETC emitcode("setb","c")
101 // A scratch register which will be used to hold
102 // result bytes from operands in far space via DPTR2.
103 #define DP2_RESULT_REG "_ap"
105 static lineNode *lineHead = NULL;
106 static lineNode *lineCurr = NULL;
108 static unsigned char SLMask[] =
109 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
110 0xE0, 0xC0, 0x80, 0x00};
111 static unsigned char SRMask[] =
112 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
113 0x07, 0x03, 0x01, 0x00};
119 #define PROTECT_SP {if (options.protect_sp_update) { \
120 symbol *lbl = newiTempLabel(NULL); \
121 emitcode ("setb","F1"); \
122 emitcode ("jbc","EA,!tlabel",lbl->key+100); \
123 emitcode ("clr","F1"); \
124 emitcode ("","!tlabeldef",lbl->key+100); \
126 #define UNPROTECT_SP { if (options.protect_sp_update) { \
127 symbol *lbl = newiTempLabel(NULL); \
128 emitcode ("jnb","F1,!tlabel",lbl->key+100); \
129 emitcode ("setb","EA"); \
130 emitcode ("","!tlabeldef",lbl->key+100); \
134 /*-----------------------------------------------------------------*/
135 /* emitcode - writes the code into a file : for now it is simple */
136 /*-----------------------------------------------------------------*/
138 emitcode (char *inst, char *fmt,...)
141 char lb[INITIAL_INLINEASM];
150 SNPRINTF (lb, sizeof(lb), "%s\t", inst);
154 SNPRINTF (lb, sizeof(lb), "%s", inst);
157 tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb),
162 tvsprintf (lb, sizeof(lb), fmt, ap);
166 while (isspace (*lbp))
173 lineCurr = (lineCurr ?
174 connectLine (lineCurr, newLineNode (lb)) :
175 (lineHead = newLineNode (lb)));
178 lineCurr->isInline = _G.inLine;
179 lineCurr->isDebug = _G.debugLine;
184 // Move the passed value into A unless it is already there.
189 if (strcmp(s,"a") && strcmp(s,"acc"))
191 emitcode("mov","a,%s",s);
196 // Move the passed value into B unless it is already there.
203 emitcode("mov","b,%s",s);
207 /*-----------------------------------------------------------------*/
208 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
209 /*-----------------------------------------------------------------*/
211 getFreePtr (iCode * ic, asmop ** aopp, bool result)
216 /* the logic: if r0 & r1 used in the instruction
217 then we are in trouble otherwise */
219 /* first check if r0 & r1 are used by this
220 instruction, in which case we are in trouble */
221 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
222 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
227 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
228 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
230 /* if no usage of r0 then return it */
233 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
234 (*aopp)->type = AOP_R0;
236 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
239 /* if no usage of r1 then return it */
242 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
243 (*aopp)->type = AOP_R1;
245 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
248 /* now we know they both have usage */
249 /* if r0 not used in this instruction */
252 /* push it if not already pushed */
255 emitcode ("push", "%s",
256 ds390_regWithIdx (R0_IDX)->dname);
260 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
261 (*aopp)->type = AOP_R0;
263 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
266 /* if r1 not used then */
270 /* push it if not already pushed */
273 emitcode ("push", "%s",
274 ds390_regWithIdx (R1_IDX)->dname);
278 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
279 (*aopp)->type = AOP_R1;
280 return ds390_regWithIdx (R1_IDX);
284 /* I said end of world but not quite end of world yet */
285 /* if this is a result then we can push it on the stack */
288 (*aopp)->type = AOP_STK;
292 /* other wise this is true end of the world */
293 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
294 "getFreePtr should never reach here");
297 return NULL; // notreached, but makes compiler happy.
300 /*-----------------------------------------------------------------*/
301 /* newAsmop - creates a new asmOp */
302 /*-----------------------------------------------------------------*/
304 newAsmop (short type)
308 aop = Safe_calloc (1, sizeof (asmop));
313 static int _currentDPS; /* Current processor DPS. */
314 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
315 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
317 /*-----------------------------------------------------------------*/
318 /* genSetDPTR: generate code to select which DPTR is in use (zero */
319 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
320 /* alternate DPTR (DPL1/DPH1/DPX1). */
321 /*-----------------------------------------------------------------*/
326 /* If we are doing lazy evaluation, simply note the desired
327 * change, but don't emit any code yet.
337 emitcode ("mov", "dps,#0");
342 emitcode ("mov", "dps,#1");
346 /*-----------------------------------------------------------------*/
347 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
349 /* Any code that operates on DPTR (NB: not on the individual */
350 /* components, like DPH) *must* call _flushLazyDPS() before using */
351 /* DPTR within a lazy DPS evaluation block. */
353 /* Note that aopPut and aopGet already contain the proper calls to */
354 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
355 /* DPS evaluation block. */
357 /* Also, _flushLazyDPS must be called before any flow control */
358 /* operations that could potentially branch out of the block. */
360 /* Lazy DPS evaluation is simply an optimization (though an */
361 /* important one), so if in doubt, leave it out. */
362 /*-----------------------------------------------------------------*/
364 _startLazyDPSEvaluation (void)
368 #ifdef BETTER_LITERAL_SHIFT
375 /*-----------------------------------------------------------------*/
376 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
377 /* desired one. Call before using DPTR within a lazy DPS evaluation */
379 /*-----------------------------------------------------------------*/
389 if (_desiredDPS != _currentDPS)
393 emitcode ("inc", "dps");
397 emitcode ("dec", "dps");
399 _currentDPS = _desiredDPS;
403 /*-----------------------------------------------------------------*/
404 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
406 /* Forces us back to the safe state (standard DPTR selected). */
407 /*-----------------------------------------------------------------*/
409 _endLazyDPSEvaluation (void)
411 #ifdef BETTER_LITERAL_SHIFT
430 /*-----------------------------------------------------------------*/
431 /* pointerCode - returns the code for a pointer type */
432 /*-----------------------------------------------------------------*/
434 pointerCode (sym_link * etype)
437 return PTR_TYPE (SPEC_OCLS (etype));
441 /*-----------------------------------------------------------------*/
442 /* leftRightUseAcc - returns size of accumulator use by operands */
443 /*-----------------------------------------------------------------*/
445 leftRightUseAcc(iCode *ic)
454 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
455 "null iCode pointer");
462 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
465 size = getSize (OP_SYMBOL (op)->type);
470 else if (ic->op == JUMPTABLE)
473 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
476 size = getSize (OP_SYMBOL (op)->type);
484 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
487 size = getSize (OP_SYMBOL (op)->type);
492 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
495 size = getSize (OP_SYMBOL (op)->type);
507 /*-----------------------------------------------------------------*/
508 /* aopForSym - for a true symbol */
509 /*-----------------------------------------------------------------*/
511 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
514 memmap *space = SPEC_OCLS (sym->etype);
515 int accuse = leftRightUseAcc (ic);
517 /* if already has one */
520 if ((sym->aop->type == AOP_DPTR && useDP2)
521 || (sym->aop->type == AOP_DPTR2 && !useDP2))
527 /* assign depending on the storage class */
528 /* if it is on the stack or indirectly addressable */
529 /* space we need to assign either r0 or r1 to it */
530 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
532 sym->aop = aop = newAsmop (0);
533 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
534 aop->size = getSize (sym->type);
536 /* now assign the address of the variable to
537 the pointer register */
538 if (aop->type != AOP_STK)
543 if (_G.accInUse || accuse)
544 emitcode ("push", "acc");
546 if (_G.bInUse || (accuse>1))
547 emitcode ("push", "b");
549 emitcode ("mov", "a,_bp");
550 emitcode ("add", "a,#!constbyte",
552 ((char) (sym->stack - _G.nRegsSaved)) :
553 ((char) sym->stack)) & 0xff);
554 emitcode ("mov", "%s,a",
555 aop->aopu.aop_ptr->name);
557 if (_G.bInUse || (accuse>1))
558 emitcode ("pop", "b");
560 if (_G.accInUse || accuse)
561 emitcode ("pop", "acc");
564 emitcode ("mov", "%s,#%s",
565 aop->aopu.aop_ptr->name,
567 aop->paged = space->paged;
570 aop->aopu.aop_stk = sym->stack;
574 if (sym->onStack && options.stack10bit)
576 short stack_val = -((sym->stack < 0) ?
577 ((short) (sym->stack - _G.nRegsSaved)) :
578 ((short) sym->stack)) ;
579 if (useDP2 && _G.dptr1InUse) {
580 emitcode ("push","dpl1");
581 emitcode ("push","dph1");
582 emitcode ("push","dpx1");
583 } else if (_G.dptrInUse ) {
584 emitcode ("push","dpl");
585 emitcode ("push","dph");
586 emitcode ("push","dpx");
588 /* It's on the 10 bit stack, which is located in
591 if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
593 if (options.model == MODEL_FLAT24)
595 emitcode ("mov", "dpx1,#!constbyte",
596 (options.stack_loc >> 16) & 0xff);
598 emitcode ("mov", "dph1,_bpx+1");
600 emitcode ("mov", "dpl1,_bpx");
601 emitcode ("mov","dps,#1");
603 if (options.model == MODEL_FLAT24)
605 emitcode ("mov", "dpx,#!constbyte",
606 (options.stack_loc >> 16) & 0xff);
608 emitcode ("mov", "dph,_bpx+1");
609 emitcode ("mov", "dpl,_bpx");
611 stack_val = -stack_val;
612 while (stack_val--) {
613 emitcode ("inc","dptr");
616 emitcode("mov","dps,#0");
619 if (_G.accInUse || accuse)
620 emitcode ("push", "acc");
622 if (_G.bInUse || (accuse>1))
623 emitcode ("push", "b");
625 emitcode ("mov", "a,_bpx");
626 emitcode ("clr","c");
627 emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
628 emitcode ("mov","b,a");
629 emitcode ("mov","a,_bpx+1");
630 emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
632 if (options.model == MODEL_FLAT24)
634 emitcode ("mov", "dpx1,#!constbyte",
635 (options.stack_loc >> 16) & 0xff);
637 emitcode ("mov", "dph1,a");
638 emitcode ("mov", "dpl1,b");
640 if (options.model == MODEL_FLAT24)
642 emitcode ("mov", "dpx,#!constbyte",
643 (options.stack_loc >> 16) & 0xff);
645 emitcode ("mov", "dph,a");
646 emitcode ("mov", "dpl,b");
649 if (_G.bInUse || (accuse>1))
650 emitcode ("pop", "b");
652 if (_G.accInUse || accuse)
653 emitcode ("pop", "acc");
655 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
656 aop->size = getSize (sym->type);
660 /* if in bit space */
661 if (IN_BITSPACE (space))
663 sym->aop = aop = newAsmop (AOP_CRY);
664 aop->aopu.aop_dir = sym->rname;
665 aop->size = getSize (sym->type);
668 /* if it is in direct space */
669 if (IN_DIRSPACE (space))
671 sym->aop = aop = newAsmop (AOP_DIR);
672 aop->aopu.aop_dir = sym->rname;
673 aop->size = getSize (sym->type);
677 /* special case for a function */
678 if (IS_FUNC (sym->type) && !(sym->isitmp))
680 sym->aop = aop = newAsmop (AOP_IMMD);
681 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
682 aop->size = FPTRSIZE;
686 /* only remaining is far space */
687 /* in which case DPTR gets the address */
688 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
693 emitcode ("mov", "dptr,#%s", sym->rname);
698 emitcode ("mov", "dptr,#%s", sym->rname);
700 aop->size = getSize (sym->type);
702 /* if it is in code space */
703 if (IN_CODESPACE (space))
709 /*-----------------------------------------------------------------*/
710 /* aopForRemat - rematerialzes an object */
711 /*-----------------------------------------------------------------*/
713 aopForRemat (symbol * sym)
715 iCode *ic = sym->rematiCode;
716 asmop *aop = newAsmop (AOP_IMMD);
723 val += (int) operandLitValue (IC_RIGHT (ic));
724 else if (ic->op == '-')
725 val -= (int) operandLitValue (IC_RIGHT (ic));
726 else if (IS_CAST_ICODE(ic)) {
727 sym_link *from_type = operandType(IC_RIGHT(ic));
728 aop->aopu.aop_immd.from_cast_remat = 1;
729 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
730 ptr_type = DCL_TYPE(from_type);
731 if (ptr_type == IPOINTER) {
738 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
743 SNPRINTF (buffer, sizeof(buffer),
745 OP_SYMBOL (IC_LEFT (ic))->rname,
746 val >= 0 ? '+' : '-',
747 abs (val) & 0xffffff);
751 if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
753 SNPRINTF(buffer, sizeof(buffer),
754 "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
758 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
762 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
763 /* set immd2 field if required */
764 if (aop->aopu.aop_immd.from_cast_remat)
766 tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
767 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
773 /*-----------------------------------------------------------------*/
774 /* aopHasRegs - returns true if aop has regs between from-to */
775 /*-----------------------------------------------------------------*/
776 static int aopHasRegs(asmop *aop, int from, int to)
780 if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
782 for (; size < aop->size ; size++) {
784 for (reg = from ; reg <= to ; reg++)
785 if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
790 /*-----------------------------------------------------------------*/
791 /* regsInCommon - two operands have some registers in common */
792 /*-----------------------------------------------------------------*/
794 regsInCommon (operand * op1, operand * op2)
799 /* if they have registers in common */
800 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
803 sym1 = OP_SYMBOL (op1);
804 sym2 = OP_SYMBOL (op2);
806 if (sym1->nRegs == 0 || sym2->nRegs == 0)
809 for (i = 0; i < sym1->nRegs; i++)
815 for (j = 0; j < sym2->nRegs; j++)
820 if (sym2->regs[j] == sym1->regs[i])
828 /*-----------------------------------------------------------------*/
829 /* operandsEqu - equivalent */
830 /*-----------------------------------------------------------------*/
832 operandsEqu (operand * op1, operand * op2)
836 /* if they not symbols */
837 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
840 sym1 = OP_SYMBOL (op1);
841 sym2 = OP_SYMBOL (op2);
843 /* if both are itemps & one is spilt
844 and the other is not then false */
845 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
846 sym1->isspilt != sym2->isspilt)
849 /* if they are the same */
853 if (strcmp (sym1->rname, sym2->rname) == 0)
857 /* if left is a tmp & right is not */
858 if (IS_ITEMP (op1) &&
861 (sym1->usl.spillLoc == sym2))
864 if (IS_ITEMP (op2) &&
868 (sym2->usl.spillLoc == sym1))
871 /* are they spilt to the same location */
872 if (IS_ITEMP (op2) &&
876 (sym1->usl.spillLoc == sym2->usl.spillLoc))
882 /*-----------------------------------------------------------------*/
883 /* sameRegs - two asmops have the same registers */
884 /*-----------------------------------------------------------------*/
886 sameRegs (asmop * aop1, asmop * aop2)
892 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
899 if (aop1->type != AOP_REG ||
900 aop2->type != AOP_REG)
903 if (aop1->size != aop2->size)
906 for (i = 0; i < aop1->size; i++)
907 if (aop1->aopu.aop_reg[i] !=
908 aop2->aopu.aop_reg[i])
914 /*-----------------------------------------------------------------*/
915 /* aopOp - allocates an asmop for an operand : */
916 /*-----------------------------------------------------------------*/
918 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
927 /* if this a literal */
928 if (IS_OP_LITERAL (op))
930 op->aop = aop = newAsmop (AOP_LIT);
931 aop->aopu.aop_lit = op->operand.valOperand;
932 aop->size = getSize (operandType (op));
936 /* if already has a asmop then continue */
939 if ((op->aop->type == AOP_DPTR && useDP2)
940 || (op->aop->type == AOP_DPTR2 && !useDP2))
946 /* if the underlying symbol has a aop */
947 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
949 op->aop = OP_SYMBOL (op)->aop;
950 if ((op->aop->type == AOP_DPTR && useDP2)
951 || (op->aop->type == AOP_DPTR2 && !useDP2))
957 /* if this is a true symbol */
958 if (IS_TRUE_SYMOP (op))
960 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
964 /* this is a temporary : this has
970 e) can be a return use only */
972 sym = OP_SYMBOL (op);
975 /* if the type is a conditional */
976 if (sym->regType == REG_CND)
978 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
983 /* if it is spilt then two situations
985 b) has a spill location */
986 if (sym->isspilt || sym->nRegs == 0)
989 /* rematerialize it NOW */
992 sym->aop = op->aop = aop =
994 aop->size = getSize (sym->type);
1001 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
1002 aop->size = getSize (sym->type);
1003 for (i = 0; i < 2; i++)
1004 aop->aopu.aop_str[i] = accUse[i];
1014 /* a AOP_STR uses DPTR, but DPTR is already in use;
1017 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
1020 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1021 aop->size = getSize (sym->type);
1022 for (i = 0; i < (int) fReturnSizeDS390; i++)
1023 aop->aopu.aop_str[i] = fReturn[i];
1027 if (sym->dptr) { /* has been allocated to a DPTRn */
1028 aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
1029 aop->size = getSize (sym->type);
1030 aop->aopu.dptr = sym->dptr;
1034 if (sym->usl.spillLoc)
1036 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1038 /* force a new aop if sizes differ */
1039 sym->usl.spillLoc->aop = NULL;
1041 sym->aop = op->aop = aop =
1042 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
1043 aop->size = getSize (sym->type);
1047 /* else must be a dummy iTemp */
1048 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1049 aop->size = getSize (sym->type);
1053 /* must be in a register */
1054 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1055 aop->size = sym->nRegs;
1056 for (i = 0; i < sym->nRegs; i++)
1057 aop->aopu.aop_reg[i] = sym->regs[i];
1060 /*-----------------------------------------------------------------*/
1061 /* freeAsmop - free up the asmop given to an operand */
1062 /*----------------------------------------------------------------*/
1064 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1081 /* depending on the asmop type only three cases need work AOP_RO
1082 , AOP_R1 && AOP_STK */
1090 emitcode ("pop", "ar0");
1094 bitVectUnSetBit (ic->rUsed, R0_IDX);
1102 emitcode ("pop", "ar1");
1106 bitVectUnSetBit (ic->rUsed, R1_IDX);
1112 int stk = aop->aopu.aop_stk + aop->size;
1113 bitVectUnSetBit (ic->rUsed, R0_IDX);
1114 bitVectUnSetBit (ic->rUsed, R1_IDX);
1116 getFreePtr (ic, &aop, FALSE);
1118 if (options.stack10bit)
1120 /* I'm not sure what to do here yet... */
1123 "*** Warning: probably generating bad code for "
1124 "10 bit stack mode.\n");
1129 emitcode ("mov", "a,_bp");
1130 emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1131 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1135 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1140 emitcode ("pop", "acc");
1141 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1144 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1147 freeAsmop (op, NULL, ic, TRUE);
1150 emitcode ("pop", "ar0");
1156 emitcode ("pop", "ar1");
1161 if (_G.dptr1InUse) {
1162 emitcode ("pop","dpx1");
1163 emitcode ("pop","dph1");
1164 emitcode ("pop","dpl1");
1169 emitcode ("pop","dpx");
1170 emitcode ("pop","dph");
1171 emitcode ("pop","dpl");
1176 /* all other cases just dealloc */
1182 OP_SYMBOL (op)->aop = NULL;
1183 /* if the symbol has a spill */
1185 SPIL_LOC (op)->aop = NULL;
1190 #define DEFAULT_ACC_WARNING 0
1191 static int saveAccWarn = DEFAULT_ACC_WARNING;
1193 /*-------------------------------------------------------------------*/
1194 /* aopGet - for fetching value of the aop */
1196 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1197 /* in the accumulator. Set it to the name of a free register */
1198 /* if acc must be preserved; the register will be used to preserve */
1199 /* acc temporarily and to return the result byte. */
1200 /*-------------------------------------------------------------------*/
1209 /* offset is greater than
1211 if (offset > (aop->size - 1) &&
1212 aop->type != AOP_LIT)
1215 /* depending on type */
1223 /* if we need to increment it */
1224 while (offset > aop->coff)
1226 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1230 while (offset < aop->coff)
1232 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1239 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1240 return (dname ? "acc" : "a");
1242 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1243 return Safe_strdup(buffer);
1246 assert(offset <= 3);
1247 return dptrn[aop->aopu.dptr][offset];
1252 if (aop->type == AOP_DPTR2)
1260 // if (aop->type != AOP_DPTR2)
1262 // if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1263 // emitcode(";", "spanky: saveAcc for DPTR");
1266 emitcode ("xch", "a, %s", saveAcc);
1271 while (offset > aop->coff)
1273 emitcode ("inc", "dptr");
1277 while (offset < aop->coff)
1279 emitcode ("lcall", "__decdptr");
1286 emitcode ("clr", "a");
1287 emitcode ("movc", "a,@a+dptr");
1291 emitcode ("movx", "a,@dptr");
1294 if (aop->type == AOP_DPTR2)
1302 emitcode ("xch", "a, %s", saveAcc);
1303 // if (strcmp(saveAcc, "_ap"))
1305 // emitcode(";", "spiffy: non _ap return from aopGet.");
1310 return (dname ? "acc" : "a");
1313 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1315 SNPRINTF(buffer, sizeof(buffer),
1316 "%s",aop->aopu.aop_immd.aop_immd2);
1320 SNPRINTF(buffer, sizeof(buffer),
1321 "#%s", aop->aopu.aop_immd.aop_immd1);
1327 tsprintf(buffer, sizeof(buffer),
1328 "#!his",aop->aopu.aop_immd.aop_immd1);
1331 tsprintf(buffer, sizeof(buffer),
1332 "#!hihis",aop->aopu.aop_immd.aop_immd1);
1335 tsprintf(buffer, sizeof(buffer),
1336 "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1338 default: /* should not need this (just in case) */
1339 SNPRINTF (buffer, sizeof(buffer),
1341 aop->aopu.aop_immd.aop_immd1,
1347 SNPRINTF (buffer, sizeof(buffer),
1348 "#%s", aop->aopu.aop_immd.aop_immd1);
1350 return Safe_strdup(buffer);
1355 SNPRINTF (buffer, sizeof(buffer),
1362 SNPRINTF(buffer, sizeof(buffer),
1363 "%s", aop->aopu.aop_dir);
1366 return Safe_strdup(buffer);
1370 return aop->aopu.aop_reg[offset]->dname;
1372 return aop->aopu.aop_reg[offset]->name;
1375 emitcode ("clr", "a");
1376 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1377 emitcode ("rlc", "a");
1378 return (dname ? "acc" : "a");
1381 if (!offset && dname)
1383 return aop->aopu.aop_str[offset];
1386 return aopLiteral (aop->aopu.aop_lit, offset);
1390 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1394 return aop->aopu.aop_str[offset];
1398 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1399 "aopget got unsupported aop->type");
1402 return NULL; // not reached, but makes compiler happy.
1404 /*-----------------------------------------------------------------*/
1405 /* aopPut - puts a string for a aop */
1406 /*-----------------------------------------------------------------*/
1408 aopPut (asmop * aop, char *s, int offset)
1410 if (aop->size && offset > (aop->size - 1))
1412 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1413 "aopPut got offset > aop->size");
1417 /* will assign value to value */
1418 /* depending on where it is ofcourse */
1422 MOVA (s); /* read s in case it was volatile */
1428 SNPRINTF (buffer, sizeof(buffer),
1430 aop->aopu.aop_dir, offset);
1434 SNPRINTF (buffer, sizeof(buffer),
1435 "%s", aop->aopu.aop_dir);
1439 if (strcmp (buffer, s))
1441 emitcode ("mov", "%s,%s", buffer, s);
1446 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1447 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1450 strcmp (s, "r0") == 0 ||
1451 strcmp (s, "r1") == 0 ||
1452 strcmp (s, "r2") == 0 ||
1453 strcmp (s, "r3") == 0 ||
1454 strcmp (s, "r4") == 0 ||
1455 strcmp (s, "r5") == 0 ||
1456 strcmp (s, "r6") == 0 ||
1457 strcmp (s, "r7") == 0)
1459 emitcode ("mov", "%s,%s",
1460 aop->aopu.aop_reg[offset]->dname, s);
1464 emitcode ("mov", "%s,%s",
1465 aop->aopu.aop_reg[offset]->name, s);
1471 emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1477 if (aop->type == AOP_DPTR2)
1485 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1486 "aopPut writting to code space");
1490 while (offset > aop->coff)
1493 emitcode ("inc", "dptr");
1496 while (offset < aop->coff)
1499 emitcode ("lcall", "__decdptr");
1504 /* if not in accumulater */
1507 emitcode ("movx", "@dptr,a");
1509 if (aop->type == AOP_DPTR2)
1517 while (offset > aop->coff)
1520 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1522 while (offset < aop->coff)
1525 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1532 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1538 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1540 else if (strcmp (s, "r0") == 0 ||
1541 strcmp (s, "r1") == 0 ||
1542 strcmp (s, "r2") == 0 ||
1543 strcmp (s, "r3") == 0 ||
1544 strcmp (s, "r4") == 0 ||
1545 strcmp (s, "r5") == 0 ||
1546 strcmp (s, "r6") == 0 ||
1547 strcmp (s, "r7") == 0)
1550 SNPRINTF(buff, sizeof(buff),
1552 emitcode ("mov", "@%s,%s",
1553 aop->aopu.aop_ptr->name, buff);
1557 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1562 if (strcmp (s, "a") == 0)
1563 emitcode ("push", "acc");
1567 emitcode ("push", "acc");
1569 emitcode ("push", s);
1575 /* if bit variable */
1576 if (!aop->aopu.aop_dir)
1578 emitcode ("clr", "a");
1579 emitcode ("rlc", "a");
1584 emitcode ("clr", "%s", aop->aopu.aop_dir);
1586 emitcode ("setb", "%s", aop->aopu.aop_dir);
1587 else if (!strcmp (s, "c"))
1588 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1591 if (strcmp (s, "a"))
1596 /* set C, if a >= 1 */
1597 emitcode ("add", "a,#!constbyte",0xff);
1598 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1606 if (strcmp (aop->aopu.aop_str[offset], s))
1607 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1612 if (!offset && (strcmp (s, "acc") == 0))
1615 if (strcmp (aop->aopu.aop_str[offset], s))
1616 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1620 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1621 "aopPut got unsupported aop->type");
1628 /*--------------------------------------------------------------------*/
1629 /* reAdjustPreg - points a register back to where it should (coff==0) */
1630 /*--------------------------------------------------------------------*/
1632 reAdjustPreg (asmop * aop)
1634 if ((aop->coff==0) || (aop->size <= 1)) {
1643 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1647 if (aop->type == AOP_DPTR2)
1654 emitcode ("lcall", "__decdptr");
1657 if (aop->type == AOP_DPTR2)
1667 #define AOP(op) op->aop
1668 #define AOP_TYPE(op) AOP(op)->type
1669 #define AOP_SIZE(op) AOP(op)->size
1670 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1671 AOP_TYPE(x) == AOP_R0))
1673 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1674 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1677 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1678 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1679 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1680 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1681 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1682 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1684 // The following two macros can be used even if the aop has not yet been aopOp'd.
1685 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1686 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1688 /* Workaround for DS80C390 bug: div ab may return bogus results
1689 * if A is accessed in instruction immediately before the div.
1691 * Will be fixed in B4 rev of processor, Dallas claims.
1694 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1695 if (!AOP_NEEDSACC(RIGHT)) \
1697 /* We can load A first, then B, since \
1698 * B (the RIGHT operand) won't clobber A, \
1699 * thus avoiding touching A right before the div. \
1701 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1702 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1704 L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1709 /* Just stuff in a nop after loading A. */ \
1710 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1711 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1713 emitcode("nop", "; workaround for DS80C390 div bug."); \
1717 /*-----------------------------------------------------------------*/
1718 /* opIsGptr: returns non-zero if the passed operand is */
1719 /* a generic pointer type. */
1720 /*-----------------------------------------------------------------*/
1722 opIsGptr (operand * op)
1724 sym_link *type = operandType (op);
1726 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1733 /*-----------------------------------------------------------------*/
1734 /* getDataSize - get the operand data size */
1735 /*-----------------------------------------------------------------*/
1737 getDataSize (operand * op)
1740 size = AOP_SIZE (op);
1741 if (size == GPTRSIZE)
1743 sym_link *type = operandType (op);
1744 if (IS_GENPTR (type))
1746 /* generic pointer; arithmetic operations
1747 * should ignore the high byte (pointer type).
1755 /*-----------------------------------------------------------------*/
1756 /* outAcc - output Acc */
1757 /*-----------------------------------------------------------------*/
1759 outAcc (operand * result)
1762 size = getDataSize (result);
1765 aopPut (AOP (result), "a", 0);
1768 /* unsigned or positive */
1771 aopPut (AOP (result), zero, offset++);
1776 /*-----------------------------------------------------------------*/
1777 /* outBitC - output a bit C */
1778 /*-----------------------------------------------------------------*/
1780 outBitC (operand * result)
1782 /* if the result is bit */
1783 if (AOP_TYPE (result) == AOP_CRY)
1785 aopPut (AOP (result), "c", 0);
1789 emitcode ("clr", "a");
1790 emitcode ("rlc", "a");
1795 /*-----------------------------------------------------------------*/
1796 /* toBoolean - emit code for orl a,operator(sizeop) */
1797 /*-----------------------------------------------------------------*/
1799 toBoolean (operand * oper)
1801 int size = AOP_SIZE (oper) - 1;
1805 /* The generic part of a generic pointer should
1806 * not participate in it's truth value.
1808 * i.e. 0x10000000 is zero.
1810 if (opIsGptr (oper))
1812 D (emitcode (";", "toBoolean: generic ptr special case."););
1816 _startLazyDPSEvaluation ();
1817 if (AOP_NEEDSACC (oper) && size)
1822 emitcode ("push", "b");
1824 MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1828 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1835 emitcode ("orl", "b,%s",
1836 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1840 emitcode ("orl", "a,%s",
1841 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1844 _endLazyDPSEvaluation ();
1848 emitcode ("mov", "a,b");
1851 emitcode ("pop", "b");
1858 /*-----------------------------------------------------------------*/
1859 /* genNot - generate code for ! operation */
1860 /*-----------------------------------------------------------------*/
1866 D (emitcode (";", "genNot "););
1868 /* assign asmOps to operand & result */
1869 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1870 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1872 /* if in bit space then a special case */
1873 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1875 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1876 emitcode ("cpl", "c");
1877 outBitC (IC_RESULT (ic));
1881 toBoolean (IC_LEFT (ic));
1883 tlbl = newiTempLabel (NULL);
1884 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1885 emitcode ("", "!tlabeldef", tlbl->key + 100);
1886 outBitC (IC_RESULT (ic));
1889 /* release the aops */
1890 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1891 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1895 /*-----------------------------------------------------------------*/
1896 /* genCpl - generate code for complement */
1897 /*-----------------------------------------------------------------*/
1905 D (emitcode (";", "genCpl "););
1908 /* assign asmOps to operand & result */
1909 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1910 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1912 /* special case if in bit space */
1913 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1914 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1915 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1916 emitcode ("cpl", "c");
1917 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1920 tlbl=newiTempLabel(NULL);
1921 emitcode ("cjne", "%s,#0x01,%05d$",
1922 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1923 emitcode ("", "%05d$:", tlbl->key+100);
1924 outBitC (IC_RESULT(ic));
1928 size = AOP_SIZE (IC_RESULT (ic));
1929 _startLazyDPSEvaluation ();
1932 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1933 emitcode ("cpl", "a");
1934 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1936 _endLazyDPSEvaluation ();
1940 /* release the aops */
1941 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1942 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1945 /*-----------------------------------------------------------------*/
1946 /* genUminusFloat - unary minus for floating points */
1947 /*-----------------------------------------------------------------*/
1949 genUminusFloat (operand * op, operand * result)
1951 int size, offset = 0;
1953 D(emitcode (";", "genUminusFloat"););
1955 /* for this we just copy and then flip the bit */
1957 _startLazyDPSEvaluation ();
1958 size = AOP_SIZE (op) - 1;
1962 aopPut (AOP (result),
1963 aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1968 MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1970 emitcode ("cpl", "acc.7");
1971 aopPut (AOP (result), "a", offset);
1972 _endLazyDPSEvaluation ();
1975 /*-----------------------------------------------------------------*/
1976 /* genUminus - unary minus code generation */
1977 /*-----------------------------------------------------------------*/
1979 genUminus (iCode * ic)
1984 D (emitcode (";", "genUminus "););
1987 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1988 aopOp (IC_RESULT (ic), ic, TRUE, (AOP_TYPE(IC_LEFT (ic)) == AOP_DPTR));
1990 /* if both in bit space then special
1992 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1993 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1996 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1997 emitcode ("cpl", "c");
1998 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2002 optype = operandType (IC_LEFT (ic));
2004 /* if float then do float stuff */
2005 if (IS_FLOAT (optype))
2007 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2011 /* otherwise subtract from zero */
2012 size = AOP_SIZE (IC_LEFT (ic));
2014 _startLazyDPSEvaluation ();
2017 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
2018 if (!strcmp (l, "a"))
2022 emitcode ("cpl", "a");
2023 emitcode ("addc", "a,#0");
2029 emitcode ("clr", "a");
2030 emitcode ("subb", "a,%s", l);
2032 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2034 _endLazyDPSEvaluation ();
2036 /* if any remaining bytes in the result */
2037 /* we just need to propagate the sign */
2038 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
2040 emitcode ("rlc", "a");
2041 emitcode ("subb", "a,acc");
2043 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2047 /* release the aops */
2048 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2049 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2052 /*-----------------------------------------------------------------*/
2053 /* savermask - saves registers in the mask */
2054 /*-----------------------------------------------------------------*/
2055 static void savermask(bitVect *rs_mask)
2058 if (options.useXstack) {
2059 if (bitVectBitValue (rs_mask, R0_IDX))
2060 emitcode ("mov", "b,r0");
2061 emitcode ("mov", "r0,%s", spname);
2062 for (i = 0; i < ds390_nRegs; i++) {
2063 if (bitVectBitValue (rs_mask, i)) {
2065 emitcode ("mov", "a,b");
2067 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2068 emitcode ("movx", "@r0,a");
2069 emitcode ("inc", "r0");
2072 emitcode ("mov", "%s,r0", spname);
2073 if (bitVectBitValue (rs_mask, R0_IDX))
2074 emitcode ("mov", "r0,b");
2076 for (i = 0; i < ds390_nRegs; i++) {
2077 if (bitVectBitValue (rs_mask, i))
2078 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2083 /*-----------------------------------------------------------------*/
2084 /* saveRegisters - will look for a call and save the registers */
2085 /*-----------------------------------------------------------------*/
2087 saveRegisters (iCode * lic)
2093 for (ic = lic; ic; ic = ic->next)
2094 if (ic->op == CALL || ic->op == PCALL)
2099 fprintf (stderr, "found parameter push with no function call\n");
2103 /* if the registers have been saved already then
2106 || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2109 /* special case if DPTR alive across a function call then must save it
2110 even though callee saves */
2111 if (IS_SYMOP(IC_LEFT(ic)) &&
2112 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2114 rsave = newBitVect(ic->rMask->size);
2115 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2116 if (bitVectBitValue(ic->rMask,i))
2117 rsave = bitVectSetBit(rsave,i);
2119 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2121 /* safe the registers in use at this time but skip the
2122 ones for the result */
2123 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2124 ds390_rUmaskForOp (IC_RESULT(ic)));
2130 /*-----------------------------------------------------------------*/
2131 /* usavermask - restore registers with mask */
2132 /*-----------------------------------------------------------------*/
2133 static void unsavermask(bitVect *rs_mask)
2136 if (options.useXstack) {
2137 emitcode ("mov", "r0,%s", spname);
2138 for (i = ds390_nRegs; i >= 0; i--) {
2139 if (bitVectBitValue (rs_mask, i)) {
2140 emitcode ("dec", "r0");
2141 emitcode ("movx", "a,@r0");
2143 emitcode ("mov", "b,a");
2145 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2148 emitcode ("mov", "%s,r0", spname);
2149 if (bitVectBitValue (rs_mask, R0_IDX))
2150 emitcode ("mov", "r0,b");
2152 for (i = ds390_nRegs; i >= 0; i--) {
2153 if (bitVectBitValue (rs_mask, i))
2154 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2159 /*-----------------------------------------------------------------*/
2160 /* unsaveRegisters - pop the pushed registers */
2161 /*-----------------------------------------------------------------*/
2163 unsaveRegisters (iCode * ic)
2167 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2169 rsave = newBitVect(ic->rMask->size);
2170 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2171 if (bitVectBitValue(ic->rMask,i))
2172 rsave = bitVectSetBit(rsave,i);
2174 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2176 /* restore the registers in use at this time but skip the
2177 ones for the result */
2178 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2179 ds390_rUmaskForOp (IC_RESULT(ic)));
2185 /*-----------------------------------------------------------------*/
2187 /*-----------------------------------------------------------------*/
2189 pushSide (operand * oper, int size)
2192 _startLazyDPSEvaluation ();
2195 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2196 if (AOP_TYPE (oper) != AOP_REG &&
2197 AOP_TYPE (oper) != AOP_DIR &&
2200 emitcode ("mov", "a,%s", l);
2201 emitcode ("push", "acc");
2204 emitcode ("push", "%s", l);
2206 _endLazyDPSEvaluation ();
2209 /*-----------------------------------------------------------------*/
2210 /* assignResultValue - */
2211 /*-----------------------------------------------------------------*/
2213 assignResultValue (operand * oper)
2216 int size = AOP_SIZE (oper);
2217 bool pushedAcc = FALSE;
2219 if (size == fReturnSizeDS390)
2221 /* I don't think this case can ever happen... */
2222 /* ACC is the last part of this. If writing the result
2223 * uses AC, we must preserve it.
2225 if (AOP_NEEDSACC(oper))
2227 emitcode(";", "assignResultValue special case for ACC.");
2228 emitcode("push", "acc");
2235 _startLazyDPSEvaluation ();
2238 aopPut (AOP (oper), fReturn[offset], offset);
2241 _endLazyDPSEvaluation ();
2245 emitcode("pop", "acc");
2246 aopPut(AOP(oper), "a", offset);
2251 /*-----------------------------------------------------------------*/
2252 /* genXpush - pushes onto the external stack */
2253 /*-----------------------------------------------------------------*/
2255 genXpush (iCode * ic)
2257 asmop *aop = newAsmop (0);
2259 int size, offset = 0;
2261 D (emitcode (";", "genXpush ");
2264 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2265 r = getFreePtr (ic, &aop, FALSE);
2268 emitcode ("mov", "%s,_spx", r->name);
2270 size = AOP_SIZE (IC_LEFT (ic));
2271 _startLazyDPSEvaluation ();
2275 MOVA (aopGet (AOP (IC_LEFT (ic)),
2276 offset++, FALSE, FALSE, NULL));
2277 emitcode ("movx", "@%s,a", r->name);
2278 emitcode ("inc", "%s", r->name);
2281 _endLazyDPSEvaluation ();
2284 emitcode ("mov", "_spx,%s", r->name);
2286 freeAsmop (NULL, aop, ic, TRUE);
2287 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2290 /*-----------------------------------------------------------------*/
2291 /* genIpush - generate code for pushing this gets a little complex */
2292 /*-----------------------------------------------------------------*/
2294 genIpush (iCode * ic)
2296 int size, offset = 0;
2299 D (emitcode (";", "genIpush ");
2302 /* if this is not a parm push : ie. it is spill push
2303 and spill push is always done on the local stack */
2307 /* and the item is spilt then do nothing */
2308 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2311 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2312 size = AOP_SIZE (IC_LEFT (ic));
2313 /* push it on the stack */
2314 _startLazyDPSEvaluation ();
2317 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2323 emitcode ("push", "%s", l);
2325 _endLazyDPSEvaluation ();
2329 /* this is a paramter push: in this case we call
2330 the routine to find the call and save those
2331 registers that need to be saved */
2334 /* if use external stack then call the external
2335 stack pushing routine */
2336 if (options.useXstack)
2342 /* then do the push */
2343 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2345 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2346 size = AOP_SIZE (IC_LEFT (ic));
2348 _startLazyDPSEvaluation ();
2351 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2352 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2353 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2356 emitcode ("mov", "a,%s", l);
2357 emitcode ("push", "acc");
2361 emitcode ("push", "%s", l);
2364 _endLazyDPSEvaluation ();
2366 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2369 /*-----------------------------------------------------------------*/
2370 /* genIpop - recover the registers: can happen only for spilling */
2371 /*-----------------------------------------------------------------*/
2373 genIpop (iCode * ic)
2377 D (emitcode (";", "genIpop ");
2381 /* if the temp was not pushed then */
2382 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2385 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2386 size = AOP_SIZE (IC_LEFT (ic));
2387 offset = (size - 1);
2388 _startLazyDPSEvaluation ();
2391 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2392 FALSE, TRUE, NULL));
2394 _endLazyDPSEvaluation ();
2396 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2399 /*-----------------------------------------------------------------*/
2400 /* unsaveRBank - restores the resgister bank from stack */
2401 /*-----------------------------------------------------------------*/
2403 unsaveRBank (int bank, iCode * ic, bool popPsw)
2409 if (options.useXstack)
2413 /* Assume r0 is available for use. */
2414 r = ds390_regWithIdx (R0_IDX);;
2419 r = getFreePtr (ic, &aop, FALSE);
2421 emitcode ("mov", "%s,_spx", r->name);
2426 if (options.useXstack)
2428 emitcode ("movx", "a,@%s", r->name);
2429 emitcode ("mov", "psw,a");
2430 emitcode ("dec", "%s", r->name);
2434 emitcode ("pop", "psw");
2438 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2440 if (options.useXstack)
2442 emitcode ("movx", "a,@%s", r->name);
2443 emitcode ("mov", "(%s+%d),a",
2444 regs390[i].base, 8 * bank + regs390[i].offset);
2445 emitcode ("dec", "%s", r->name);
2449 emitcode ("pop", "(%s+%d)",
2450 regs390[i].base, 8 * bank + regs390[i].offset);
2453 if (options.useXstack)
2455 emitcode ("mov", "_spx,%s", r->name);
2460 freeAsmop (NULL, aop, ic, TRUE);
2464 /*-----------------------------------------------------------------*/
2465 /* saveRBank - saves an entire register bank on the stack */
2466 /*-----------------------------------------------------------------*/
2468 saveRBank (int bank, iCode * ic, bool pushPsw)
2474 if (options.useXstack)
2478 /* Assume r0 is available for use. */
2479 r = ds390_regWithIdx (R0_IDX);;
2484 r = getFreePtr (ic, &aop, FALSE);
2486 emitcode ("mov", "%s,_spx", r->name);
2489 for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2491 if (options.useXstack)
2493 emitcode ("inc", "%s", r->name);
2494 emitcode ("mov", "a,(%s+%d)",
2495 regs390[i].base, 8 * bank + regs390[i].offset);
2496 emitcode ("movx", "@%s,a", r->name);
2499 emitcode ("push", "(%s+%d)",
2500 regs390[i].base, 8 * bank + regs390[i].offset);
2505 if (options.useXstack)
2507 emitcode ("mov", "a,psw");
2508 emitcode ("movx", "@%s,a", r->name);
2509 emitcode ("inc", "%s", r->name);
2510 emitcode ("mov", "_spx,%s", r->name);
2514 emitcode ("push", "psw");
2517 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2522 freeAsmop (NULL, aop, ic, TRUE);
2531 /*-----------------------------------------------------------------*/
2532 /* genSend - gen code for SEND */
2533 /*-----------------------------------------------------------------*/
2534 static void genSend(set *sendSet)
2538 static int rb1_count = 0;
2540 for (sic = setFirstItem (sendSet); sic;
2541 sic = setNextItem (sendSet)) {
2542 int size, offset = 0;
2544 size=getSize(operandType(IC_LEFT(sic)));
2545 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2546 if (sendCount == 0) { /* first parameter */
2547 // we know that dpl(hxb) is the result, so
2549 _startLazyDPSEvaluation ();
2551 aopOp (IC_LEFT (sic), sic, FALSE,
2552 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2554 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2557 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2558 FALSE, FALSE, NULL);
2559 if (strcmp (l, fReturn[offset])) {
2560 emitcode ("mov", "%s,%s",
2566 _endLazyDPSEvaluation ();
2567 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2569 } else { /* if more parameter in registers */
2570 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2572 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2573 FALSE, FALSE, NULL));
2575 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2582 adjustEsp(const char *reg)
2584 emitcode ("anl","%s,#3", reg);
2585 if (TARGET_IS_DS400)
2587 emitcode ("orl","%s,#!constbyte",
2589 (options.stack_loc >> 8) & 0xff);
2593 /*-----------------------------------------------------------------*/
2594 /* genCall - generates a call statement */
2595 /*-----------------------------------------------------------------*/
2597 genCall (iCode * ic)
2600 bool restoreBank = FALSE;
2601 bool swapBanks = FALSE;
2603 D (emitcode (";", "genCall "););
2605 /* if we are calling a not _naked function that is not using
2606 the same register bank then we need to save the
2607 destination registers on the stack */
2608 dtype = operandType (IC_LEFT (ic));
2609 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2610 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2611 IFFUNC_ISISR (currFunc->type))
2615 /* This is unexpected; the bank should have been saved in
2618 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2624 /* if caller saves & we have not saved then */
2628 /* if send set is not empty the assign */
2629 /* We've saved all the registers we care about;
2630 * therefore, we may clobber any register not used
2631 * in the calling convention (i.e. anything not in
2636 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2637 genSend(reverseSet(_G.sendSet));
2639 genSend(_G.sendSet);
2646 emitcode ("mov", "psw,#!constbyte",
2647 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2651 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2652 OP_SYMBOL (IC_LEFT (ic))->rname :
2653 OP_SYMBOL (IC_LEFT (ic))->name));
2657 emitcode ("mov", "psw,#!constbyte",
2658 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2661 /* if we need assign a result value */
2662 if ((IS_ITEMP (IC_RESULT (ic)) &&
2663 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2664 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2665 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2666 IS_TRUE_SYMOP (IC_RESULT (ic)))
2668 if (isOperandInFarSpace (IC_RESULT (ic))
2669 && getSize (operandType (IC_RESULT (ic))) <= 2)
2671 int size = getSize (operandType (IC_RESULT (ic)));
2673 /* Special case for 1 or 2 byte return in far space. */
2677 emitcode ("mov", "b,%s", fReturn[1]);
2682 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2688 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2692 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2694 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2699 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2702 assignResultValue (IC_RESULT (ic));
2704 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2708 /* adjust the stack for parameters if
2710 if (ic->parmBytes) {
2712 if (options.stack10bit) {
2713 if (ic->parmBytes <= 10) {
2714 emitcode(";","stack adjustment for parms");
2715 for (i=0; i < ic->parmBytes ; i++) {
2716 emitcode("pop","acc");
2720 emitcode ("clr","c");
2721 emitcode ("mov","a,sp");
2722 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2723 emitcode ("mov","sp,a");
2724 emitcode ("mov","a,esp");
2726 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2727 emitcode ("mov","esp,a");
2731 if (ic->parmBytes > 3) {
2732 emitcode ("mov", "a,%s", spname);
2733 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2734 emitcode ("mov", "%s,a", spname);
2736 for (i = 0; i < ic->parmBytes; i++)
2737 emitcode ("dec", "%s", spname);
2741 /* if we hade saved some registers then unsave them */
2743 unsaveRegisters (ic);
2745 /* if register bank was saved then pop them */
2747 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2750 /*-----------------------------------------------------------------*/
2751 /* genPcall - generates a call by pointer statement */
2752 /*-----------------------------------------------------------------*/
2754 genPcall (iCode * ic)
2757 symbol *rlbl = newiTempLabel (NULL);
2758 bool restoreBank=FALSE;
2760 D (emitcode (";", "genPcall ");
2764 /* if caller saves & we have not saved then */
2768 /* if we are calling a function that is not using
2769 the same register bank then we need to save the
2770 destination registers on the stack */
2771 dtype = operandType (IC_LEFT (ic));
2772 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2773 IFFUNC_ISISR (currFunc->type) &&
2774 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2775 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2779 /* push the return address on to the stack */
2780 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2781 emitcode ("push", "acc");
2782 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2783 emitcode ("push", "acc");
2785 if (options.model == MODEL_FLAT24)
2787 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2788 emitcode ("push", "acc");
2791 /* now push the calling address */
2792 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2794 pushSide (IC_LEFT (ic), FPTRSIZE);
2796 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2798 /* if send set is not empty the assign */
2801 genSend(reverseSet(_G.sendSet));
2805 emitcode ("ret", "");
2806 emitcode ("", "!tlabeldef", (rlbl->key + 100));
2809 /* if we need assign a result value */
2810 if ((IS_ITEMP (IC_RESULT (ic)) &&
2811 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2812 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2813 IS_TRUE_SYMOP (IC_RESULT (ic)))
2817 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2820 assignResultValue (IC_RESULT (ic));
2822 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2825 /* adjust the stack for parameters if
2830 if (options.stack10bit) {
2831 if (ic->parmBytes <= 10) {
2832 emitcode(";","stack adjustment for parms");
2833 for (i=0; i < ic->parmBytes ; i++) {
2834 emitcode("pop","acc");
2838 emitcode ("clr","c");
2839 emitcode ("mov","a,sp");
2840 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2841 emitcode ("mov","sp,a");
2842 emitcode ("mov","a,esp");
2844 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2845 emitcode ("mov","esp,a");
2849 if (ic->parmBytes > 3) {
2850 emitcode ("mov", "a,%s", spname);
2851 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2852 emitcode ("mov", "%s,a", spname);
2855 for (i = 0; i < ic->parmBytes; i++)
2856 emitcode ("dec", "%s", spname);
2860 /* if register bank was saved then unsave them */
2862 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2864 /* if we hade saved some registers then
2867 unsaveRegisters (ic);
2871 /*-----------------------------------------------------------------*/
2872 /* resultRemat - result is rematerializable */
2873 /*-----------------------------------------------------------------*/
2875 resultRemat (iCode * ic)
2877 if (SKIP_IC (ic) || ic->op == IFX)
2880 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2882 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2883 if (sym->remat && !POINTER_SET (ic))
2890 #if defined(__BORLANDC__) || defined(_MSC_VER)
2891 #define STRCASECMP stricmp
2893 #define STRCASECMP strcasecmp
2896 /*-----------------------------------------------------------------*/
2897 /* inExcludeList - return 1 if the string is in exclude Reg list */
2898 /*-----------------------------------------------------------------*/
2900 regsCmp(void *p1, void *p2)
2902 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2906 inExcludeList (char *s)
2908 const char *p = setFirstItem(options.excludeRegsSet);
2910 if (p == NULL || STRCASECMP(p, "none") == 0)
2914 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2917 /*-----------------------------------------------------------------*/
2918 /* genFunction - generated code for function entry */
2919 /*-----------------------------------------------------------------*/
2921 genFunction (iCode * ic)
2925 bool switchedPSW = FALSE;
2927 D (emitcode (";", "genFunction "););
2930 /* create the function header */
2931 emitcode (";", "-----------------------------------------");
2932 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2933 emitcode (";", "-----------------------------------------");
2935 emitcode ("", "%s:", sym->rname);
2936 ftype = operandType (IC_LEFT (ic));
2938 if (IFFUNC_ISNAKED(ftype))
2940 emitcode(";", "naked function: no prologue.");
2944 if (options.stack_probe)
2945 emitcode ("lcall","__stack_probe");
2947 /* here we need to generate the equates for the
2948 register bank if required */
2949 if (FUNC_REGBANK (ftype) != rbank)
2953 rbank = FUNC_REGBANK (ftype);
2954 for (i = 0; i < ds390_nRegs; i++)
2956 if (regs390[i].print) {
2957 if (strcmp (regs390[i].base, "0") == 0)
2958 emitcode ("", "%s !equ !constbyte",
2960 8 * rbank + regs390[i].offset);
2962 emitcode ("", "%s !equ %s + !constbyte",
2965 8 * rbank + regs390[i].offset);
2970 /* if this is an interrupt service routine then
2971 save acc, b, dpl, dph */
2972 if (IFFUNC_ISISR (sym->type))
2974 if (!inExcludeList ("acc"))
2975 emitcode ("push", "acc");
2976 if (!inExcludeList ("b"))
2977 emitcode ("push", "b");
2978 if (!inExcludeList ("dpl"))
2979 emitcode ("push", "dpl");
2980 if (!inExcludeList ("dph"))
2981 emitcode ("push", "dph");
2982 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2984 emitcode ("push", "dpx");
2985 /* Make sure we're using standard DPTR */
2986 emitcode ("push", "dps");
2987 emitcode ("mov", "dps,#0");
2988 if (options.stack10bit)
2990 /* This ISR could conceivably use DPTR2. Better save it. */
2991 emitcode ("push", "dpl1");
2992 emitcode ("push", "dph1");
2993 emitcode ("push", "dpx1");
2994 emitcode ("push", DP2_RESULT_REG);
2997 /* if this isr has no bank i.e. is going to
2998 run with bank 0 , then we need to save more
3000 if (!FUNC_REGBANK (sym->type))
3004 /* if this function does not call any other
3005 function then we can be economical and
3006 save only those registers that are used */
3007 if (!IFFUNC_HASFCALL(sym->type))
3010 /* if any registers used */
3013 /* save the registers used */
3014 for (i = 0; i < sym->regsUsed->size; i++)
3016 if (bitVectBitValue (sym->regsUsed, i) ||
3017 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3018 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3025 /* this function has a function call cannot
3026 determines register usage so we will have to push the
3028 saveRBank (0, ic, FALSE);
3029 if (options.parms_in_bank1) {
3030 for (i=0; i < 8 ; i++ ) {
3031 emitcode ("push","%s",rb1regs[i]);
3038 /* This ISR uses a non-zero bank.
3040 * We assume that the bank is available for our
3043 * However, if this ISR calls a function which uses some
3044 * other bank, we must save that bank entirely.
3046 unsigned long banksToSave = 0;
3048 if (IFFUNC_HASFCALL(sym->type))
3051 #define MAX_REGISTER_BANKS 4
3056 for (i = ic; i; i = i->next)
3058 if (i->op == ENDFUNCTION)
3060 /* we got to the end OK. */
3068 dtype = operandType (IC_LEFT(i));
3070 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3072 /* Mark this bank for saving. */
3073 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3075 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3079 banksToSave |= (1 << FUNC_REGBANK(dtype));
3082 /* And note that we don't need to do it in
3090 /* This is a mess; we have no idea what
3091 * register bank the called function might
3094 * The only thing I can think of to do is
3095 * throw a warning and hope.
3097 werror(W_FUNCPTR_IN_USING_ISR);
3101 if (banksToSave && options.useXstack)
3103 /* Since we aren't passing it an ic,
3104 * saveRBank will assume r0 is available to abuse.
3106 * So switch to our (trashable) bank now, so
3107 * the caller's R0 isn't trashed.
3109 emitcode ("push", "psw");
3110 emitcode ("mov", "psw,#!constbyte",
3111 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3115 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3117 if (banksToSave & (1 << ix))
3119 saveRBank(ix, NULL, FALSE);
3123 // TODO: this needs a closer look
3124 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3129 /* if callee-save to be used for this function
3130 then save the registers being used in this function */
3131 if (IFFUNC_CALLEESAVES(sym->type))
3135 /* if any registers used */
3138 /* save the registers used */
3139 for (i = 0; i < sym->regsUsed->size; i++)
3141 if (bitVectBitValue (sym->regsUsed, i) ||
3142 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3144 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3152 /* set the register bank to the desired value */
3153 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3156 emitcode ("push", "psw");
3157 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3160 if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3161 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3162 if (options.stack10bit) {
3163 emitcode ("push","_bpx");
3164 emitcode ("push","_bpx+1");
3165 emitcode ("mov","_bpx,%s",spname);
3166 emitcode ("mov","_bpx+1,esp");
3167 adjustEsp("_bpx+1");
3169 if (options.useXstack) {
3170 emitcode ("mov", "r0,%s", spname);
3171 emitcode ("mov", "a,_bp");
3172 emitcode ("movx", "@r0,a");
3173 emitcode ("inc", "%s", spname);
3175 /* set up the stack */
3176 emitcode ("push", "_bp"); /* save the callers stack */
3178 emitcode ("mov", "_bp,%s", spname);
3182 /* adjust the stack for the function */
3185 if (options.stack10bit) {
3186 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3187 assert (sym->recvSize <= 4);
3188 if (sym->stack <= 8) {
3189 while (i--) emitcode ("push","acc");
3192 emitcode ("mov","a,sp");
3193 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3194 emitcode ("mov","sp,a");
3195 emitcode ("mov","a,esp");
3197 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3198 emitcode ("mov","esp,a");
3203 werror (W_STACK_OVERFLOW, sym->name);
3205 if (i > 3 && sym->recvSize < 4) {
3207 emitcode ("mov", "a,sp");
3208 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3209 emitcode ("mov", "sp,a");
3213 emitcode ("inc", "sp");
3220 emitcode ("mov", "a,_spx");
3221 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3222 emitcode ("mov", "_spx,a");
3225 /* if critical function then turn interrupts off */
3226 if (IFFUNC_ISCRITICAL (ftype))
3228 symbol *tlbl = newiTempLabel (NULL);
3229 emitcode ("setb", "c");
3230 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3231 emitcode ("clr", "c");
3232 emitcode ("", "%05d$:", (tlbl->key + 100));
3233 emitcode ("push", "psw"); /* save old ea via c in psw */
3238 /*-----------------------------------------------------------------*/
3239 /* genEndFunction - generates epilogue for functions */
3240 /*-----------------------------------------------------------------*/
3242 genEndFunction (iCode * ic)
3244 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3246 D (emitcode (";", "genEndFunction "););
3248 if (IFFUNC_ISNAKED(sym->type))
3250 emitcode(";", "naked function: no epilogue.");
3254 if (IFFUNC_ISCRITICAL (sym->type))
3256 emitcode ("pop", "psw"); /* restore ea via c in psw */
3257 emitcode ("mov", "ea,c");
3260 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3261 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3263 if (options.stack10bit) {
3265 emitcode ("mov", "sp,_bpx", spname);
3266 emitcode ("mov", "esp,_bpx+1", spname);
3269 emitcode ("mov", "%s,_bp", spname);
3273 /* if use external stack but some variables were
3274 added to the local stack then decrement the
3276 if (options.useXstack && sym->stack) {
3277 emitcode ("mov", "a,sp");
3278 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3279 emitcode ("mov", "sp,a");
3283 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3284 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3286 if (options.useXstack) {
3287 emitcode ("mov", "r0,%s", spname);
3288 emitcode ("movx", "a,@r0");
3289 emitcode ("mov", "_bp,a");
3290 emitcode ("dec", "%s", spname);
3292 if (options.stack10bit) {
3293 emitcode ("pop", "_bpx+1");
3294 emitcode ("pop", "_bpx");
3296 emitcode ("pop", "_bp");
3301 /* restore the register bank */
3302 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3304 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3305 || !options.useXstack)
3307 /* Special case of ISR using non-zero bank with useXstack
3310 emitcode ("pop", "psw");
3314 if (IFFUNC_ISISR (sym->type))
3317 /* now we need to restore the registers */
3318 /* if this isr has no bank i.e. is going to
3319 run with bank 0 , then we need to save more
3321 if (!FUNC_REGBANK (sym->type))
3324 /* if this function does not call any other
3325 function then we can be economical and
3326 save only those registers that are used */
3327 if (!IFFUNC_HASFCALL(sym->type))
3330 /* if any registers used */
3333 /* save the registers used */
3334 for (i = sym->regsUsed->size; i >= 0; i--)
3336 if (bitVectBitValue (sym->regsUsed, i) ||
3337 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3338 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3345 /* this function has a function call cannot
3346 determines register usage so we will have to pop the
3348 if (options.parms_in_bank1) {
3349 for (i = 7 ; i >= 0 ; i-- ) {
3350 emitcode ("pop","%s",rb1regs[i]);
3353 unsaveRBank (0, ic, FALSE);
3358 /* This ISR uses a non-zero bank.
3360 * Restore any register banks saved by genFunction
3363 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3366 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3368 if (savedBanks & (1 << ix))
3370 unsaveRBank(ix, NULL, FALSE);
3374 if (options.useXstack)
3376 /* Restore bank AFTER calling unsaveRBank,
3377 * since it can trash r0.
3379 emitcode ("pop", "psw");
3383 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3385 if (options.stack10bit)
3387 emitcode ("pop", DP2_RESULT_REG);
3388 emitcode ("pop", "dpx1");
3389 emitcode ("pop", "dph1");
3390 emitcode ("pop", "dpl1");
3392 emitcode ("pop", "dps");
3393 emitcode ("pop", "dpx");
3395 if (!inExcludeList ("dph"))
3396 emitcode ("pop", "dph");
3397 if (!inExcludeList ("dpl"))
3398 emitcode ("pop", "dpl");
3399 if (!inExcludeList ("b"))
3400 emitcode ("pop", "b");
3401 if (!inExcludeList ("acc"))
3402 emitcode ("pop", "acc");
3404 /* if debug then send end of function */
3405 if (options.debug && currFunc) {
3407 emitcode ("", "C$%s$%d$%d$%d ==.",
3408 FileBaseName (ic->filename), currFunc->lastLine,
3409 ic->level, ic->block);
3410 if (IS_STATIC (currFunc->etype))
3411 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3413 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3417 emitcode ("reti", "");
3421 if (IFFUNC_CALLEESAVES(sym->type))
3425 /* if any registers used */
3428 /* save the registers used */
3429 for (i = sym->regsUsed->size; i >= 0; i--)
3431 if (bitVectBitValue (sym->regsUsed, i) ||
3432 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3433 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3439 /* if debug then send end of function */
3440 if (options.debug && currFunc)
3443 emitcode ("", "C$%s$%d$%d$%d ==.",
3444 FileBaseName (ic->filename), currFunc->lastLine,
3445 ic->level, ic->block);
3446 if (IS_STATIC (currFunc->etype))
3447 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3449 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3453 emitcode ("ret", "");
3458 /*-----------------------------------------------------------------*/
3459 /* genJavaNativeRet - generate code for return JavaNative */
3460 /*-----------------------------------------------------------------*/
3461 static void genJavaNativeRet(iCode *ic)
3465 aopOp (IC_LEFT (ic), ic, FALSE,
3466 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3467 size = AOP_SIZE (IC_LEFT (ic));
3471 /* it is assigned to GPR0-R3 then push them */
3472 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3473 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3474 for (i = 0 ; i < size ; i++ ) {
3475 emitcode ("push","%s",
3476 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3478 for (i = (size-1) ; i >= 0 ; i--) {
3479 emitcode ("pop","a%s",javaRet[i]);
3482 for (i = 0 ; i < size ; i++)
3483 emitcode ("mov","%s,%s",javaRet[i],
3484 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3486 for (i = size ; i < 4 ; i++ )
3487 emitcode ("mov","%s,#0",javaRet[i]);
3491 /*-----------------------------------------------------------------*/
3492 /* genRet - generate code for return statement */
3493 /*-----------------------------------------------------------------*/
3497 int size, offset = 0, pushed = 0;
3499 D (emitcode (";", "genRet "););
3501 /* if we have no return value then
3502 just generate the "ret" */
3506 /* if this is a JavaNative function then return
3507 value in different register */
3508 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3509 genJavaNativeRet(ic);
3512 /* we have something to return then
3513 move the return value into place */
3514 aopOp (IC_LEFT (ic), ic, FALSE,
3515 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3516 size = AOP_SIZE (IC_LEFT (ic));
3518 _startLazyDPSEvaluation ();
3522 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3524 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3526 emitcode ("push", "%s", l);
3531 /* Since A is the last element of fReturn,
3532 * is is OK to clobber it in the aopGet.
3534 l = aopGet (AOP (IC_LEFT (ic)), offset,
3535 FALSE, FALSE, NULL);
3536 if (strcmp (fReturn[offset], l))
3537 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3540 _endLazyDPSEvaluation ();
3547 if (strcmp (fReturn[pushed], "a"))
3548 emitcode ("pop", fReturn[pushed]);
3550 emitcode ("pop", "acc");
3553 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3556 /* generate a jump to the return label
3557 if the next is not the return statement */
3558 if (!(ic->next && ic->next->op == LABEL &&
3559 IC_LABEL (ic->next) == returnLabel))
3561 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3565 /*-----------------------------------------------------------------*/
3566 /* genLabel - generates a label */
3567 /*-----------------------------------------------------------------*/
3569 genLabel (iCode * ic)
3571 /* special case never generate */
3572 if (IC_LABEL (ic) == entryLabel)
3575 D (emitcode (";", "genLabel ");
3578 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3581 /*-----------------------------------------------------------------*/
3582 /* genGoto - generates a ljmp */
3583 /*-----------------------------------------------------------------*/
3585 genGoto (iCode * ic)
3587 D (emitcode (";", "genGoto ");
3589 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3592 /*-----------------------------------------------------------------*/
3593 /* findLabelBackwards: walks back through the iCode chain looking */
3594 /* for the given label. Returns number of iCode instructions */
3595 /* between that label and given ic. */
3596 /* Returns zero if label not found. */
3597 /*-----------------------------------------------------------------*/
3599 findLabelBackwards (iCode * ic, int key)
3608 /* If we have any pushes or pops, we cannot predict the distance.
3609 I don't like this at all, this should be dealt with in the
3611 if (ic->op == IPUSH || ic->op == IPOP) {
3615 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3617 /* printf("findLabelBackwards = %d\n", count); */
3625 /*-----------------------------------------------------------------*/
3626 /* genPlusIncr :- does addition with increment if possible */
3627 /*-----------------------------------------------------------------*/
3629 genPlusIncr (iCode * ic)
3631 unsigned int icount;
3632 unsigned int size = getDataSize (IC_RESULT (ic));
3634 /* will try to generate an increment */
3635 /* if the right side is not a literal
3637 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3640 /* if the literal value of the right hand side
3641 is greater than 4 then it is not worth it */
3642 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3645 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3646 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3648 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3652 /* if increment 16 bits in register */
3654 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3655 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3656 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3665 /* If the next instruction is a goto and the goto target
3666 * is <= 5 instructions previous to this, we can generate
3667 * jumps straight to that target.
3669 if (ic->next && ic->next->op == GOTO
3670 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3673 D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3674 tlbl = IC_LABEL (ic->next);
3679 tlbl = newiTempLabel (NULL);
3683 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3684 emitcode ("inc", "%s", l);
3686 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3687 IS_AOP_PREG (IC_RESULT (ic)))
3689 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3693 emitcode ("clr", "a");
3694 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3697 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
3698 emitcode ("inc", "%s", l);
3701 if (!strcmp(l, "acc"))
3703 emitcode("jnz", "!tlabel", tlbl->key + 100);
3705 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3706 IS_AOP_PREG (IC_RESULT (ic)))
3708 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3712 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3715 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3716 emitcode ("inc", "%s", l);
3720 if (!strcmp(l, "acc"))
3722 emitcode("jnz", "!tlabel", tlbl->key + 100);
3724 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3725 IS_AOP_PREG (IC_RESULT (ic)))
3727 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3731 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3734 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3735 emitcode ("inc", "%s", l); }
3739 emitcode ("", "!tlabeldef", tlbl->key + 100);
3744 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3745 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
3746 options.model == MODEL_FLAT24 ) {
3750 emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3752 emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3754 emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3757 while (icount--) emitcode ("inc","dptr");
3761 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3762 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3764 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3765 while (icount--) emitcode ("inc","dptr");
3766 emitcode ("mov","dps,#0");
3770 /* if the sizes are greater than 1 then we cannot */
3771 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3772 AOP_SIZE (IC_LEFT (ic)) > 1)
3775 /* we can if the aops of the left & result match or
3776 if they are in registers and the registers are the
3779 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3780 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3781 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3786 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3787 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3788 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3793 _startLazyDPSEvaluation ();
3796 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3798 _endLazyDPSEvaluation ();
3807 /*-----------------------------------------------------------------*/
3808 /* outBitAcc - output a bit in acc */
3809 /*-----------------------------------------------------------------*/
3811 outBitAcc (operand * result)
3813 symbol *tlbl = newiTempLabel (NULL);
3814 /* if the result is a bit */
3815 if (AOP_TYPE (result) == AOP_CRY)
3817 aopPut (AOP (result), "a", 0);
3821 emitcode ("jz", "!tlabel", tlbl->key + 100);
3822 emitcode ("mov", "a,%s", one);
3823 emitcode ("", "!tlabeldef", tlbl->key + 100);
3828 /*-----------------------------------------------------------------*/
3829 /* genPlusBits - generates code for addition of two bits */
3830 /*-----------------------------------------------------------------*/
3832 genPlusBits (iCode * ic)
3834 D (emitcode (";", "genPlusBits "););
3836 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3838 symbol *lbl = newiTempLabel (NULL);
3839 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3840 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3841 emitcode ("cpl", "c");
3842 emitcode ("", "!tlabeldef", (lbl->key + 100));
3843 outBitC (IC_RESULT (ic));
3847 emitcode ("clr", "a");
3848 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3849 emitcode ("rlc", "a");
3850 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3851 emitcode ("addc", "a,#0");
3852 outAcc (IC_RESULT (ic));
3857 adjustArithmeticResult (iCode * ic)
3859 if (opIsGptr (IC_RESULT (ic)) &&
3860 opIsGptr (IC_LEFT (ic)) &&
3861 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3863 aopPut (AOP (IC_RESULT (ic)),
3864 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3868 if (opIsGptr (IC_RESULT (ic)) &&
3869 opIsGptr (IC_RIGHT (ic)) &&
3870 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3872 aopPut (AOP (IC_RESULT (ic)),
3873 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3877 if (opIsGptr (IC_RESULT (ic)) &&
3878 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3879 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3880 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3881 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3884 SNPRINTF (buff, sizeof(buff),
3885 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3886 aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3890 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3891 // generates the result if possible. If result is generated, returns TRUE; otherwise
3892 // returns false and caller must deal with fact that result isn't aopOp'd.
3893 bool aopOp3(iCode * ic)
3895 bool dp1InUse, dp2InUse;
3898 // First, generate the right opcode. DPTR may be used if neither left nor result are
3901 // D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3902 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3903 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3904 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3906 // D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3907 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3908 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3909 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3912 // Right uses DPTR unless left or result is an AOP_STR; however,
3913 // if right is an AOP_STR, it must use DPTR regardless.
3914 if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
3915 && !AOP_IS_STR(IC_RIGHT(ic)))
3924 aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
3926 // if the right used DPTR, left MUST use DPTR2.
3927 // if the right used DPTR2, left MUST use DPTR.
3928 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3929 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3930 // enabling us to assign DPTR to result.
3932 if (AOP_USESDPTR(IC_RIGHT(ic)))
3936 else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3942 if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3952 aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3955 // We've op'd the left & right. So, if left or right are the same operand as result,
3956 // we know aopOp will succeed, and we can just do it & bail.
3957 if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))
3959 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
3962 if (isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3964 // D(emitcode(";", "aopOp3: (left | right) & result equal"););
3965 aopOp(IC_RESULT(ic),ic,TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
3969 // Operands may be equivalent (but not equal) if they share a spill location. If
3970 // so, use the same DPTR or DPTR2.
3971 if (operandsEqu (IC_LEFT(ic), IC_RESULT(ic)))
3973 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
3976 if (operandsEqu (IC_RIGHT(ic), IC_RESULT(ic)))
3978 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
3982 // Note which dptrs are currently in use.
3983 dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3984 dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3986 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
3988 if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3993 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3994 if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3999 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
4000 if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
4005 aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
4007 // Some sanity checking...
4008 if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
4011 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
4012 __FILE__, __LINE__, ic->filename, ic->lineno);
4013 emitcode(";", ">>> unexpected DPTR here.");
4016 if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
4019 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
4020 __FILE__, __LINE__, ic->filename, ic->lineno);
4021 emitcode(";", ">>> unexpected DPTR2 here.");
4027 // Macro to aopOp all three operands of an ic. If this cannot be done,
4028 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
4029 // will be set TRUE. The caller must then handle the case specially, noting
4030 // that the IC_RESULT operand is not aopOp'd.
4032 #define AOP_OP_3_NOFATAL(ic, rc) \
4033 do { rc = !aopOp3(ic); } while (0)
4035 // aopOp the left & right operands of an ic.
4036 #define AOP_OP_2(ic) \
4037 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
4038 aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
4040 // convienience macro.
4041 #define AOP_SET_LOCALS(ic) \
4042 left = IC_LEFT(ic); \
4043 right = IC_RIGHT(ic); \
4044 result = IC_RESULT(ic);
4047 // Given an integer value of pushedSize bytes on the stack,
4048 // adjust it to be resultSize bytes, either by discarding
4049 // the most significant bytes or by zero-padding.
4051 // On exit from this macro, pushedSize will have been adjusted to
4052 // equal resultSize, and ACC may be trashed.
4053 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
4054 /* If the pushed data is bigger than the result, \
4055 * simply discard unused bytes. Icky, but works. \
4057 while (pushedSize > resultSize) \
4059 D (emitcode (";", "discarding unused result byte."););\
4060 emitcode ("pop", "acc"); \
4063 if (pushedSize < resultSize) \
4065 emitcode ("clr", "a"); \
4066 /* Conversly, we haven't pushed enough here. \
4067 * just zero-pad, and all is well. \
4069 while (pushedSize < resultSize) \
4071 emitcode("push", "acc"); \
4075 assert(pushedSize == resultSize);
4077 /*-----------------------------------------------------------------*/
4078 /* genPlus - generates code for addition */
4079 /*-----------------------------------------------------------------*/
4081 genPlus (iCode * ic)
4083 int size, offset = 0;
4087 D (emitcode (";", "genPlus "););
4089 /* special cases :- */
4090 if ( AOP_IS_STR(IC_LEFT(ic)) &&
4091 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4092 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4093 size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4095 while (size--) emitcode ("inc","dptr");
4097 emitcode ("mov","a,dpl");
4098 emitcode ("add","a,#!constbyte",size & 0xff);
4099 emitcode ("mov","dpl,a");
4100 emitcode ("mov","a,dph");
4101 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4102 emitcode ("mov","dph,a");
4103 emitcode ("mov","a,dpx");
4104 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4105 emitcode ("mov","dpx,a");
4107 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4110 if ( IS_SYMOP(IC_LEFT(ic)) &&
4111 OP_SYMBOL(IC_LEFT(ic))->remat &&
4112 isOperandInFarSpace(IC_RIGHT(ic))) {
4113 operand *op = IC_RIGHT(ic);
4114 IC_RIGHT(ic) = IC_LEFT(ic);
4118 AOP_OP_3_NOFATAL (ic, pushResult);
4122 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4127 /* if literal, literal on the right or
4128 if left requires ACC or right is already
4130 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4131 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4132 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4134 operand *t = IC_RIGHT (ic);
4135 IC_RIGHT (ic) = IC_LEFT (ic);
4137 emitcode (";", "Swapped plus args.");
4140 /* if both left & right are in bit
4142 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4143 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4149 /* if left in bit space & right literal */
4150 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4151 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4153 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4154 /* if result in bit space */
4155 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4157 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4158 emitcode ("cpl", "c");
4159 outBitC (IC_RESULT (ic));
4163 size = getDataSize (IC_RESULT (ic));
4164 _startLazyDPSEvaluation ();
4167 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4168 emitcode ("addc", "a,#0");
4169 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4171 _endLazyDPSEvaluation ();
4176 /* if I can do an increment instead
4177 of add then GOOD for ME */
4178 if (genPlusIncr (ic) == TRUE)
4180 emitcode (";", "did genPlusIncr");
4185 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4187 _startLazyDPSEvaluation ();
4190 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4192 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4194 emitcode ("add", "a,%s",
4195 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4197 emitcode ("addc", "a,%s",
4198 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4202 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4204 /* right is going to use ACC or we would have taken the
4207 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4209 D(emitcode(";", "+ AOP_ACC special case."););
4210 emitcode("xch", "a, %s", DP2_RESULT_REG);
4212 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4215 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4218 emitcode("add", "a, %s", DP2_RESULT_REG);
4222 emitcode ("add", "a,%s",
4223 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4229 emitcode ("addc", "a,%s",
4230 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4236 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4240 emitcode ("push", "acc");
4244 _endLazyDPSEvaluation ();
4248 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4250 size = getDataSize (IC_LEFT (ic));
4251 rSize = getDataSize (IC_RESULT (ic));
4253 ADJUST_PUSHED_RESULT(size, rSize);
4255 _startLazyDPSEvaluation ();
4258 emitcode ("pop", "acc");
4259 aopPut (AOP (IC_RESULT (ic)), "a", size);
4261 _endLazyDPSEvaluation ();
4264 adjustArithmeticResult (ic);
4267 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4268 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4269 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4272 /*-----------------------------------------------------------------*/
4273 /* genMinusDec :- does subtraction with deccrement if possible */
4274 /*-----------------------------------------------------------------*/
4276 genMinusDec (iCode * ic)
4278 unsigned int icount;
4279 unsigned int size = getDataSize (IC_RESULT (ic));
4281 /* will try to generate an increment */
4282 /* if the right side is not a literal
4284 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4287 /* if the literal value of the right hand side
4288 is greater than 4 then it is not worth it */
4289 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4292 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4293 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4295 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4299 /* if decrement 16 bits in register */
4300 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4301 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4302 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4311 /* If the next instruction is a goto and the goto target
4312 * is <= 5 instructions previous to this, we can generate
4313 * jumps straight to that target.
4315 if (ic->next && ic->next->op == GOTO
4316 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4319 emitcode (";", "tail decrement optimized (range %d)", labelRange);
4320 tlbl = IC_LABEL (ic->next);
4325 tlbl = newiTempLabel (NULL);
4329 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4330 emitcode ("dec", "%s", l);
4332 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4333 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4334 IS_AOP_PREG (IC_RESULT (ic)))
4336 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4340 emitcode ("mov", "a,#!constbyte",0xff);
4341 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4343 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4344 emitcode ("dec", "%s", l);
4347 if (!strcmp(l, "acc"))
4349 emitcode("jnz", "!tlabel", tlbl->key + 100);
4351 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4352 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4353 IS_AOP_PREG (IC_RESULT (ic)))
4355 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4359 emitcode ("mov", "a,#!constbyte",0xff);
4360 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4362 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4363 emitcode ("dec", "%s", l);
4367 if (!strcmp(l, "acc"))
4369 emitcode("jnz", "!tlabel", tlbl->key + 100);
4371 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4372 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4373 IS_AOP_PREG (IC_RESULT (ic)))
4375 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4379 emitcode ("mov", "a,#!constbyte",0xff);
4380 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4382 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4383 emitcode ("dec", "%s", l);
4387 emitcode ("", "!tlabeldef", tlbl->key + 100);
4392 /* if the sizes are greater than 1 then we cannot */
4393 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4394 AOP_SIZE (IC_LEFT (ic)) > 1)
4397 /* we can if the aops of the left & result match or
4398 if they are in registers and the registers are the
4401 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4402 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4403 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4406 _startLazyDPSEvaluation ();
4409 emitcode ("dec", "%s",
4410 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4412 _endLazyDPSEvaluation ();
4420 /*-----------------------------------------------------------------*/
4421 /* addSign - complete with sign */
4422 /*-----------------------------------------------------------------*/
4424 addSign (operand * result, int offset, int sign)
4426 int size = (getDataSize (result) - offset);
4429 _startLazyDPSEvaluation();
4432 emitcode ("rlc", "a");
4433 emitcode ("subb", "a,acc");
4436 aopPut (AOP (result), "a", offset++);
4443 aopPut (AOP (result), zero, offset++);
4446 _endLazyDPSEvaluation();
4450 /*-----------------------------------------------------------------*/
4451 /* genMinusBits - generates code for subtraction of two bits */
4452 /*-----------------------------------------------------------------*/
4454 genMinusBits (iCode * ic)
4456 symbol *lbl = newiTempLabel (NULL);
4458 D (emitcode (";", "genMinusBits "););
4460 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4462 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4463 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4464 emitcode ("cpl", "c");
4465 emitcode ("", "!tlabeldef", (lbl->key + 100));
4466 outBitC (IC_RESULT (ic));
4470 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4471 emitcode ("subb", "a,acc");
4472 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4473 emitcode ("inc", "a");
4474 emitcode ("", "!tlabeldef", (lbl->key + 100));
4475 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4476 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4480 /*-----------------------------------------------------------------*/
4481 /* genMinus - generates code for subtraction */
4482 /*-----------------------------------------------------------------*/
4484 genMinus (iCode * ic)
4486 int size, offset = 0;
4491 D (emitcode (";", "genMinus "););
4493 AOP_OP_3_NOFATAL(ic, pushResult);
4497 /* special cases :- */
4498 /* if both left & right are in bit space */
4499 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4500 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4506 /* if I can do an decrement instead
4507 of subtract then GOOD for ME */
4508 if (genMinusDec (ic) == TRUE)
4513 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4515 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4521 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4526 /* if literal, add a,#-lit, else normal subb */
4527 _startLazyDPSEvaluation ();
4529 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4530 if (AOP_USESDPTR(IC_RIGHT(ic))) {
4531 emitcode ("mov","b,%s",
4532 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4533 MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4534 emitcode ("subb","a,b");
4536 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4537 emitcode ("subb", "a,%s",
4538 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE,
4542 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4543 /* first add without previous c */
4545 if (!size && lit==-1) {
4546 emitcode ("dec", "a");
4548 emitcode ("add", "a,#!constbyte",
4549 (unsigned int) (lit & 0x0FFL));
4552 emitcode ("addc", "a,#!constbyte",
4553 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4558 emitcode ("push", "acc");
4560 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4564 _endLazyDPSEvaluation ();
4568 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4570 size = getDataSize (IC_LEFT (ic));
4571 rSize = getDataSize (IC_RESULT (ic));
4573 ADJUST_PUSHED_RESULT(size, rSize);
4575 _startLazyDPSEvaluation ();
4578 emitcode ("pop", "acc");
4579 aopPut (AOP (IC_RESULT (ic)), "a", size);
4581 _endLazyDPSEvaluation ();
4584 adjustArithmeticResult (ic);
4587 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4588 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4589 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4593 /*-----------------------------------------------------------------*/
4594 /* genMultbits :- multiplication of bits */
4595 /*-----------------------------------------------------------------*/
4597 genMultbits (operand * left,
4602 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4603 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4604 aopOp(result, ic, TRUE, FALSE);
4609 /*-----------------------------------------------------------------*/
4610 /* genMultOneByte : 8*8=8/16 bit multiplication */
4611 /*-----------------------------------------------------------------*/
4613 genMultOneByte (operand * left,
4620 bool runtimeSign, compiletimeSign;
4621 bool lUnsigned, rUnsigned;
4624 /* (if two literals: the value is computed before) */
4625 /* if one literal, literal on the right */
4626 if (AOP_TYPE (left) == AOP_LIT)
4631 emitcode (";", "swapped left and right");
4634 /* (if two literals: the value is computed before) */
4635 /* if one literal, literal on the right */
4636 if (AOP_TYPE (left) == AOP_LIT)
4641 /* emitcode (";", "swapped left and right"); */
4643 /* if no literal, unsigned on the right: shorter code */
4644 if ( AOP_TYPE (right) != AOP_LIT
4645 && SPEC_USIGN (getSpec (operandType (left))))
4652 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4653 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4655 if ((lUnsigned && rUnsigned)
4656 /* sorry, I don't know how to get size
4657 without calling aopOp (result,...);
4658 see Feature Request */
4659 /* || size == 1 */ ) /* no, this is not a bug; with a 1 byte result there's
4660 no need to take care about the signedness! */
4662 /* just an unsigned 8 * 8 = 8 multiply
4664 /* emitcode (";","unsigned"); */
4665 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4666 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4667 emitcode ("mul", "ab");
4669 _G.accInUse++; _G.bInUse++;
4670 aopOp (result, ic, TRUE, FALSE);
4671 size = AOP_SIZE (result);
4673 if (size < 1 || size > 2)
4675 /* this should never happen */
4676 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4677 size, __FILE__, lineno);
4681 aopPut (AOP (result), "a", 0);
4682 _G.accInUse--; _G.bInUse--;
4684 aopPut (AOP (result), "b", 1);
4688 /* we have to do a signed multiply */
4689 /* emitcode (";", "signed"); */
4691 /* now sign adjust for both left & right */
4693 /* let's see what's needed: */
4694 /* apply negative sign during runtime */
4695 runtimeSign = FALSE;
4696 /* negative sign from literals */
4697 compiletimeSign = FALSE;
4701 if (AOP_TYPE(left) == AOP_LIT)
4703 /* signed literal */
4704 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4706 compiletimeSign = TRUE;
4709 /* signed but not literal */
4715 if (AOP_TYPE(right) == AOP_LIT)
4717 /* signed literal */
4718 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4720 compiletimeSign ^= TRUE;
4723 /* signed but not literal */
4727 /* initialize F0, which stores the runtime sign */
4730 if (compiletimeSign)
4731 emitcode ("setb", "F0"); /* set sign flag */
4733 emitcode ("clr", "F0"); /* reset sign flag */
4736 /* save the signs of the operands */
4737 if (AOP_TYPE(right) == AOP_LIT)
4739 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4741 if (!rUnsigned && val < 0)
4742 emitcode ("mov", "b,#!constbyte", -val);
4744 emitcode ("mov", "b,#!constbyte", (unsigned char) val);
4746 else /* ! literal */
4748 if (rUnsigned) /* emitcode (";", "signed"); */
4749 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4752 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4753 lbl = newiTempLabel (NULL);
4754 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
4755 emitcode ("cpl", "F0"); /* complement sign flag */
4756 emitcode ("cpl", "a"); /* 2's complement */
4757 emitcode ("inc", "a");
4758 emitcode ("", "!tlabeldef", lbl->key + 100);
4759 emitcode ("mov", "b,a");
4763 if (AOP_TYPE(left) == AOP_LIT)
4765 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4767 if (!lUnsigned && val < 0)
4768 emitcode ("mov", "a,#!constbyte", -val);
4770 emitcode ("mov", "a,#!constbyte", (unsigned char) val);
4772 else /* ! literal */
4774 if (lUnsigned) /* emitcode (";", "signed"); */
4776 emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4779 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4780 lbl = newiTempLabel (NULL);
4781 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
4782 emitcode ("cpl", "F0"); /* complement sign flag */
4783 emitcode ("cpl", "a"); /* 2's complement */
4784 emitcode ("inc", "a");
4785 emitcode ("", "!tlabeldef", lbl->key + 100);
4789 /* now the multiplication */
4790 emitcode ("mul", "ab");
4791 _G.accInUse++;_G.bInUse++;
4792 aopOp(result, ic, TRUE, FALSE);
4793 size = AOP_SIZE (result);
4795 if (size < 1 || size > 2)
4797 /* this should never happen */
4798 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4799 size, __FILE__, lineno);
4803 if (runtimeSign || compiletimeSign)
4805 lbl = newiTempLabel (NULL);
4807 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
4808 emitcode ("cpl", "a"); /* lsb 2's complement */
4810 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4813 emitcode ("add", "a,#1"); /* this sets carry flag */
4814 emitcode ("xch", "a,b");
4815 emitcode ("cpl", "a"); /* msb 2's complement */
4816 emitcode ("addc", "a,#0");
4817 emitcode ("xch", "a,b");
4819 emitcode ("", "!tlabeldef", lbl->key + 100);
4821 aopPut (AOP (result), "a", 0);
4822 _G.accInUse--;_G.bInUse--;
4824 aopPut (AOP (result), "b", 1);
4827 /*-----------------------------------------------------------------*/
4828 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4829 /*-----------------------------------------------------------------*/
4830 static void genMultTwoByte (operand *left, operand *right,
4831 operand *result, iCode *ic)
4833 sym_link *retype = getSpec(operandType(right));
4834 sym_link *letype = getSpec(operandType(left));
4835 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4838 if (AOP_TYPE (left) == AOP_LIT) {
4843 /* save EA bit in F1 */
4844 lbl = newiTempLabel(NULL);
4845 emitcode ("setb","F1");
4846 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4847 emitcode ("clr","F1");
4848 emitcode("","!tlabeldef",lbl->key+100);
4850 /* load up MB with right */
4852 emitcode("clr","F0");
4853 if (AOP_TYPE(right) == AOP_LIT) {
4854 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4856 emitcode("setb","F0");
4859 emitcode ("mov","mb,#!constbyte",val & 0xff);
4860 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4862 lbl = newiTempLabel(NULL);
4863 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4864 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4865 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4866 emitcode ("xch", "a,b");
4867 emitcode ("cpl","a");
4868 emitcode ("add", "a,#1");
4869 emitcode ("xch", "a,b");
4870 emitcode ("cpl", "a"); // msb
4871 emitcode ("addc", "a,#0");
4872 emitcode ("setb","F0");
4873 emitcode ("","!tlabeldef",lbl->key+100);
4874 emitcode ("mov","mb,b");
4875 emitcode ("mov","mb,a");
4878 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4879 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4881 /* load up MA with left */
4883 lbl = newiTempLabel(NULL);
4884 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4885 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4886 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4887 emitcode ("xch", "a,b");
4888 emitcode ("cpl","a");
4889 emitcode ("add", "a,#1");
4890 emitcode ("xch", "a,b");
4891 emitcode ("cpl", "a"); // msb
4892 emitcode ("addc","a,#0");
4893 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4894 emitcode ("setb","F0");
4895 emitcode ("","!tlabeldef",lbl->key+100);
4896 emitcode ("mov","ma,b");
4897 emitcode ("mov","ma,a");
4899 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4900 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4902 /* wait for multiplication to finish */
4903 lbl = newiTempLabel(NULL);
4904 emitcode("","!tlabeldef", lbl->key+100);
4905 emitcode("mov","a,mcnt1");
4906 emitcode("anl","a,#!constbyte",0x80);
4907 emitcode("jnz","!tlabel",lbl->key+100);
4909 freeAsmop (left, NULL, ic, TRUE);
4910 freeAsmop (right, NULL, ic,TRUE);
4911 aopOp(result, ic, TRUE, FALSE);
4913 /* if unsigned then simple */
4915 emitcode ("mov","a,ma");
4916 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4917 emitcode ("mov","a,ma");
4918 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4919 aopPut(AOP(result),"ma",1);
4920 aopPut(AOP(result),"ma",0);
4922 emitcode("push","ma");
4923 emitcode("push","ma");
4924 emitcode("push","ma");
4926 /* negate result if needed */
4927 lbl = newiTempLabel(NULL);
4928 emitcode("jnb","F0,!tlabel",lbl->key+100);
4929 emitcode("cpl","a");
4930 emitcode("add","a,#1");
4931 emitcode("","!tlabeldef", lbl->key+100);
4932 if (AOP_TYPE(result) == AOP_ACC)
4934 D(emitcode(";", "ACC special case."););
4935 /* We know result is the only live aop, and
4936 * it's obviously not a DPTR2, so AP is available.
4938 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4942 aopPut(AOP(result),"a",0);
4945 emitcode("pop","acc");
4946 lbl = newiTempLabel(NULL);
4947 emitcode("jnb","F0,!tlabel",lbl->key+100);
4948 emitcode("cpl","a");
4949 emitcode("addc","a,#0");
4950 emitcode("","!tlabeldef", lbl->key+100);
4951 aopPut(AOP(result),"a",1);
4952 emitcode("pop","acc");
4953 if (AOP_SIZE(result) >= 3) {
4954 lbl = newiTempLabel(NULL);
4955 emitcode("jnb","F0,!tlabel",lbl->key+100);
4956 emitcode("cpl","a");
4957 emitcode("addc","a,#0");
4958 emitcode("","!tlabeldef", lbl->key+100);
4959 aopPut(AOP(result),"a",2);
4961 emitcode("pop","acc");
4962 if (AOP_SIZE(result) >= 4) {
4963 lbl = newiTempLabel(NULL);
4964 emitcode("jnb","F0,!tlabel",lbl->key+100);
4965 emitcode("cpl","a");
4966 emitcode("addc","a,#0");
4967 emitcode("","!tlabeldef", lbl->key+100);
4968 aopPut(AOP(result),"a",3);
4970 if (AOP_TYPE(result) == AOP_ACC)
4972 /* We stashed the result away above. */
4973 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4977 freeAsmop (result, NULL, ic, TRUE);
4979 /* restore EA bit in F1 */
4980 lbl = newiTempLabel(NULL);
4981 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4982 emitcode ("setb","EA");
4983 emitcode("","!tlabeldef",lbl->key+100);
4987 /*-----------------------------------------------------------------*/
4988 /* genMult - generates code for multiplication */
4989 /*-----------------------------------------------------------------*/
4991 genMult (iCode * ic)
4993 operand *left = IC_LEFT (ic);
4994 operand *right = IC_RIGHT (ic);
4995 operand *result = IC_RESULT (ic);
4997 D (emitcode (";", "genMult "););
4999 /* assign the amsops */
5002 /* special cases first */
5004 if (AOP_TYPE (left) == AOP_CRY &&
5005 AOP_TYPE (right) == AOP_CRY)
5007 genMultbits (left, right, result, ic);
5011 /* if both are of size == 1 */
5012 if (AOP_SIZE (left) == 1 &&
5013 AOP_SIZE (right) == 1)
5015 genMultOneByte (left, right, result, ic);
5019 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5020 /* use the ds390 ARITHMETIC accel UNIT */
5021 genMultTwoByte (left, right, result, ic);
5024 /* should have been converted to function call */
5028 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5029 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5030 freeAsmop (result, NULL, ic, TRUE);
5033 /*-----------------------------------------------------------------*/
5034 /* genDivbits :- division of bits */
5035 /*-----------------------------------------------------------------*/
5037 genDivbits (operand * left,
5045 /* the result must be bit */
5046 LOAD_AB_FOR_DIV (left, right, l);
5047 emitcode ("div", "ab");
5048 emitcode ("rrc", "a");
5049 aopOp(result, ic, TRUE, FALSE);
5051 aopPut (AOP (result), "c", 0);
5054 /*-----------------------------------------------------------------*/
5055 /* genDivOneByte : 8 bit division */
5056 /*-----------------------------------------------------------------*/
5058 genDivOneByte (operand * left,
5063 bool lUnsigned, rUnsigned;
5064 bool runtimeSign, compiletimeSign;
5070 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5071 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5073 /* signed or unsigned */
5074 if (lUnsigned && rUnsigned)
5076 /* unsigned is easy */
5077 LOAD_AB_FOR_DIV (left, right, l);
5078 emitcode ("div", "ab");
5081 aopOp (result, ic, TRUE, FALSE);
5082 aopPut (AOP (result), "a", 0);
5085 size = AOP_SIZE (result) - 1;
5088 aopPut (AOP (result), zero, offset++);
5092 /* signed is a little bit more difficult */
5094 /* now sign adjust for both left & right */
5096 /* let's see what's needed: */
5097 /* apply negative sign during runtime */
5098 runtimeSign = FALSE;
5099 /* negative sign from literals */
5100 compiletimeSign = FALSE;
5104 if (AOP_TYPE(left) == AOP_LIT)
5106 /* signed literal */
5107 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5109 compiletimeSign = TRUE;
5112 /* signed but not literal */
5118 if (AOP_TYPE(right) == AOP_LIT)
5120 /* signed literal */
5121 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5123 compiletimeSign ^= TRUE;
5126 /* signed but not literal */
5130 /* initialize F0, which stores the runtime sign */
5133 if (compiletimeSign)
5134 emitcode ("setb", "F0"); /* set sign flag */
5136 emitcode ("clr", "F0"); /* reset sign flag */
5139 /* save the signs of the operands */
5140 if (AOP_TYPE(right) == AOP_LIT)
5142 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5144 if (!rUnsigned && val < 0)
5145 emitcode ("mov", "b,#0x%02x", -val);
5147 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5149 else /* ! literal */
5152 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5155 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5156 lbl = newiTempLabel (NULL);
5157 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5158 emitcode ("cpl", "F0"); /* complement sign flag */
5159 emitcode ("cpl", "a"); /* 2's complement */
5160 emitcode ("inc", "a");
5161 emitcode ("", "!tlabeldef", lbl->key + 100);
5162 emitcode ("mov", "b,a");
5166 if (AOP_TYPE(left) == AOP_LIT)
5168 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5170 if (!lUnsigned && val < 0)
5171 emitcode ("mov", "a,#0x%02x", -val);
5173 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5175 else /* ! literal */
5178 emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5181 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5182 lbl = newiTempLabel (NULL);
5183 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5184 emitcode ("cpl", "F0"); /* complement sign flag */
5185 emitcode ("cpl", "a"); /* 2's complement */
5186 emitcode ("inc", "a");
5187 emitcode ("", "!tlabeldef", lbl->key + 100);
5191 /* now the division */
5192 emitcode ("nop", "; workaround for DS80C390 div bug.");
5193 emitcode ("div", "ab");
5195 if (runtimeSign || compiletimeSign)
5197 lbl = newiTempLabel (NULL);
5199 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5200 emitcode ("cpl", "a"); /* lsb 2's complement */
5201 emitcode ("inc", "a");
5202 emitcode ("", "!tlabeldef", lbl->key + 100);
5204 _G.accInUse++; _G.bInUse++;
5205 aopOp (result, ic, TRUE, FALSE);
5206 size = AOP_SIZE (result) - 1;
5210 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5211 then the result will be in b, a */
5212 emitcode ("mov", "b,a"); /* 1 */
5213 /* msb is 0x00 or 0xff depending on the sign */
5216 emitcode ("mov", "c,F0");
5217 emitcode ("subb", "a,acc");
5218 emitcode ("xch", "a,b"); /* 2 */
5220 aopPut (AOP (result), "b", offset++); /* write msb's */
5222 else /* compiletimeSign */
5224 aopPut (AOP (result), "#0xff", offset++); /* write msb's */
5226 aopPut (AOP (result), "a", 0); /* 3: write lsb */
5230 _G.accInUse++; _G.bInUse++;
5231 aopOp(result, ic, TRUE, FALSE);
5232 size = AOP_SIZE (result) - 1;
5234 aopPut (AOP (result), "a", 0);
5236 aopPut (AOP (result), zero, offset++);
5238 _G.accInUse--; _G.bInUse--;
5242 /*-----------------------------------------------------------------*/
5243 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
5244 /*-----------------------------------------------------------------*/
5245 static void genDivTwoByte (operand *left, operand *right,
5246 operand *result, iCode *ic)
5248 sym_link *retype = getSpec(operandType(right));
5249 sym_link *letype = getSpec(operandType(left));
5250 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5253 /* save EA bit in F1 */
5254 lbl = newiTempLabel(NULL);
5255 emitcode ("setb","F1");
5256 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5257 emitcode ("clr","F1");
5258 emitcode("","!tlabeldef",lbl->key+100);
5260 /* load up MA with left */
5262 emitcode("clr","F0");
5263 lbl = newiTempLabel(NULL);
5264 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5265 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5266 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5267 emitcode ("xch", "a,b");
5268 emitcode ("cpl","a");
5269 emitcode ("add", "a,#1");
5270 emitcode ("xch", "a,b");
5271 emitcode ("cpl", "a"); // msb
5272 emitcode ("addc","a,#0");
5273 emitcode ("setb","F0");
5274 emitcode ("","!tlabeldef",lbl->key+100);
5275 emitcode ("mov","ma,b");
5276 emitcode ("mov","ma,a");
5278 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5279 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5282 /* load up MB with right */
5284 if (AOP_TYPE(right) == AOP_LIT) {
5285 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5287 lbl = newiTempLabel(NULL);
5288 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5289 emitcode("setb","F0");
5290 emitcode ("","!tlabeldef",lbl->key+100);
5293 emitcode ("mov","mb,#!constbyte",val & 0xff);
5294 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5296 lbl = newiTempLabel(NULL);
5297 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5298 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5299 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5300 emitcode ("xch", "a,b");
5301 emitcode ("cpl","a");
5302 emitcode ("add", "a,#1");
5303 emitcode ("xch", "a,b");
5304 emitcode ("cpl", "a"); // msb
5305 emitcode ("addc", "a,#0");
5306 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5307 emitcode ("setb","F0");
5308 emitcode ("","!tlabeldef",lbl->key+100);
5309 emitcode ("mov","mb,b");
5310 emitcode ("mov","mb,a");
5313 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5314 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5317 /* wait for multiplication to finish */
5318 lbl = newiTempLabel(NULL);
5319 emitcode("","!tlabeldef", lbl->key+100);
5320 emitcode("mov","a,mcnt1");
5321 emitcode("anl","a,#!constbyte",0x80);
5322 emitcode("jnz","!tlabel",lbl->key+100);
5324 freeAsmop (left, NULL, ic, TRUE);
5325 freeAsmop (right, NULL, ic,TRUE);
5326 aopOp(result, ic, TRUE, FALSE);
5328 /* if unsigned then simple */
5330 aopPut(AOP(result),"ma",1);
5331 aopPut(AOP(result),"ma",0);
5333 emitcode("push","ma");
5335 /* negate result if needed */
5336 lbl = newiTempLabel(NULL);
5337 emitcode("jnb","F0,!tlabel",lbl->key+100);
5338 emitcode("cpl","a");
5339 emitcode("add","a,#1");
5340 emitcode("","!tlabeldef", lbl->key+100);
5341 aopPut(AOP(result),"a",0);
5342 emitcode("pop","acc");
5343 lbl = newiTempLabel(NULL);
5344 emitcode("jnb","F0,!tlabel",lbl->key+100);
5345 emitcode("cpl","a");
5346 emitcode("addc","a,#0");
5347 emitcode("","!tlabeldef", lbl->key+100);
5348 aopPut(AOP(result),"a",1);
5350 freeAsmop (result, NULL, ic, TRUE);
5351 /* restore EA bit in F1 */
5352 lbl = newiTempLabel(NULL);
5353 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5354 emitcode ("setb","EA");
5355 emitcode("","!tlabeldef",lbl->key+100);
5359 /*-----------------------------------------------------------------*/
5360 /* genDiv - generates code for division */
5361 /*-----------------------------------------------------------------*/
5365 operand *left = IC_LEFT (ic);
5366 operand *right = IC_RIGHT (ic);
5367 operand *result = IC_RESULT (ic);
5369 D (emitcode (";", "genDiv "););
5371 /* assign the amsops */
5374 /* special cases first */
5376 if (AOP_TYPE (left) == AOP_CRY &&
5377 AOP_TYPE (right) == AOP_CRY)
5379 genDivbits (left, right, result, ic);
5383 /* if both are of size == 1 */
5384 if (AOP_SIZE (left) == 1 &&
5385 AOP_SIZE (right) == 1)
5387 genDivOneByte (left, right, result, ic);
5391 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5392 /* use the ds390 ARITHMETIC accel UNIT */
5393 genDivTwoByte (left, right, result, ic);
5396 /* should have been converted to function call */
5399 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5400 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5401 freeAsmop (result, NULL, ic, TRUE);
5404 /*-----------------------------------------------------------------*/
5405 /* genModbits :- modulus of bits */
5406 /*-----------------------------------------------------------------*/
5408 genModbits (operand * left,
5416 /* the result must be bit */
5417 LOAD_AB_FOR_DIV (left, right, l);
5418 emitcode ("div", "ab");
5419 emitcode ("mov", "a,b");
5420 emitcode ("rrc", "a");
5421 aopOp(result, ic, TRUE, FALSE);
5422 aopPut (AOP (result), "c", 0);
5425 /*-----------------------------------------------------------------*/
5426 /* genModOneByte : 8 bit modulus */
5427 /*-----------------------------------------------------------------*/
5429 genModOneByte (operand * left,
5434 bool lUnsigned, rUnsigned;
5435 bool runtimeSign, compiletimeSign;
5441 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5442 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5444 /* signed or unsigned */
5445 if (lUnsigned && rUnsigned)
5447 /* unsigned is easy */
5448 LOAD_AB_FOR_DIV (left, right, l);
5449 emitcode ("div", "ab");
5450 aopOp (result, ic, TRUE, FALSE);
5451 aopPut (AOP (result), "b", 0);
5453 for (size = AOP_SIZE (result) - 1; size--;)
5454 aopPut (AOP (result), zero, offset++);
5458 /* signed is a little bit more difficult */
5460 /* now sign adjust for both left & right */
5462 /* modulus: sign of the right operand has no influence on the result! */
5463 if (AOP_TYPE(right) == AOP_LIT)
5465 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5467 if (!rUnsigned && val < 0)
5468 emitcode ("mov", "b,#0x%02x", -val);
5470 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5472 else /* ! literal */
5475 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5478 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5479 lbl = newiTempLabel (NULL);
5480 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5481 emitcode ("cpl", "a"); /* 2's complement */
5482 emitcode ("inc", "a");
5483 emitcode ("", "!tlabeldef", lbl->key + 100);
5484 emitcode ("mov", "b,a");
5488 /* let's see what's needed: */
5489 /* apply negative sign during runtime */
5490 runtimeSign = FALSE;
5491 /* negative sign from literals */
5492 compiletimeSign = FALSE;
5494 /* sign adjust left side */
5495 if (AOP_TYPE(left) == AOP_LIT)
5497 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5499 if (!lUnsigned && val < 0)
5501 compiletimeSign = TRUE; /* set sign flag */
5502 emitcode ("mov", "a,#0x%02x", -val);
5505 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5507 else /* ! literal */
5509 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5514 emitcode ("clr", "F0"); /* clear sign flag */
5516 lbl = newiTempLabel (NULL);
5517 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5518 emitcode ("setb", "F0"); /* set sign flag */
5519 emitcode ("cpl", "a"); /* 2's complement */
5520 emitcode ("inc", "a");
5521 emitcode ("", "!tlabeldef", lbl->key + 100);
5525 /* now the modulus */
5526 emitcode ("nop", "; workaround for DS80C390 div bug.");
5527 emitcode ("div", "ab");
5529 if (runtimeSign || compiletimeSign)
5531 emitcode ("mov", "a,b");
5532 lbl = newiTempLabel (NULL);
5534 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5535 emitcode ("cpl", "a"); /* lsb 2's complement */
5536 emitcode ("inc", "a");
5537 emitcode ("", "!tlabeldef", lbl->key + 100);
5539 _G.accInUse++; _G.bInUse++;
5540 aopOp (result, ic, TRUE, FALSE);
5541 size = AOP_SIZE (result) - 1;
5545 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5546 then the result will be in b, a */
5547 emitcode ("mov", "b,a"); /* 1 */
5548 /* msb is 0x00 or 0xff depending on the sign */
5551 emitcode ("mov", "c,F0");
5552 emitcode ("subb", "a,acc");
5553 emitcode ("xch", "a,b"); /* 2 */
5555 aopPut (AOP (result), "b", offset++); /* write msb's */
5557 else /* compiletimeSign */
5559 aopPut (AOP (result), "#0xff", offset++); /* write msb's */
5561 aopPut (AOP (result), "a", 0); /* 3: write lsb */
5565 _G.accInUse++; _G.bInUse++;
5566 aopOp(result, ic, TRUE, FALSE);
5567 size = AOP_SIZE (result) - 1;
5569 aopPut (AOP (result), "b", 0);
5571 aopPut (AOP (result), zero, offset++);
5573 _G.accInUse--; _G.bInUse--;
5577 /*-----------------------------------------------------------------*/
5578 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
5579 /*-----------------------------------------------------------------*/
5580 static void genModTwoByte (operand *left, operand *right,
5581 operand *result, iCode *ic)
5583 sym_link *retype = getSpec(operandType(right));
5584 sym_link *letype = getSpec(operandType(left));
5585 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5588 /* load up MA with left */
5589 /* save EA bit in F1 */
5590 lbl = newiTempLabel(NULL);
5591 emitcode ("setb","F1");
5592 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5593 emitcode ("clr","F1");
5594 emitcode("","!tlabeldef",lbl->key+100);
5597 lbl = newiTempLabel(NULL);
5598 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5599 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5600 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5601 emitcode ("xch", "a,b");
5602 emitcode ("cpl","a");
5603 emitcode ("add", "a,#1");
5604 emitcode ("xch", "a,b");
5605 emitcode ("cpl", "a"); // msb
5606 emitcode ("addc","a,#0");
5607 emitcode ("","!tlabeldef",lbl->key+100);
5608 emitcode ("mov","ma,b");
5609 emitcode ("mov","ma,a");
5611 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5612 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5615 /* load up MB with right */
5617 if (AOP_TYPE(right) == AOP_LIT) {
5618 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5622 emitcode ("mov","mb,#!constbyte",val & 0xff);
5623 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5625 lbl = newiTempLabel(NULL);
5626 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5627 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5628 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5629 emitcode ("xch", "a,b");
5630 emitcode ("cpl","a");
5631 emitcode ("add", "a,#1");
5632 emitcode ("xch", "a,b");
5633 emitcode ("cpl", "a"); // msb
5634 emitcode ("addc", "a,#0");
5635 emitcode ("","!tlabeldef",lbl->key+100);
5636 emitcode ("mov","mb,b");
5637 emitcode ("mov","mb,a");
5640 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5641 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5644 /* wait for multiplication to finish */
5645 lbl = newiTempLabel(NULL);
5646 emitcode("","!tlabeldef", lbl->key+100);
5647 emitcode("mov","a,mcnt1");
5648 emitcode("anl","a,#!constbyte",0x80);
5649 emitcode("jnz","!tlabel",lbl->key+100);
5651 freeAsmop (left, NULL, ic, TRUE);
5652 freeAsmop (right, NULL, ic,TRUE);
5653 aopOp(result, ic, TRUE, FALSE);
5655 aopPut(AOP(result),"mb",1);
5656 aopPut(AOP(result),"mb",0);
5657 freeAsmop (result, NULL, ic, TRUE);
5659 /* restore EA bit in F1 */
5660 lbl = newiTempLabel(NULL);
5661 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5662 emitcode ("setb","EA");
5663 emitcode("","!tlabeldef",lbl->key+100);
5667 /*-----------------------------------------------------------------*/
5668 /* genMod - generates code for division */
5669 /*-----------------------------------------------------------------*/
5673 operand *left = IC_LEFT (ic);
5674 operand *right = IC_RIGHT (ic);
5675 operand *result = IC_RESULT (ic);
5677 D (emitcode (";", "genMod "); );
5679 /* assign the amsops */
5682 /* special cases first */
5684 if (AOP_TYPE (left) == AOP_CRY &&
5685 AOP_TYPE (right) == AOP_CRY)
5687 genModbits (left, right, result, ic);
5691 /* if both are of size == 1 */
5692 if (AOP_SIZE (left) == 1 &&
5693 AOP_SIZE (right) == 1)
5695 genModOneByte (left, right, result, ic);
5699 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5700 /* use the ds390 ARITHMETIC accel UNIT */
5701 genModTwoByte (left, right, result, ic);
5705 /* should have been converted to function call */
5709 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5710 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5711 freeAsmop (result, NULL, ic, TRUE);
5714 /*-----------------------------------------------------------------*/
5715 /* genIfxJump :- will create a jump depending on the ifx */
5716 /*-----------------------------------------------------------------*/
5718 genIfxJump (iCode * ic, char *jval)
5721 symbol *tlbl = newiTempLabel (NULL);
5724 D (emitcode (";", "genIfxJump"););
5726 /* if true label then we jump if condition
5730 jlbl = IC_TRUE (ic);
5731 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5732 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5736 /* false label is present */
5737 jlbl = IC_FALSE (ic);
5738 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5739 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5741 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5742 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5744 emitcode (inst, "!tlabel", tlbl->key + 100);
5745 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5746 emitcode ("", "!tlabeldef", tlbl->key + 100);
5748 /* mark the icode as generated */
5752 /*-----------------------------------------------------------------*/
5753 /* genCmp :- greater or less than comparison */
5754 /*-----------------------------------------------------------------*/
5756 genCmp (operand * left, operand * right,
5757 iCode * ic, iCode * ifx, int sign)
5759 int size, offset = 0;
5760 unsigned long lit = 0L;
5763 D (emitcode (";", "genCmp"););
5765 result = IC_RESULT (ic);
5767 /* if left & right are bit variables */
5768 if (AOP_TYPE (left) == AOP_CRY &&
5769 AOP_TYPE (right) == AOP_CRY)
5771 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5772 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5776 /* subtract right from left if at the
5777 end the carry flag is set then we know that
5778 left is greater than right */
5779 size = max (AOP_SIZE (left), AOP_SIZE (right));
5781 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5782 if ((size == 1) && !sign
5783 && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5785 symbol *lbl = newiTempLabel (NULL);
5786 emitcode ("cjne", "%s,%s,!tlabel",
5787 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5788 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5790 emitcode ("", "!tlabeldef", lbl->key + 100);
5794 if (AOP_TYPE (right) == AOP_LIT)
5796 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5797 /* optimize if(x < 0) or if(x >= 0) */
5806 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5808 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5809 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5811 aopOp (result, ic, FALSE, FALSE);
5813 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5815 freeAsmop (result, NULL, ic, TRUE);
5816 genIfxJump (ifx, "acc.7");
5821 emitcode ("rlc", "a");
5823 goto release_freedLR;
5831 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5832 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5833 // emitcode (";", "genCmp #2");
5834 if (sign && (size == 0))
5836 // emitcode (";", "genCmp #3");
5837 emitcode ("xrl", "a,#!constbyte",0x80);
5838 if (AOP_TYPE (right) == AOP_LIT)
5840 unsigned long lit = (unsigned long)
5841 floatFromVal (AOP (right)->aopu.aop_lit);
5842 // emitcode (";", "genCmp #3.1");
5843 emitcode ("subb", "a,#!constbyte",
5844 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5848 // emitcode (";", "genCmp #3.2");
5850 MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5851 saveAccWarn = DEFAULT_ACC_WARNING;
5852 emitcode ("xrl", "b,#!constbyte",0x80);
5853 emitcode ("subb", "a,b");
5860 // emitcode (";", "genCmp #4");
5862 s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5863 saveAccWarn = DEFAULT_ACC_WARNING;
5865 emitcode ("subb", "a,%s", s);
5872 /* Don't need the left & right operands any more; do need the result. */
5873 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5874 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5876 aopOp (result, ic, FALSE, FALSE);
5880 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5886 /* if the result is used in the next
5887 ifx conditional branch then generate
5888 code a little differently */
5891 genIfxJump (ifx, "c");
5897 /* leave the result in acc */
5899 freeAsmop (result, NULL, ic, TRUE);
5902 /*-----------------------------------------------------------------*/
5903 /* genCmpGt :- greater than comparison */
5904 /*-----------------------------------------------------------------*/
5906 genCmpGt (iCode * ic, iCode * ifx)
5908 operand *left, *right;
5909 sym_link *letype, *retype;
5912 D (emitcode (";", "genCmpGt ");
5915 left = IC_LEFT (ic);
5916 right = IC_RIGHT (ic);
5918 letype = getSpec (operandType (left));
5919 retype = getSpec (operandType (right));
5920 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5922 /* assign the left & right amsops */
5925 genCmp (right, left, ic, ifx, sign);
5928 /*-----------------------------------------------------------------*/
5929 /* genCmpLt - less than comparisons */
5930 /*-----------------------------------------------------------------*/
5932 genCmpLt (iCode * ic, iCode * ifx)
5934 operand *left, *right;
5935 sym_link *letype, *retype;
5938 D (emitcode (";", "genCmpLt "););
5940 left = IC_LEFT (ic);
5941 right = IC_RIGHT (ic);
5943 letype = getSpec (operandType (left));
5944 retype = getSpec (operandType (right));
5945 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5947 /* assign the left & right amsops */
5950 genCmp (left, right, ic, ifx, sign);
5953 /*-----------------------------------------------------------------*/
5954 /* gencjneshort - compare and jump if not equal */
5955 /*-----------------------------------------------------------------*/
5957 gencjneshort (operand * left, operand * right, symbol * lbl)
5959 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5961 unsigned long lit = 0L;
5963 D (emitcode (";", "gencjneshort");
5966 /* if the left side is a literal or
5967 if the right is in a pointer register and left
5969 if ((AOP_TYPE (left) == AOP_LIT) ||
5970 (AOP_TYPE (left) == AOP_IMMD) ||
5971 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5978 if (AOP_TYPE (right) == AOP_LIT)
5979 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5981 if (opIsGptr (left) || opIsGptr (right))
5983 /* We are comparing a generic pointer to something.
5984 * Exclude the generic type byte from the comparison.
5987 D (emitcode (";", "cjneshort: generic ptr special case."););
5991 /* if the right side is a literal then anything goes */
5992 if (AOP_TYPE (right) == AOP_LIT &&
5993 AOP_TYPE (left) != AOP_DIR)
5997 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5998 emitcode ("cjne", "a,%s,!tlabel",
5999 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
6005 /* if the right side is in a register or in direct space or
6006 if the left is a pointer register & right is not */
6007 else if (AOP_TYPE (right) == AOP_REG ||
6008 AOP_TYPE (right) == AOP_DIR ||
6009 AOP_TYPE (right) == AOP_LIT ||
6010 AOP_TYPE (right) == AOP_IMMD ||
6011 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6012 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6016 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6017 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6018 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6019 emitcode ("jnz", "!tlabel", lbl->key + 100);
6021 emitcode ("cjne", "a,%s,!tlabel",
6022 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
6029 /* right is a pointer reg need both a & b */
6032 MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6033 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6034 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
6040 /*-----------------------------------------------------------------*/
6041 /* gencjne - compare and jump if not equal */
6042 /*-----------------------------------------------------------------*/
6044 gencjne (operand * left, operand * right, symbol * lbl)
6046 symbol *tlbl = newiTempLabel (NULL);
6048 D (emitcode (";", "gencjne");
6051 gencjneshort (left, right, lbl);
6053 emitcode ("mov", "a,%s", one);
6054 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
6055 emitcode ("", "!tlabeldef", lbl->key + 100);
6056 emitcode ("clr", "a");
6057 emitcode ("", "!tlabeldef", tlbl->key + 100);
6060 /*-----------------------------------------------------------------*/
6061 /* genCmpEq - generates code for equal to */
6062 /*-----------------------------------------------------------------*/
6064 genCmpEq (iCode * ic, iCode * ifx)
6066 operand *left, *right, *result;
6068 D (emitcode (";", "genCmpEq ");
6072 AOP_SET_LOCALS (ic);
6074 /* if literal, literal on the right or
6075 if the right is in a pointer register and left
6077 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6078 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6080 operand *t = IC_RIGHT (ic);
6081 IC_RIGHT (ic) = IC_LEFT (ic);
6085 if (ifx && /* !AOP_SIZE(result) */
6086 OP_SYMBOL (result) &&
6087 OP_SYMBOL (result)->regType == REG_CND)
6090 /* if they are both bit variables */
6091 if (AOP_TYPE (left) == AOP_CRY &&
6092 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6094 if (AOP_TYPE (right) == AOP_LIT)
6096 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6099 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6100 emitcode ("cpl", "c");
6104 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6108 emitcode ("clr", "c");
6110 /* AOP_TYPE(right) == AOP_CRY */
6114 symbol *lbl = newiTempLabel (NULL);
6115 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6116 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6117 emitcode ("cpl", "c");
6118 emitcode ("", "!tlabeldef", (lbl->key + 100));
6120 /* if true label then we jump if condition
6122 tlbl = newiTempLabel (NULL);
6125 emitcode ("jnc", "!tlabel", tlbl->key + 100);
6126 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6130 emitcode ("jc", "!tlabel", tlbl->key + 100);
6131 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6133 emitcode ("", "!tlabeldef", tlbl->key + 100);
6137 tlbl = newiTempLabel (NULL);
6138 gencjneshort (left, right, tlbl);
6141 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6142 emitcode ("", "!tlabeldef", tlbl->key + 100);
6146 symbol *lbl = newiTempLabel (NULL);
6147 emitcode ("sjmp", "!tlabel", lbl->key + 100);
6148 emitcode ("", "!tlabeldef", tlbl->key + 100);
6149 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6150 emitcode ("", "!tlabeldef", lbl->key + 100);
6153 /* mark the icode as generated */
6156 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6157 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6161 /* if they are both bit variables */
6162 if (AOP_TYPE (left) == AOP_CRY &&
6163 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6165 if (AOP_TYPE (right) == AOP_LIT)
6167 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6170 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6171 emitcode ("cpl", "c");
6175 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6179 emitcode ("clr", "c");
6181 /* AOP_TYPE(right) == AOP_CRY */
6185 symbol *lbl = newiTempLabel (NULL);
6186 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6187 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6188 emitcode ("cpl", "c");
6189 emitcode ("", "!tlabeldef", (lbl->key + 100));
6192 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6193 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6195 aopOp (result, ic, TRUE, FALSE);
6198 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6205 genIfxJump (ifx, "c");
6208 /* if the result is used in an arithmetic operation
6209 then put the result in place */
6214 gencjne (left, right, newiTempLabel (NULL));
6216 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6217 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6219 aopOp (result, ic, TRUE, FALSE);
6221 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6223 aopPut (AOP (result), "a", 0);
6228 genIfxJump (ifx, "a");
6231 /* if the result is used in an arithmetic operation
6232 then put the result in place */
6233 if (AOP_TYPE (result) != AOP_CRY)
6235 /* leave the result in acc */
6239 freeAsmop (result, NULL, ic, TRUE);
6242 /*-----------------------------------------------------------------*/
6243 /* ifxForOp - returns the icode containing the ifx for operand */
6244 /*-----------------------------------------------------------------*/
6246 ifxForOp (operand * op, iCode * ic)
6248 /* if true symbol then needs to be assigned */
6249 if (IS_TRUE_SYMOP (op))
6252 /* if this has register type condition and
6253 the next instruction is ifx with the same operand
6254 and live to of the operand is upto the ifx only then */
6256 ic->next->op == IFX &&
6257 IC_COND (ic->next)->key == op->key &&
6258 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6263 /*-----------------------------------------------------------------*/
6264 /* hasInc - operand is incremented before any other use */
6265 /*-----------------------------------------------------------------*/
6267 hasInc (operand *op, iCode *ic, int osize)
6269 sym_link *type = operandType(op);
6270 sym_link *retype = getSpec (type);
6271 iCode *lic = ic->next;
6274 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6275 if (!IS_SYMOP(op)) return NULL;
6277 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6278 if (IS_AGGREGATE(type->next)) return NULL;
6279 if (osize != (isize = getSize(type->next))) return NULL;
6282 /* if operand of the form op = op + <sizeof *op> */
6283 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6284 isOperandEqual(IC_RESULT(lic),op) &&
6285 isOperandLiteral(IC_RIGHT(lic)) &&
6286 operandLitValue(IC_RIGHT(lic)) == isize) {
6289 /* if the operand used or deffed */
6290 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
6293 /* if GOTO or IFX */
6294 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6300 /*-----------------------------------------------------------------*/
6301 /* genAndOp - for && operation */
6302 /*-----------------------------------------------------------------*/
6304 genAndOp (iCode * ic)
6306 operand *left, *right, *result;
6309 D (emitcode (";", "genAndOp "););
6311 /* note here that && operations that are in an
6312 if statement are taken away by backPatchLabels
6313 only those used in arthmetic operations remain */
6315 AOP_SET_LOCALS (ic);
6317 /* if both are bit variables */
6318 if (AOP_TYPE (left) == AOP_CRY &&
6319 AOP_TYPE (right) == AOP_CRY)
6321 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6322 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6323 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6324 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6326 aopOp (result,ic,FALSE, FALSE);
6331 tlbl = newiTempLabel (NULL);
6333 emitcode ("jz", "!tlabel", tlbl->key + 100);
6335 emitcode ("", "!tlabeldef", tlbl->key + 100);
6336 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6337 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6339 aopOp (result,ic,FALSE, FALSE);
6342 freeAsmop (result, NULL, ic, TRUE);
6346 /*-----------------------------------------------------------------*/
6347 /* genOrOp - for || operation */
6348 /*-----------------------------------------------------------------*/
6350 genOrOp (iCode * ic)
6352 operand *left, *right, *result;
6355 D (emitcode (";", "genOrOp "););
6357 /* note here that || operations that are in an
6358 if statement are taken away by backPatchLabels
6359 only those used in arthmetic operations remain */
6361 AOP_SET_LOCALS (ic);
6363 /* if both are bit variables */
6364 if (AOP_TYPE (left) == AOP_CRY &&
6365 AOP_TYPE (right) == AOP_CRY)
6367 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6368 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6369 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6370 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6372 aopOp (result,ic,FALSE, FALSE);
6378 tlbl = newiTempLabel (NULL);
6380 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6382 emitcode ("", "!tlabeldef", tlbl->key + 100);
6383 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6384 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6386 aopOp (result,ic,FALSE, FALSE);
6391 freeAsmop (result, NULL, ic, TRUE);
6394 /*-----------------------------------------------------------------*/
6395 /* isLiteralBit - test if lit == 2^n */
6396 /*-----------------------------------------------------------------*/
6398 isLiteralBit (unsigned long lit)
6400 unsigned long pw[32] =
6401 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6402 0x100L, 0x200L, 0x400L, 0x800L,
6403 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6404 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6405 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6406 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6407 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6410 for (idx = 0; idx < 32; idx++)
6416 /*-----------------------------------------------------------------*/
6417 /* continueIfTrue - */
6418 /*-----------------------------------------------------------------*/
6420 continueIfTrue (iCode * ic)
6423 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6427 /*-----------------------------------------------------------------*/
6429 /*-----------------------------------------------------------------*/
6431 jumpIfTrue (iCode * ic)
6434 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6438 /*-----------------------------------------------------------------*/
6439 /* jmpTrueOrFalse - */
6440 /*-----------------------------------------------------------------*/
6442 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6444 // ugly but optimized by peephole
6447 symbol *nlbl = newiTempLabel (NULL);
6448 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6449 emitcode ("", "!tlabeldef", tlbl->key + 100);
6450 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6451 emitcode ("", "!tlabeldef", nlbl->key + 100);
6455 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6456 emitcode ("", "!tlabeldef", tlbl->key + 100);
6461 // Generate code to perform a bit-wise logic operation
6462 // on two operands in far space (assumed to already have been
6463 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6464 // in far space. This requires pushing the result on the stack
6465 // then popping it into the result.
6467 genFarFarLogicOp(iCode *ic, char *logicOp)
6469 int size, resultSize, compSize;
6473 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6474 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
6475 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6477 _startLazyDPSEvaluation();
6478 for (size = compSize; (size--); offset++)
6480 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6481 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6482 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6484 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6485 emitcode ("push", "acc");
6487 _endLazyDPSEvaluation();
6489 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6490 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6491 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6493 resultSize = AOP_SIZE(IC_RESULT(ic));
6495 ADJUST_PUSHED_RESULT(compSize, resultSize);
6497 _startLazyDPSEvaluation();
6500 emitcode ("pop", "acc");
6501 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6503 _endLazyDPSEvaluation();
6504 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6508 /*-----------------------------------------------------------------*/
6509 /* genAnd - code for and */
6510 /*-----------------------------------------------------------------*/
6512 genAnd (iCode * ic, iCode * ifx)
6514 operand *left, *right, *result;
6515 int size, offset = 0;
6516 unsigned long lit = 0L;
6521 D (emitcode (";", "genAnd "););
6523 AOP_OP_3_NOFATAL (ic, pushResult);
6524 AOP_SET_LOCALS (ic);
6528 genFarFarLogicOp(ic, "anl");
6533 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6535 AOP_TYPE (left), AOP_TYPE (right));
6536 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6538 AOP_SIZE (left), AOP_SIZE (right));
6541 /* if left is a literal & right is not then exchange them */
6542 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6543 #ifdef LOGIC_OPS_BROKEN
6544 || AOP_NEEDSACC (left)
6548 operand *tmp = right;
6553 /* if result = right then exchange them */
6554 if (sameRegs (AOP (result), AOP (right)))
6556 operand *tmp = right;
6561 /* if right is bit then exchange them */
6562 if (AOP_TYPE (right) == AOP_CRY &&
6563 AOP_TYPE (left) != AOP_CRY)
6565 operand *tmp = right;
6569 if (AOP_TYPE (right) == AOP_LIT)
6570 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6572 size = AOP_SIZE (result);
6575 // result = bit & yy;
6576 if (AOP_TYPE (left) == AOP_CRY)
6578 // c = bit & literal;
6579 if (AOP_TYPE (right) == AOP_LIT)
6583 if (size && sameRegs (AOP (result), AOP (left)))
6586 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6591 if (size && (AOP_TYPE (result) == AOP_CRY))
6593 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6596 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6601 emitcode ("clr", "c");
6606 if (AOP_TYPE (right) == AOP_CRY)
6609 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6610 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6615 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6617 emitcode ("rrc", "a");
6618 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6626 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6627 genIfxJump (ifx, "c");
6631 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6632 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6633 if ((AOP_TYPE (right) == AOP_LIT) &&
6634 (AOP_TYPE (result) == AOP_CRY) &&
6635 (AOP_TYPE (left) != AOP_CRY))
6637 int posbit = isLiteralBit (lit);
6642 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6645 emitcode ("mov", "c,acc.%d", posbit & 0x07);
6651 SNPRINTF (buff, sizeof(buff),
6652 "acc.%d", posbit & 0x07);
6653 genIfxJump (ifx, buff);
6657 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6664 symbol *tlbl = newiTempLabel (NULL);
6665 int sizel = AOP_SIZE (left);
6667 emitcode ("setb", "c");
6670 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6672 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6674 if ((posbit = isLiteralBit (bytelit)) != 0)
6675 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6678 if (bytelit != 0x0FFL)
6679 emitcode ("anl", "a,%s",
6680 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6681 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6686 // bit = left & literal
6689 emitcode ("clr", "c");
6690 emitcode ("", "!tlabeldef", tlbl->key + 100);
6692 // if(left & literal)
6696 jmpTrueOrFalse (ifx, tlbl);
6698 emitcode ("", "!tlabeldef", tlbl->key + 100);
6706 /* if left is same as result */
6707 if (sameRegs (AOP (result), AOP (left)))
6709 for (; size--; offset++)
6711 if (AOP_TYPE (right) == AOP_LIT)
6713 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6715 else if (bytelit == 0)
6716 aopPut (AOP (result), zero, offset);
6717 else if (IS_AOP_PREG (result))
6719 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6720 emitcode ("anl", "a,%s",
6721 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6722 aopPut (AOP (result), "a", offset);
6725 emitcode ("anl", "%s,%s",
6726 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6727 aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6731 if (AOP_TYPE (left) == AOP_ACC)
6732 emitcode ("anl", "a,%s",
6733 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6736 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6737 if (IS_AOP_PREG (result))
6739 emitcode ("anl", "a,%s",
6740 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6741 aopPut (AOP (result), "a", offset);
6744 emitcode ("anl", "%s,a",
6745 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6752 // left & result in different registers
6753 if (AOP_TYPE (result) == AOP_CRY)
6756 // if(size), result in bit
6757 // if(!size && ifx), conditional oper: if(left & right)
6758 symbol *tlbl = newiTempLabel (NULL);
6759 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6761 emitcode ("setb", "c");
6764 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6765 emitcode ("anl", "a,%s",
6766 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6768 if (AOP_TYPE(left)==AOP_ACC) {
6769 emitcode("mov", "b,a");
6770 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6771 emitcode("anl", "a,b");
6773 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6774 emitcode ("anl", "a,%s",
6775 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6778 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6784 emitcode ("", "!tlabeldef", tlbl->key + 100);
6788 jmpTrueOrFalse (ifx, tlbl);
6790 emitcode ("", "!tlabeldef", tlbl->key + 100);
6794 for (; (size--); offset++)
6797 // result = left & right
6798 if (AOP_TYPE (right) == AOP_LIT)
6800 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6802 aopPut (AOP (result),
6803 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6807 else if (bytelit == 0)
6809 aopPut (AOP (result), zero, offset);
6812 D (emitcode (";", "better literal AND."););
6813 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6814 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6815 FALSE, FALSE, DP2_RESULT_REG));
6820 // faster than result <- left, anl result,right
6821 // and better if result is SFR
6822 if (AOP_TYPE (left) == AOP_ACC)
6824 emitcode ("anl", "a,%s",
6825 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6829 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6830 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6832 emitcode("mov", "b,a");
6836 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6837 emitcode ("anl", "a,%s", rOp);
6840 aopPut (AOP (result), "a", offset);
6846 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6847 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6848 freeAsmop (result, NULL, ic, TRUE);
6852 /*-----------------------------------------------------------------*/
6853 /* genOr - code for or */
6854 /*-----------------------------------------------------------------*/
6856 genOr (iCode * ic, iCode * ifx)
6858 operand *left, *right, *result;
6859 int size, offset = 0;
6860 unsigned long lit = 0L;
6863 D (emitcode (";", "genOr "););
6865 AOP_OP_3_NOFATAL (ic, pushResult);
6866 AOP_SET_LOCALS (ic);
6870 genFarFarLogicOp(ic, "orl");
6876 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6878 AOP_TYPE (left), AOP_TYPE (right));
6879 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6881 AOP_SIZE (left), AOP_SIZE (right));
6884 /* if left is a literal & right is not then exchange them */
6885 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6886 #ifdef LOGIC_OPS_BROKEN
6887 || AOP_NEEDSACC (left) // I think this is a net loss now.
6891 operand *tmp = right;
6896 /* if result = right then exchange them */
6897 if (sameRegs (AOP (result), AOP (right)))
6899 operand *tmp = right;
6904 /* if right is bit then exchange them */
6905 if (AOP_TYPE (right) == AOP_CRY &&
6906 AOP_TYPE (left) != AOP_CRY)
6908 operand *tmp = right;
6912 if (AOP_TYPE (right) == AOP_LIT)
6913 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6915 size = AOP_SIZE (result);
6919 if (AOP_TYPE (left) == AOP_CRY)
6921 if (AOP_TYPE (right) == AOP_LIT)
6923 // c = bit & literal;
6926 // lit != 0 => result = 1
6927 if (AOP_TYPE (result) == AOP_CRY)
6930 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6932 continueIfTrue (ifx);
6935 emitcode ("setb", "c");
6939 // lit == 0 => result = left
6940 if (size && sameRegs (AOP (result), AOP (left)))
6942 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6947 if (AOP_TYPE (right) == AOP_CRY)
6950 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6951 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6956 symbol *tlbl = newiTempLabel (NULL);
6957 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6958 emitcode ("setb", "c");
6959 emitcode ("jb", "%s,!tlabel",
6960 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6962 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6963 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6965 jmpTrueOrFalse (ifx, tlbl);
6971 emitcode ("", "!tlabeldef", tlbl->key + 100);
6980 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6981 genIfxJump (ifx, "c");
6985 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6986 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6987 if ((AOP_TYPE (right) == AOP_LIT) &&
6988 (AOP_TYPE (result) == AOP_CRY) &&
6989 (AOP_TYPE (left) != AOP_CRY))
6995 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6997 continueIfTrue (ifx);
7002 // lit = 0, result = boolean(left)
7004 emitcode ("setb", "c");
7008 symbol *tlbl = newiTempLabel (NULL);
7009 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7011 emitcode ("", "!tlabeldef", tlbl->key + 100);
7015 genIfxJump (ifx, "a");
7023 /* if left is same as result */
7024 if (sameRegs (AOP (result), AOP (left)))
7026 for (; size--; offset++)
7028 if (AOP_TYPE (right) == AOP_LIT)
7030 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7036 if (IS_AOP_PREG (left))
7038 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7039 emitcode ("orl", "a,%s",
7040 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7041 aopPut (AOP (result), "a", offset);
7045 emitcode ("orl", "%s,%s",
7046 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7047 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7053 if (AOP_TYPE (left) == AOP_ACC)
7055 emitcode ("orl", "a,%s",
7056 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7060 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7061 if (IS_AOP_PREG (left))
7063 emitcode ("orl", "a,%s",
7064 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7065 aopPut (AOP (result), "a", offset);
7069 emitcode ("orl", "%s,a",
7070 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7078 // left & result in different registers
7079 if (AOP_TYPE (result) == AOP_CRY)
7082 // if(size), result in bit
7083 // if(!size && ifx), conditional oper: if(left | right)
7084 symbol *tlbl = newiTempLabel (NULL);
7085 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7087 emitcode ("setb", "c");
7090 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7091 emitcode ("orl", "a,%s",
7092 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7094 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7095 emitcode ("orl", "a,%s",
7096 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
7098 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7104 emitcode ("", "!tlabeldef", tlbl->key + 100);
7108 jmpTrueOrFalse (ifx, tlbl);
7110 emitcode ("", "!tlabeldef", tlbl->key + 100);
7114 _startLazyDPSEvaluation();
7115 for (; (size--); offset++)
7118 // result = left & right
7119 if (AOP_TYPE (right) == AOP_LIT)
7121 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7123 aopPut (AOP (result),
7124 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7128 D (emitcode (";", "better literal OR."););
7129 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7130 emitcode ("orl", "a, %s",
7131 aopGet (AOP (right), offset,
7132 FALSE, FALSE, DP2_RESULT_REG));
7137 // faster than result <- left, anl result,right
7138 // and better if result is SFR
7139 if (AOP_TYPE (left) == AOP_ACC)
7141 emitcode ("orl", "a,%s",
7142 aopGet (AOP (right), offset,
7143 FALSE, FALSE, DP2_RESULT_REG));
7147 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7149 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7151 emitcode("mov", "b,a");
7155 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7156 emitcode ("orl", "a,%s", rOp);
7159 aopPut (AOP (result), "a", offset);
7161 _endLazyDPSEvaluation();
7166 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7167 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7168 freeAsmop (result, NULL, ic, TRUE);
7171 /*-----------------------------------------------------------------*/
7172 /* genXor - code for xclusive or */
7173 /*-----------------------------------------------------------------*/
7175 genXor (iCode * ic, iCode * ifx)
7177 operand *left, *right, *result;
7178 int size, offset = 0;
7179 unsigned long lit = 0L;
7182 D (emitcode (";", "genXor "););
7184 AOP_OP_3_NOFATAL (ic, pushResult);
7185 AOP_SET_LOCALS (ic);
7189 genFarFarLogicOp(ic, "xrl");
7194 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7196 AOP_TYPE (left), AOP_TYPE (right));
7197 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7199 AOP_SIZE (left), AOP_SIZE (right));
7202 /* if left is a literal & right is not ||
7203 if left needs acc & right does not */
7204 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7205 #ifdef LOGIC_OPS_BROKEN
7206 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
7210 operand *tmp = right;
7215 /* if result = right then exchange them */
7216 if (sameRegs (AOP (result), AOP (right)))
7218 operand *tmp = right;
7223 /* if right is bit then exchange them */
7224 if (AOP_TYPE (right) == AOP_CRY &&
7225 AOP_TYPE (left) != AOP_CRY)
7227 operand *tmp = right;
7231 if (AOP_TYPE (right) == AOP_LIT)
7232 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7234 size = AOP_SIZE (result);
7238 if (AOP_TYPE (left) == AOP_CRY)
7240 if (AOP_TYPE (right) == AOP_LIT)
7242 // c = bit & literal;
7245 // lit>>1 != 0 => result = 1
7246 if (AOP_TYPE (result) == AOP_CRY)
7249 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7251 continueIfTrue (ifx);
7254 emitcode ("setb", "c");
7261 // lit == 0, result = left
7262 if (size && sameRegs (AOP (result), AOP (left)))
7264 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7268 // lit == 1, result = not(left)
7269 if (size && sameRegs (AOP (result), AOP (left)))
7271 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7276 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7277 emitcode ("cpl", "c");
7286 symbol *tlbl = newiTempLabel (NULL);
7287 if (AOP_TYPE (right) == AOP_CRY)
7290 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7294 int sizer = AOP_SIZE (right);
7296 // if val>>1 != 0, result = 1
7297 emitcode ("setb", "c");
7300 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
7302 // test the msb of the lsb
7303 emitcode ("anl", "a,#!constbyte",0xfe);
7304 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7308 emitcode ("rrc", "a");
7310 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7311 emitcode ("cpl", "c");
7312 emitcode ("", "!tlabeldef", (tlbl->key + 100));
7319 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7320 genIfxJump (ifx, "c");
7324 if (sameRegs (AOP (result), AOP (left)))
7326 /* if left is same as result */
7327 for (; size--; offset++)
7329 if (AOP_TYPE (right) == AOP_LIT)
7331 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7333 else if (IS_AOP_PREG (left))
7335 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7336 emitcode ("xrl", "a,%s",
7337 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7338 aopPut (AOP (result), "a", offset);
7341 emitcode ("xrl", "%s,%s",
7342 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7343 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7347 if (AOP_TYPE (left) == AOP_ACC)
7348 emitcode ("xrl", "a,%s",
7349 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7352 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7353 if (IS_AOP_PREG (left))
7355 emitcode ("xrl", "a,%s",
7356 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7357 aopPut (AOP (result), "a", offset);
7360 emitcode ("xrl", "%s,a",
7361 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7368 // left & result in different registers
7369 if (AOP_TYPE (result) == AOP_CRY)
7372 // if(size), result in bit
7373 // if(!size && ifx), conditional oper: if(left ^ right)
7374 symbol *tlbl = newiTempLabel (NULL);
7375 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7378 emitcode ("setb", "c");
7381 if ((AOP_TYPE (right) == AOP_LIT) &&
7382 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7384 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7388 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7389 emitcode ("xrl", "a,%s",
7390 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7392 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7393 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7395 emitcode("mov", "b,a");
7399 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7400 emitcode ("xrl", "a,%s", rOp);
7403 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7409 emitcode ("", "!tlabeldef", tlbl->key + 100);
7413 jmpTrueOrFalse (ifx, tlbl);
7417 for (; (size--); offset++)
7420 // result = left & right
7421 if (AOP_TYPE (right) == AOP_LIT)
7423 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7425 aopPut (AOP (result),
7426 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7430 D (emitcode (";", "better literal XOR."););
7431 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7432 emitcode ("xrl", "a, %s",
7433 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7437 // faster than result <- left, anl result,right
7438 // and better if result is SFR
7439 if (AOP_TYPE (left) == AOP_ACC)
7441 emitcode ("xrl", "a,%s",
7442 aopGet (AOP (right), offset,
7443 FALSE, FALSE, DP2_RESULT_REG));
7447 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7448 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7450 emitcode("mov", "b,a");
7454 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7455 emitcode ("xrl", "a,%s", rOp);
7458 aopPut (AOP (result), "a", offset);
7465 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7466 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7467 freeAsmop (result, NULL, ic, TRUE);
7470 /*-----------------------------------------------------------------*/
7471 /* genInline - write the inline code out */
7472 /*-----------------------------------------------------------------*/
7474 genInline (iCode * ic)
7476 char *buffer, *bp, *bp1;
7478 D (emitcode (";", "genInline "); );
7480 _G.inLine += (!options.asmpeep);
7482 buffer = Safe_strdup(IC_INLINE(ic));
7486 /* emit each line as a code */
7511 /* emitcode("",buffer); */
7512 _G.inLine -= (!options.asmpeep);
7515 /*-----------------------------------------------------------------*/
7516 /* genRRC - rotate right with carry */
7517 /*-----------------------------------------------------------------*/
7521 operand *left, *result;
7524 D (emitcode (";", "genRRC "););
7526 /* rotate right with carry */
7527 left = IC_LEFT (ic);
7528 result = IC_RESULT (ic);
7529 aopOp (left, ic, FALSE, FALSE);
7530 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7532 /* move it to the result */
7533 size = AOP_SIZE (result);
7537 _startLazyDPSEvaluation ();
7540 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7541 emitcode ("rrc", "a");
7542 if (AOP_SIZE (result) > 1)
7543 aopPut (AOP (result), "a", offset--);
7545 _endLazyDPSEvaluation ();
7547 /* now we need to put the carry into the
7548 highest order byte of the result */
7549 if (AOP_SIZE (result) > 1)
7551 MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7553 emitcode ("mov", "acc.7,c");
7554 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7555 freeAsmop (left, NULL, ic, TRUE);
7556 freeAsmop (result, NULL, ic, TRUE);
7559 /*-----------------------------------------------------------------*/
7560 /* genRLC - generate code for rotate left with carry */
7561 /*-----------------------------------------------------------------*/
7565 operand *left, *result;
7569 D (emitcode (";", "genRLC "););
7571 /* rotate right with carry */
7572 left = IC_LEFT (ic);
7573 result = IC_RESULT (ic);
7574 aopOp (left, ic, FALSE, FALSE);
7575 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7577 /* move it to the result */
7578 size = AOP_SIZE (result);
7582 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7584 emitcode ("add", "a,acc");
7585 if (AOP_SIZE (result) > 1)
7587 aopPut (AOP (result), "a", offset++);
7590 _startLazyDPSEvaluation ();
7593 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7595 emitcode ("rlc", "a");
7596 if (AOP_SIZE (result) > 1)
7597 aopPut (AOP (result), "a", offset++);
7599 _endLazyDPSEvaluation ();
7601 /* now we need to put the carry into the
7602 highest order byte of the result */
7603 if (AOP_SIZE (result) > 1)
7605 l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7608 emitcode ("mov", "acc.0,c");
7609 aopPut (AOP (result), "a", 0);
7610 freeAsmop (left, NULL, ic, TRUE);
7611 freeAsmop (result, NULL, ic, TRUE);
7614 /*-----------------------------------------------------------------*/
7615 /* genGetHbit - generates code get highest order bit */
7616 /*-----------------------------------------------------------------*/
7618 genGetHbit (iCode * ic)
7620 operand *left, *result;
7621 left = IC_LEFT (ic);
7622 result = IC_RESULT (ic);
7623 aopOp (left, ic, FALSE, FALSE);
7624 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7626 D (emitcode (";", "genGetHbit "););
7628 /* get the highest order byte into a */
7629 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7630 if (AOP_TYPE (result) == AOP_CRY)
7632 emitcode ("rlc", "a");
7637 emitcode ("rl", "a");
7638 emitcode ("anl", "a,#1");
7643 freeAsmop (left, NULL, ic, TRUE);
7644 freeAsmop (result, NULL, ic, TRUE);
7647 /*-----------------------------------------------------------------*/
7648 /* genSwap - generates code to swap nibbles or bytes */
7649 /*-----------------------------------------------------------------*/
7651 genSwap (iCode * ic)
7653 operand *left, *result;
7655 D(emitcode ("; genSwap",""));
7657 left = IC_LEFT (ic);
7658 result = IC_RESULT (ic);
7659 aopOp (left, ic, FALSE, FALSE);
7660 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7662 _startLazyDPSEvaluation ();
7663 switch (AOP_SIZE (left))
7665 case 1: /* swap nibbles in byte */
7666 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7667 emitcode ("swap", "a");
7668 aopPut (AOP (result), "a", 0);
7670 case 2: /* swap bytes in word */
7671 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7673 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7674 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7675 aopPut (AOP (result), "a", 1);
7677 else if (operandsEqu (left, result))
7680 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7681 if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
7683 emitcode ("mov", "b,a");
7687 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7688 aopPut (AOP (result), reg, 1);
7693 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7694 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE, NULL), 1);
7698 wassertl(FALSE, "unsupported SWAP operand size");
7700 _endLazyDPSEvaluation ();
7702 freeAsmop (left, NULL, ic, TRUE);
7703 freeAsmop (result, NULL, ic, TRUE);
7706 /*-----------------------------------------------------------------*/
7707 /* AccRol - rotate left accumulator by known count */
7708 /*-----------------------------------------------------------------*/
7710 AccRol (int shCount)
7712 shCount &= 0x0007; // shCount : 0..7
7719 emitcode ("rl", "a");
7722 emitcode ("rl", "a");
7723 emitcode ("rl", "a");
7726 emitcode ("swap", "a");
7727 emitcode ("rr", "a");
7730 emitcode ("swap", "a");
7733 emitcode ("swap", "a");
7734 emitcode ("rl", "a");
7737 emitcode ("rr", "a");
7738 emitcode ("rr", "a");
7741 emitcode ("rr", "a");
7746 /*-----------------------------------------------------------------*/
7747 /* AccLsh - left shift accumulator by known count */
7748 /*-----------------------------------------------------------------*/
7750 AccLsh (int shCount)
7755 emitcode ("add", "a,acc");
7756 else if (shCount == 2)
7758 emitcode ("add", "a,acc");
7759 emitcode ("add", "a,acc");
7763 /* rotate left accumulator */
7765 /* and kill the lower order bits */
7766 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7771 /*-----------------------------------------------------------------*/
7772 /* AccRsh - right shift accumulator by known count */
7773 /*-----------------------------------------------------------------*/
7775 AccRsh (int shCount)
7782 emitcode ("rrc", "a");
7786 /* rotate right accumulator */
7787 AccRol (8 - shCount);
7788 /* and kill the higher order bits */
7789 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7794 #ifdef BETTER_LITERAL_SHIFT
7795 /*-----------------------------------------------------------------*/
7796 /* AccSRsh - signed right shift accumulator by known count */
7797 /*-----------------------------------------------------------------*/
7799 AccSRsh (int shCount)
7806 emitcode ("mov", "c,acc.7");
7807 emitcode ("rrc", "a");
7809 else if (shCount == 2)
7811 emitcode ("mov", "c,acc.7");
7812 emitcode ("rrc", "a");
7813 emitcode ("mov", "c,acc.7");
7814 emitcode ("rrc", "a");
7818 tlbl = newiTempLabel (NULL);
7819 /* rotate right accumulator */
7820 AccRol (8 - shCount);
7821 /* and kill the higher order bits */
7822 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7823 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7824 emitcode ("orl", "a,#!constbyte",
7825 (unsigned char) ~SRMask[shCount]);
7826 emitcode ("", "!tlabeldef", tlbl->key + 100);
7832 #ifdef BETTER_LITERAL_SHIFT
7833 /*-----------------------------------------------------------------*/
7834 /* shiftR1Left2Result - shift right one byte from left to result */
7835 /*-----------------------------------------------------------------*/
7837 shiftR1Left2Result (operand * left, int offl,
7838 operand * result, int offr,
7839 int shCount, int sign)
7841 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7842 /* shift right accumulator */
7847 aopPut (AOP (result), "a", offr);
7851 #ifdef BETTER_LITERAL_SHIFT
7852 /*-----------------------------------------------------------------*/
7853 /* shiftL1Left2Result - shift left one byte from left to result */
7854 /*-----------------------------------------------------------------*/
7856 shiftL1Left2Result (operand * left, int offl,
7857 operand * result, int offr, int shCount)
7859 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7860 /* shift left accumulator */
7862 aopPut (AOP (result), "a", offr);
7866 #ifdef BETTER_LITERAL_SHIFT
7867 /*-----------------------------------------------------------------*/
7868 /* movLeft2Result - move byte from left to result */
7869 /*-----------------------------------------------------------------*/
7871 movLeft2Result (operand * left, int offl,
7872 operand * result, int offr, int sign)
7875 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7877 l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7879 if (*l == '@' && (IS_AOP_PREG (result)))
7881 emitcode ("mov", "a,%s", l);
7882 aopPut (AOP (result), "a", offr);
7888 aopPut (AOP (result), l, offr);
7892 /* MSB sign in acc.7 ! */
7893 if (getDataSize (left) == offl + 1)
7895 emitcode ("mov", "a,%s", l);
7896 aopPut (AOP (result), "a", offr);
7904 #ifdef BETTER_LITERAL_SHIFT
7905 /*-----------------------------------------------------------------*/
7906 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7907 /*-----------------------------------------------------------------*/
7911 emitcode ("rrc", "a");
7912 emitcode ("xch", "a,%s", x);
7913 emitcode ("rrc", "a");
7914 emitcode ("xch", "a,%s", x);
7918 #ifdef BETTER_LITERAL_SHIFT
7920 /*-----------------------------------------------------------------*/
7921 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7922 /*-----------------------------------------------------------------*/
7926 emitcode ("xch", "a,%s", x);
7927 emitcode ("rlc", "a");
7928 emitcode ("xch", "a,%s", x);
7929 emitcode ("rlc", "a");
7933 #ifdef BETTER_LITERAL_SHIFT
7934 /*-----------------------------------------------------------------*/
7935 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7936 /*-----------------------------------------------------------------*/
7940 emitcode ("xch", "a,%s", x);
7941 emitcode ("add", "a,acc");
7942 emitcode ("xch", "a,%s", x);
7943 emitcode ("rlc", "a");
7947 #ifdef BETTER_LITERAL_SHIFT
7948 /*-----------------------------------------------------------------*/
7949 /* AccAXLsh - left shift a:x by known count (0..7) */
7950 /*-----------------------------------------------------------------*/
7952 AccAXLsh (char *x, int shCount)
7967 case 5: // AAAAABBB:CCCCCDDD
7969 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7971 emitcode ("anl", "a,#!constbyte",
7972 SLMask[shCount]); // BBB00000:CCCCCDDD
7974 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7976 AccRol (shCount); // DDDCCCCC:BBB00000
7978 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7980 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7982 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7984 emitcode ("anl", "a,#!constbyte",
7985 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7987 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7989 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7992 case 6: // AAAAAABB:CCCCCCDD
7993 emitcode ("anl", "a,#!constbyte",
7994 SRMask[shCount]); // 000000BB:CCCCCCDD
7995 emitcode ("mov", "c,acc.0"); // c = B
7996 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7998 AccAXRrl1 (x); // BCCCCCCD:D000000B
7999 AccAXRrl1 (x); // BBCCCCCC:DD000000
8001 emitcode("rrc","a");
8002 emitcode("xch","a,%s", x);
8003 emitcode("rrc","a");
8004 emitcode("mov","c,acc.0"); //<< get correct bit
8005 emitcode("xch","a,%s", x);
8007 emitcode("rrc","a");
8008 emitcode("xch","a,%s", x);
8009 emitcode("rrc","a");
8010 emitcode("xch","a,%s", x);
8013 case 7: // a:x <<= 7
8015 emitcode ("anl", "a,#!constbyte",
8016 SRMask[shCount]); // 0000000B:CCCCCCCD
8018 emitcode ("mov", "c,acc.0"); // c = B
8020 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8022 AccAXRrl1 (x); // BCCCCCCC:D0000000
8031 #ifdef BETTER_LITERAL_SHIFT
8033 /*-----------------------------------------------------------------*/
8034 /* AccAXRsh - right shift a:x known count (0..7) */
8035 /*-----------------------------------------------------------------*/
8037 AccAXRsh (char *x, int shCount)
8045 AccAXRrl1 (x); // 0->a:x
8050 AccAXRrl1 (x); // 0->a:x
8053 AccAXRrl1 (x); // 0->a:x
8058 case 5: // AAAAABBB:CCCCCDDD = a:x
8060 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8062 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8064 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8066 emitcode ("anl", "a,#!constbyte",
8067 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8069 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8071 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8073 emitcode ("anl", "a,#!constbyte",
8074 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8076 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8078 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8080 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8083 case 6: // AABBBBBB:CCDDDDDD
8085 emitcode ("mov", "c,acc.7");
8086 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8088 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8090 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8092 emitcode ("anl", "a,#!constbyte",
8093 SRMask[shCount]); // 000000AA:BBBBBBCC
8096 case 7: // ABBBBBBB:CDDDDDDD
8098 emitcode ("mov", "c,acc.7"); // c = A
8100 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8102 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8104 emitcode ("anl", "a,#!constbyte",
8105 SRMask[shCount]); // 0000000A:BBBBBBBC
8114 #ifdef BETTER_LITERAL_SHIFT
8115 /*-----------------------------------------------------------------*/
8116 /* AccAXRshS - right shift signed a:x known count (0..7) */
8117 /*-----------------------------------------------------------------*/
8119 AccAXRshS (char *x, int shCount)
8127 emitcode ("mov", "c,acc.7");
8128 AccAXRrl1 (x); // s->a:x
8132 emitcode ("mov", "c,acc.7");
8133 AccAXRrl1 (x); // s->a:x
8135 emitcode ("mov", "c,acc.7");
8136 AccAXRrl1 (x); // s->a:x
8141 case 5: // AAAAABBB:CCCCCDDD = a:x
8143 tlbl = newiTempLabel (NULL);
8144 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8146 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8148 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8150 emitcode ("anl", "a,#!constbyte",
8151 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8153 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8155 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8157 emitcode ("anl", "a,#!constbyte",
8158 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8160 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8162 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8164 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8166 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8167 emitcode ("orl", "a,#!constbyte",
8168 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8170 emitcode ("", "!tlabeldef", tlbl->key + 100);
8171 break; // SSSSAAAA:BBBCCCCC
8173 case 6: // AABBBBBB:CCDDDDDD
8175 tlbl = newiTempLabel (NULL);
8176 emitcode ("mov", "c,acc.7");
8177 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8179 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8181 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8183 emitcode ("anl", "a,#!constbyte",
8184 SRMask[shCount]); // 000000AA:BBBBBBCC
8186 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8187 emitcode ("orl", "a,#!constbyte",
8188 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8190 emitcode ("", "!tlabeldef", tlbl->key + 100);
8192 case 7: // ABBBBBBB:CDDDDDDD
8194 tlbl = newiTempLabel (NULL);
8195 emitcode ("mov", "c,acc.7"); // c = A
8197 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8199 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8201 emitcode ("anl", "a,#!constbyte",
8202 SRMask[shCount]); // 0000000A:BBBBBBBC
8204 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8205 emitcode ("orl", "a,#!constbyte",
8206 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8208 emitcode ("", "!tlabeldef", tlbl->key + 100);
8216 #ifdef BETTER_LITERAL_SHIFT
8218 _loadLeftIntoAx(char **lsb,
8224 // Get the initial value from left into a pair of registers.
8225 // MSB must be in A, LSB can be any register.
8227 // If the result is held in registers, it is an optimization
8228 // if the LSB can be held in the register which will hold the,
8229 // result LSB since this saves us from having to copy it into
8230 // the result following AccAXLsh.
8232 // If the result is addressed indirectly, this is not a gain.
8233 if (AOP_NEEDSACC(result))
8237 _startLazyDPSEvaluation();
8238 if (AOP_TYPE(left) == AOP_DPTR2)
8241 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
8242 // get LSB in DP2_RESULT_REG.
8243 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
8244 assert(!strcmp(leftByte, DP2_RESULT_REG));
8248 // get LSB into DP2_RESULT_REG
8249 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
8250 if (strcmp(leftByte, DP2_RESULT_REG))
8253 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
8256 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
8257 assert(strcmp(leftByte, DP2_RESULT_REG));
8260 _endLazyDPSEvaluation();
8261 *lsb = DP2_RESULT_REG;
8265 if (sameRegs (AOP (result), AOP (left)) &&
8266 ((offl + MSB16) == offr))
8268 /* don't crash result[offr] */
8269 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
8270 emitcode ("xch", "a,%s",
8271 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
8275 movLeft2Result (left, offl, result, offr, 0);
8276 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
8278 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
8279 assert(strcmp(*lsb,"a"));
8284 _storeAxResults(char *lsb,
8288 _startLazyDPSEvaluation();
8289 if (AOP_NEEDSACC(result))
8291 /* We have to explicitly update the result LSB.
8293 emitcode("xch","a,%s", lsb);
8294 aopPut(AOP(result), "a", offr);
8295 emitcode("mov","a,%s", lsb);
8297 if (getDataSize (result) > 1)
8299 aopPut (AOP (result), "a", offr + MSB16);
8301 _endLazyDPSEvaluation();
8304 /*-----------------------------------------------------------------*/
8305 /* shiftL2Left2Result - shift left two bytes from left to result */
8306 /*-----------------------------------------------------------------*/
8308 shiftL2Left2Result (operand * left, int offl,
8309 operand * result, int offr, int shCount)
8313 _loadLeftIntoAx(&lsb, left, result, offl, offr);
8315 AccAXLsh (lsb, shCount);
8317 _storeAxResults(lsb, result, offr);
8321 #ifdef BETTER_LITERAL_SHIFT
8322 /*-----------------------------------------------------------------*/
8323 /* shiftR2Left2Result - shift right two bytes from left to result */
8324 /*-----------------------------------------------------------------*/
8326 shiftR2Left2Result (operand * left, int offl,
8327 operand * result, int offr,
8328 int shCount, int sign)
8332 _loadLeftIntoAx(&lsb, left, result, offl, offr);
8334 /* a:x >> shCount (x = lsb(result)) */
8337 AccAXRshS(lsb, shCount);
8341 AccAXRsh(lsb, shCount);
8344 _storeAxResults(lsb, result, offr);
8348 /*-----------------------------------------------------------------*/
8349 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8350 /*-----------------------------------------------------------------*/
8352 shiftLLeftOrResult (operand * left, int offl,
8353 operand * result, int offr, int shCount)
8355 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8356 /* shift left accumulator */
8358 /* or with result */
8359 emitcode ("orl", "a,%s",
8360 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8361 /* back to result */
8362 aopPut (AOP (result), "a", offr);
8367 /*-----------------------------------------------------------------*/
8368 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8369 /*-----------------------------------------------------------------*/
8371 shiftRLeftOrResult (operand * left, int offl,
8372 operand * result, int offr, int shCount)
8374 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8375 /* shift right accumulator */
8377 /* or with result */
8378 emitcode ("orl", "a,%s",
8379 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8380 /* back to result */
8381 aopPut (AOP (result), "a", offr);
8385 #ifdef BETTER_LITERAL_SHIFT
8386 /*-----------------------------------------------------------------*/
8387 /* genlshOne - left shift a one byte quantity by known count */
8388 /*-----------------------------------------------------------------*/
8390 genlshOne (operand * result, operand * left, int shCount)
8392 D (emitcode (";", "genlshOne "););
8393 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8397 #ifdef BETTER_LITERAL_SHIFT
8398 /*-----------------------------------------------------------------*/
8399 /* genlshTwo - left shift two bytes by known amount != 0 */
8400 /*-----------------------------------------------------------------*/
8402 genlshTwo (operand * result, operand * left, int shCount)
8406 D (emitcode (";", "genlshTwo "););
8408 size = getDataSize (result);
8410 /* if shCount >= 8 */
8415 _startLazyDPSEvaluation();
8421 _endLazyDPSEvaluation();
8422 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8423 aopPut (AOP (result), zero, LSB);
8427 movLeft2Result (left, LSB, result, MSB16, 0);
8428 aopPut (AOP (result), zero, LSB);
8429 _endLazyDPSEvaluation();
8434 aopPut (AOP (result), zero, LSB);
8435 _endLazyDPSEvaluation();
8439 /* 1 <= shCount <= 7 */
8444 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8448 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8456 /*-----------------------------------------------------------------*/
8457 /* shiftLLong - shift left one long from left to result */
8458 /* offl = LSB or MSB16 */
8459 /*-----------------------------------------------------------------*/
8461 shiftLLong (operand * left, operand * result, int offr)
8464 int size = AOP_SIZE (result);
8466 if (size >= LSB + offr)
8468 l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8470 emitcode ("add", "a,acc");
8471 if (sameRegs (AOP (left), AOP (result)) &&
8472 size >= MSB16 + offr && offr != LSB)
8473 emitcode ("xch", "a,%s",
8474 aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8476 aopPut (AOP (result), "a", LSB + offr);
8479 if (size >= MSB16 + offr)
8481 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8483 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8485 emitcode ("rlc", "a");
8486 if (sameRegs (AOP (left), AOP (result)) &&
8487 size >= MSB24 + offr && offr != LSB)
8488 emitcode ("xch", "a,%s",
8489 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8491 aopPut (AOP (result), "a", MSB16 + offr);
8494 if (size >= MSB24 + offr)
8496 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8498 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8500 emitcode ("rlc", "a");
8501 if (sameRegs (AOP (left), AOP (result)) &&
8502 size >= MSB32 + offr && offr != LSB)
8503 emitcode ("xch", "a,%s",
8504 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8506 aopPut (AOP (result), "a", MSB24 + offr);
8509 if (size > MSB32 + offr)
8511 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8513 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8515 emitcode ("rlc", "a");
8516 aopPut (AOP (result), "a", MSB32 + offr);
8519 aopPut (AOP (result), zero, LSB);
8525 /*-----------------------------------------------------------------*/
8526 /* genlshFour - shift four byte by a known amount != 0 */
8527 /*-----------------------------------------------------------------*/
8529 genlshFour (operand * result, operand * left, int shCount)
8533 D (emitcode (";", "genlshFour ");
8536 size = AOP_SIZE (result);
8538 /* if shifting more that 3 bytes */
8543 /* lowest order of left goes to the highest
8544 order of the destination */
8545 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8547 movLeft2Result (left, LSB, result, MSB32, 0);
8548 aopPut (AOP (result), zero, LSB);
8549 aopPut (AOP (result), zero, MSB16);
8550 aopPut (AOP (result), zero, MSB24);
8554 /* more than two bytes */
8555 else if (shCount >= 16)
8557 /* lower order two bytes goes to higher order two bytes */
8559 /* if some more remaining */
8561 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8564 movLeft2Result (left, MSB16, result, MSB32, 0);
8565 movLeft2Result (left, LSB, result, MSB24, 0);
8567 aopPut (AOP (result), zero, MSB16);
8568 aopPut (AOP (result), zero, LSB);
8572 /* if more than 1 byte */
8573 else if (shCount >= 8)
8575 /* lower order three bytes goes to higher order three bytes */
8580 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8582 movLeft2Result (left, LSB, result, MSB16, 0);
8588 movLeft2Result (left, MSB24, result, MSB32, 0);
8589 movLeft2Result (left, MSB16, result, MSB24, 0);
8590 movLeft2Result (left, LSB, result, MSB16, 0);
8591 aopPut (AOP (result), zero, LSB);
8593 else if (shCount == 1)
8594 shiftLLong (left, result, MSB16);
8597 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8598 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8599 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8600 aopPut (AOP (result), zero, LSB);
8605 /* 1 <= shCount <= 7 */
8606 else if (shCount <= 2)
8608 shiftLLong (left, result, LSB);
8610 shiftLLong (result, result, LSB);
8612 /* 3 <= shCount <= 7, optimize */
8615 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8616 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8617 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8622 #ifdef BETTER_LITERAL_SHIFT
8623 /*-----------------------------------------------------------------*/
8624 /* genLeftShiftLiteral - left shifting by known count */
8625 /*-----------------------------------------------------------------*/
8627 genLeftShiftLiteral (operand * left,
8632 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8635 size = getSize (operandType (result));
8637 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8639 /* We only handle certain easy cases so far. */
8641 && (shCount < (size * 8))
8645 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8649 freeAsmop (right, NULL, ic, TRUE);
8651 aopOp(left, ic, FALSE, FALSE);
8652 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8655 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8657 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8658 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8660 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8663 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8665 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8666 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8668 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8674 emitcode ("; shift left ", "result %d, left %d", size,
8678 /* I suppose that the left size >= result size */
8681 _startLazyDPSEvaluation();
8684 movLeft2Result (left, size, result, size, 0);
8686 _endLazyDPSEvaluation();
8688 else if (shCount >= (size * 8))
8690 _startLazyDPSEvaluation();
8693 aopPut (AOP (result), zero, size);
8695 _endLazyDPSEvaluation();
8702 genlshOne (result, left, shCount);
8706 genlshTwo (result, left, shCount);
8710 genlshFour (result, left, shCount);
8714 fprintf(stderr, "*** ack! mystery literal shift!\n");
8718 freeAsmop (left, NULL, ic, TRUE);
8719 freeAsmop (result, NULL, ic, TRUE);
8724 /*-----------------------------------------------------------------*/
8725 /* genLeftShift - generates code for left shifting */
8726 /*-----------------------------------------------------------------*/
8728 genLeftShift (iCode * ic)
8730 operand *left, *right, *result;
8733 symbol *tlbl, *tlbl1;
8735 D (emitcode (";", "genLeftShift "););
8737 right = IC_RIGHT (ic);
8738 left = IC_LEFT (ic);
8739 result = IC_RESULT (ic);
8741 aopOp (right, ic, FALSE, FALSE);
8744 #ifdef BETTER_LITERAL_SHIFT
8745 /* if the shift count is known then do it
8746 as efficiently as possible */
8747 if (AOP_TYPE (right) == AOP_LIT)
8749 if (genLeftShiftLiteral (left, right, result, ic))
8756 /* shift count is unknown then we have to form
8757 a loop get the loop count in B : Note: we take
8758 only the lower order byte since shifting
8759 more that 32 bits make no sense anyway, ( the
8760 largest size of an object can be only 32 bits ) */
8762 if (AOP_TYPE (right) == AOP_LIT)
8764 /* Really should be handled by genLeftShiftLiteral,
8765 * but since I'm too lazy to fix that today, at least we can make
8766 * some small improvement.
8768 emitcode("mov", "b,#!constbyte",
8769 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8773 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8774 emitcode ("inc", "b");
8776 freeAsmop (right, NULL, ic, TRUE);
8777 aopOp (left, ic, FALSE, FALSE);
8778 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8780 /* now move the left to the result if they are not the
8782 if (!sameRegs (AOP (left), AOP (result)) &&
8783 AOP_SIZE (result) > 1)
8786 size = AOP_SIZE (result);
8788 _startLazyDPSEvaluation ();
8791 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8792 if (*l == '@' && (IS_AOP_PREG (result)))
8795 emitcode ("mov", "a,%s", l);
8796 aopPut (AOP (result), "a", offset);
8799 aopPut (AOP (result), l, offset);
8802 _endLazyDPSEvaluation ();
8805 tlbl = newiTempLabel (NULL);
8806 size = AOP_SIZE (result);
8808 tlbl1 = newiTempLabel (NULL);
8810 /* if it is only one byte then */
8813 symbol *tlbl1 = newiTempLabel (NULL);
8815 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8816 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8817 emitcode ("", "!tlabeldef", tlbl->key + 100);
8818 emitcode ("add", "a,acc");
8819 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8820 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8821 aopPut (AOP (result), "a", 0);
8825 reAdjustPreg (AOP (result));
8827 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8828 emitcode ("", "!tlabeldef", tlbl->key + 100);
8829 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8830 emitcode ("add", "a,acc");
8831 aopPut (AOP (result), "a", offset++);
8832 _startLazyDPSEvaluation ();
8835 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8836 emitcode ("rlc", "a");
8837 aopPut (AOP (result), "a", offset++);
8839 _endLazyDPSEvaluation ();
8840 reAdjustPreg (AOP (result));
8842 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8843 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8845 freeAsmop (left, NULL, ic, TRUE);
8846 freeAsmop (result, NULL, ic, TRUE);
8849 #ifdef BETTER_LITERAL_SHIFT
8850 /*-----------------------------------------------------------------*/
8851 /* genrshOne - right shift a one byte quantity by known count */
8852 /*-----------------------------------------------------------------*/
8854 genrshOne (operand * result, operand * left,
8855 int shCount, int sign)
8857 D (emitcode (";", "genrshOne"););
8858 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8862 #ifdef BETTER_LITERAL_SHIFT
8863 /*-----------------------------------------------------------------*/
8864 /* genrshTwo - right shift two bytes by known amount != 0 */
8865 /*-----------------------------------------------------------------*/
8867 genrshTwo (operand * result, operand * left,
8868 int shCount, int sign)
8870 D (emitcode (";", "genrshTwo"););
8872 /* if shCount >= 8 */
8876 _startLazyDPSEvaluation();
8879 shiftR1Left2Result (left, MSB16, result, LSB,
8884 movLeft2Result (left, MSB16, result, LSB, sign);
8886 addSign (result, MSB16, sign);
8887 _endLazyDPSEvaluation();
8890 /* 1 <= shCount <= 7 */
8893 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8898 /*-----------------------------------------------------------------*/
8899 /* shiftRLong - shift right one long from left to result */
8900 /* offl = LSB or MSB16 */
8901 /*-----------------------------------------------------------------*/
8903 shiftRLong (operand * left, int offl,
8904 operand * result, int sign)
8906 int isSameRegs=sameRegs(AOP(left),AOP(result));
8908 if (isSameRegs && offl>1) {
8909 // we are in big trouble, but this shouldn't happen
8910 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8913 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8918 emitcode ("rlc", "a");
8919 emitcode ("subb", "a,acc");
8920 emitcode ("xch", "a,%s",
8921 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
8923 aopPut (AOP(result), zero, MSB32);
8928 emitcode ("clr", "c");
8930 emitcode ("mov", "c,acc.7");
8933 emitcode ("rrc", "a");
8935 if (isSameRegs && offl==MSB16) {
8937 "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
8939 aopPut (AOP (result), "a", MSB32);
8940 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8943 emitcode ("rrc", "a");
8944 if (isSameRegs && offl==1) {
8945 emitcode ("xch", "a,%s",
8946 aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
8948 aopPut (AOP (result), "a", MSB24);
8949 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
8951 emitcode ("rrc", "a");
8952 aopPut (AOP (result), "a", MSB16 - offl);
8956 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
8957 emitcode ("rrc", "a");
8958 aopPut (AOP (result), "a", LSB);
8962 /*-----------------------------------------------------------------*/
8963 /* genrshFour - shift four byte by a known amount != 0 */
8964 /*-----------------------------------------------------------------*/
8966 genrshFour (operand * result, operand * left,
8967 int shCount, int sign)
8969 D (emitcode (";", "genrshFour"););
8971 /* if shifting more that 3 bytes */
8975 _startLazyDPSEvaluation();
8977 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8979 movLeft2Result (left, MSB32, result, LSB, sign);
8980 addSign (result, MSB16, sign);
8981 _endLazyDPSEvaluation();
8983 else if (shCount >= 16)
8986 _startLazyDPSEvaluation();
8988 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8991 movLeft2Result (left, MSB24, result, LSB, 0);
8992 movLeft2Result (left, MSB32, result, MSB16, sign);
8994 addSign (result, MSB24, sign);
8995 _endLazyDPSEvaluation();
8997 else if (shCount >= 8)
9000 _startLazyDPSEvaluation();
9003 shiftRLong (left, MSB16, result, sign);
9005 else if (shCount == 0)
9007 movLeft2Result (left, MSB16, result, LSB, 0);
9008 movLeft2Result (left, MSB24, result, MSB16, 0);
9009 movLeft2Result (left, MSB32, result, MSB24, sign);
9010 addSign (result, MSB32, sign);
9014 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9015 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9016 /* the last shift is signed */
9017 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9018 addSign (result, MSB32, sign);
9020 _endLazyDPSEvaluation();
9024 /* 1 <= shCount <= 7 */
9027 shiftRLong (left, LSB, result, sign);
9029 shiftRLong (result, LSB, result, sign);
9033 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9034 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9035 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9040 #ifdef BETTER_LITERAL_SHIFT
9041 /*-----------------------------------------------------------------*/
9042 /* genRightShiftLiteral - right shifting by known count */
9043 /*-----------------------------------------------------------------*/
9045 genRightShiftLiteral (operand * left,
9051 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9054 size = getSize (operandType (result));
9056 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
9058 /* We only handle certain easy cases so far. */
9060 && (shCount < (size * 8))
9065 D(emitcode (";", "genRightShiftLiteral wimping out"););
9069 freeAsmop (right, NULL, ic, TRUE);
9071 aopOp (left, ic, FALSE, FALSE);
9072 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9075 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9079 /* test the LEFT size !!! */
9081 /* I suppose that the left size >= result size */
9084 size = getDataSize (result);
9085 _startLazyDPSEvaluation();
9088 movLeft2Result (left, size, result, size, 0);
9090 _endLazyDPSEvaluation();
9092 else if (shCount >= (size * 8))
9096 /* get sign in acc.7 */
9097 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
9099 addSign (result, LSB, sign);
9106 genrshOne (result, left, shCount, sign);
9110 genrshTwo (result, left, shCount, sign);
9114 genrshFour (result, left, shCount, sign);
9121 freeAsmop (left, NULL, ic, TRUE);
9122 freeAsmop (result, NULL, ic, TRUE);
9128 /*-----------------------------------------------------------------*/
9129 /* genSignedRightShift - right shift of signed number */
9130 /*-----------------------------------------------------------------*/
9132 genSignedRightShift (iCode * ic)
9134 operand *right, *left, *result;
9137 symbol *tlbl, *tlbl1;
9139 D (emitcode (";", "genSignedRightShift "););
9141 /* we do it the hard way put the shift count in b
9142 and loop thru preserving the sign */
9144 right = IC_RIGHT (ic);
9145 left = IC_LEFT (ic);
9146 result = IC_RESULT (ic);
9148 aopOp (right, ic, FALSE, FALSE);
9150 #ifdef BETTER_LITERAL_SHIFT
9151 if (AOP_TYPE (right) == AOP_LIT)
9153 if (genRightShiftLiteral (left, right, result, ic, 1))
9159 /* shift count is unknown then we have to form
9160 a loop get the loop count in B : Note: we take
9161 only the lower order byte since shifting
9162 more that 32 bits make no sense anyway, ( the
9163 largest size of an object can be only 32 bits ) */
9165 if (AOP_TYPE (right) == AOP_LIT)
9167 /* Really should be handled by genRightShiftLiteral,
9168 * but since I'm too lazy to fix that today, at least we can make
9169 * some small improvement.
9171 emitcode("mov", "b,#!constbyte",
9172 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9176 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9177 emitcode ("inc", "b");
9179 freeAsmop (right, NULL, ic, TRUE);
9180 aopOp (left, ic, FALSE, FALSE);
9181 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9183 /* now move the left to the result if they are not the
9185 if (!sameRegs (AOP (left), AOP (result)) &&
9186 AOP_SIZE (result) > 1)
9189 size = AOP_SIZE (result);
9191 _startLazyDPSEvaluation ();
9194 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9195 if (*l == '@' && IS_AOP_PREG (result))
9198 emitcode ("mov", "a,%s", l);
9199 aopPut (AOP (result), "a", offset);
9202 aopPut (AOP (result), l, offset);
9205 _endLazyDPSEvaluation ();
9208 /* mov the highest order bit to OVR */
9209 tlbl = newiTempLabel (NULL);
9210 tlbl1 = newiTempLabel (NULL);
9212 size = AOP_SIZE (result);
9214 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
9215 emitcode ("rlc", "a");
9216 emitcode ("mov", "ov,c");
9217 /* if it is only one byte then */
9220 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9221 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9222 emitcode ("", "!tlabeldef", tlbl->key + 100);
9223 emitcode ("mov", "c,ov");
9224 emitcode ("rrc", "a");
9225 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9226 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9227 aopPut (AOP (result), "a", 0);
9231 reAdjustPreg (AOP (result));
9232 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9233 emitcode ("", "!tlabeldef", tlbl->key + 100);
9234 emitcode ("mov", "c,ov");
9235 _startLazyDPSEvaluation ();
9238 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9239 emitcode ("rrc", "a");
9240 aopPut (AOP (result), "a", offset--);
9242 _endLazyDPSEvaluation ();
9243 reAdjustPreg (AOP (result));
9244 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9245 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9248 freeAsmop (left, NULL, ic, TRUE);
9249 freeAsmop (result, NULL, ic, TRUE);
9252 /*-----------------------------------------------------------------*/
9253 /* genRightShift - generate code for right shifting */
9254 /*-----------------------------------------------------------------*/
9256 genRightShift (iCode * ic)
9258 operand *right, *left, *result;
9262 symbol *tlbl, *tlbl1;
9264 D (emitcode (";", "genRightShift "););
9266 /* if signed then we do it the hard way preserve the
9267 sign bit moving it inwards */
9268 letype = getSpec (operandType (IC_LEFT (ic)));
9270 if (!SPEC_USIGN (letype))
9272 genSignedRightShift (ic);
9276 /* signed & unsigned types are treated the same : i.e. the
9277 signed is NOT propagated inwards : quoting from the
9278 ANSI - standard : "for E1 >> E2, is equivalent to division
9279 by 2**E2 if unsigned or if it has a non-negative value,
9280 otherwise the result is implementation defined ", MY definition
9281 is that the sign does not get propagated */
9283 right = IC_RIGHT (ic);
9284 left = IC_LEFT (ic);
9285 result = IC_RESULT (ic);
9287 aopOp (right, ic, FALSE, FALSE);
9289 #ifdef BETTER_LITERAL_SHIFT
9290 /* if the shift count is known then do it
9291 as efficiently as possible */
9292 if (AOP_TYPE (right) == AOP_LIT)
9294 if (genRightShiftLiteral (left, right, result, ic, 0))
9301 /* shift count is unknown then we have to form
9302 a loop get the loop count in B : Note: we take
9303 only the lower order byte since shifting
9304 more that 32 bits make no sense anyway, ( the
9305 largest size of an object can be only 32 bits ) */
9307 if (AOP_TYPE (right) == AOP_LIT)
9309 /* Really should be handled by genRightShiftLiteral,
9310 * but since I'm too lazy to fix that today, at least we can make
9311 * some small improvement.
9313 emitcode("mov", "b,#!constbyte",
9314 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9318 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9319 emitcode ("inc", "b");
9321 freeAsmop (right, NULL, ic, TRUE);
9322 aopOp (left, ic, FALSE, FALSE);
9323 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9325 /* now move the left to the result if they are not the
9327 if (!sameRegs (AOP (left), AOP (result)) &&
9328 AOP_SIZE (result) > 1)
9331 size = AOP_SIZE (result);
9333 _startLazyDPSEvaluation ();
9336 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9337 if (*l == '@' && IS_AOP_PREG (result))
9340 emitcode ("mov", "a,%s", l);
9341 aopPut (AOP (result), "a", offset);
9344 aopPut (AOP (result), l, offset);
9347 _endLazyDPSEvaluation ();
9350 tlbl = newiTempLabel (NULL);
9351 tlbl1 = newiTempLabel (NULL);
9352 size = AOP_SIZE (result);
9355 /* if it is only one byte then */
9358 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9359 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9360 emitcode ("", "!tlabeldef", tlbl->key + 100);
9362 emitcode ("rrc", "a");
9363 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9364 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9365 aopPut (AOP (result), "a", 0);
9369 reAdjustPreg (AOP (result));
9370 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9371 emitcode ("", "!tlabeldef", tlbl->key + 100);
9373 _startLazyDPSEvaluation ();
9376 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9377 emitcode ("rrc", "a");
9378 aopPut (AOP (result), "a", offset--);
9380 _endLazyDPSEvaluation ();
9381 reAdjustPreg (AOP (result));
9383 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9384 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9387 freeAsmop (left, NULL, ic, TRUE);
9388 freeAsmop (result, NULL, ic, TRUE);
9392 /*-----------------------------------------------------------------*/
9393 /* emitPtrByteGet - emits code to get a byte into A through a */
9394 /* pointer register (R0, R1, or DPTR). The */
9395 /* original value of A can be preserved in B. */
9396 /*-----------------------------------------------------------------*/
9398 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9405 emitcode ("mov", "b,a");
9406 emitcode ("mov", "a,@%s", rname);
9411 emitcode ("mov", "b,a");
9412 emitcode ("movx", "a,@%s", rname);
9417 emitcode ("mov", "b,a");
9418 emitcode ("movx", "a,@dptr");
9423 emitcode ("mov", "b,a");
9424 emitcode ("clr", "a");
9425 emitcode ("movc", "a,@a+dptr");
9431 emitcode ("push", "b");
9432 emitcode ("push", "acc");
9434 emitcode ("lcall", "__gptrget");
9436 emitcode ("pop", "b");
9441 /*-----------------------------------------------------------------*/
9442 /* emitPtrByteSet - emits code to set a byte from src through a */
9443 /* pointer register (R0, R1, or DPTR). */
9444 /*-----------------------------------------------------------------*/
9446 emitPtrByteSet (char *rname, int p_type, char *src)
9455 emitcode ("mov", "@%s,a", rname);
9458 emitcode ("mov", "@%s,%s", rname, src);
9463 emitcode ("movx", "@%s,a", rname);
9468 emitcode ("movx", "@dptr,a");
9473 emitcode ("lcall", "__gptrput");
9478 /*-----------------------------------------------------------------*/
9479 /* genUnpackBits - generates code for unpacking bits */
9480 /*-----------------------------------------------------------------*/
9482 genUnpackBits (operand * result, char *rname, int ptype)
9484 int offset = 0; /* result byte offset */
9485 int rsize; /* result size */
9486 int rlen = 0; /* remaining bitfield length */
9487 sym_link *etype; /* bitfield type information */
9488 int blen; /* bitfield length */
9489 int bstr; /* bitfield starting bit within byte */
9491 D(emitcode ("; genUnpackBits",""));
9493 etype = getSpec (operandType (result));
9494 rsize = getSize (operandType (result));
9495 blen = SPEC_BLEN (etype);
9496 bstr = SPEC_BSTR (etype);
9498 /* If the bitfield length is less than a byte */
9501 emitPtrByteGet (rname, ptype, FALSE);
9503 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9504 aopPut (AOP (result), "a", offset++);
9508 /* Bit field did not fit in a byte. Copy all
9509 but the partial byte at the end. */
9510 for (rlen=blen;rlen>=8;rlen-=8)
9512 emitPtrByteGet (rname, ptype, FALSE);
9513 aopPut (AOP (result), "a", offset++);
9515 emitcode ("inc", "%s", rname);
9518 /* Handle the partial byte at the end */
9521 emitPtrByteGet (rname, ptype, FALSE);
9522 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9523 aopPut (AOP (result), "a", offset++);
9531 aopPut (AOP (result), zero, offset++);
9536 /*-----------------------------------------------------------------*/
9537 /* genDataPointerGet - generates code when ptr offset is known */
9538 /*-----------------------------------------------------------------*/
9540 genDataPointerGet (operand * left,
9546 int size, offset = 0;
9547 aopOp (result, ic, TRUE, FALSE);
9549 /* get the string representation of the name */
9550 l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9551 size = AOP_SIZE (result);
9552 _startLazyDPSEvaluation ();
9557 SNPRINTF (buff, sizeof(buff),
9558 "(%s + %d)", l + 1, offset);
9562 SNPRINTF (buff, sizeof(buff),
9565 aopPut (AOP (result), buff, offset++);
9567 _endLazyDPSEvaluation ();
9569 freeAsmop (left, NULL, ic, TRUE);
9570 freeAsmop (result, NULL, ic, TRUE);
9573 /*-----------------------------------------------------------------*/
9574 /* genNearPointerGet - emitcode for near pointer fetch */
9575 /*-----------------------------------------------------------------*/
9577 genNearPointerGet (operand * left,
9585 sym_link *rtype, *retype, *letype;
9586 sym_link *ltype = operandType (left);
9589 rtype = operandType (result);
9590 retype = getSpec (rtype);
9591 letype = getSpec (ltype);
9593 aopOp (left, ic, FALSE, FALSE);
9595 /* if left is rematerialisable and
9596 result is not bitfield variable type and
9597 the left is pointer to data space i.e
9598 lower 128 bytes of space */
9599 if (AOP_TYPE (left) == AOP_IMMD &&
9600 !IS_BITFIELD (retype) &&
9601 !IS_BITFIELD (letype) &&
9602 DCL_TYPE (ltype) == POINTER)
9604 genDataPointerGet (left, result, ic);
9608 /* if the value is already in a pointer register
9609 then don't need anything more */
9610 if (!AOP_INPREG (AOP (left)))
9612 /* otherwise get a free pointer register */
9614 preg = getFreePtr (ic, &aop, FALSE);
9615 emitcode ("mov", "%s,%s",
9617 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9621 rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9623 freeAsmop (left, NULL, ic, TRUE);
9624 aopOp (result, ic, FALSE, FALSE);
9626 /* if bitfield then unpack the bits */
9627 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9628 genUnpackBits (result, rname, POINTER);
9631 /* we have can just get the values */
9632 int size = AOP_SIZE (result);
9637 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9640 emitcode ("mov", "a,@%s", rname);
9641 aopPut (AOP (result), "a", offset);
9645 SNPRINTF (buff, sizeof(buff), "@%s", rname);
9646 aopPut (AOP (result), buff, offset);
9651 emitcode ("inc", "%s", rname);
9656 /* now some housekeeping stuff */
9659 /* we had to allocate for this iCode */
9660 if (pi) { /* post increment present */
9661 aopPut(AOP ( left ),rname,0);
9663 freeAsmop (NULL, aop, ic, TRUE);
9667 /* we did not allocate which means left
9668 already in a pointer register, then
9669 if size > 0 && this could be used again
9670 we have to point it back to where it
9672 if (AOP_SIZE (result) > 1 &&
9673 !OP_SYMBOL (left)->remat &&
9674 (OP_SYMBOL (left)->liveTo > ic->seq ||
9678 int size = AOP_SIZE (result) - 1;
9680 emitcode ("dec", "%s", rname);
9685 freeAsmop (result, NULL, ic, TRUE);
9686 if (pi) pi->generated = 1;
9689 /*-----------------------------------------------------------------*/
9690 /* genPagedPointerGet - emitcode for paged pointer fetch */
9691 /*-----------------------------------------------------------------*/
9693 genPagedPointerGet (operand * left,
9701 sym_link *rtype, *retype, *letype;
9703 rtype = operandType (result);
9704 retype = getSpec (rtype);
9705 letype = getSpec (operandType (left));
9706 aopOp (left, ic, FALSE, FALSE);
9708 /* if the value is already in a pointer register
9709 then don't need anything more */
9710 if (!AOP_INPREG (AOP (left)))
9712 /* otherwise get a free pointer register */
9714 preg = getFreePtr (ic, &aop, FALSE);
9715 emitcode ("mov", "%s,%s",
9717 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9721 rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9723 freeAsmop (left, NULL, ic, TRUE);
9724 aopOp (result, ic, FALSE, FALSE);
9726 /* if bitfield then unpack the bits */
9727 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9728 genUnpackBits (result, rname, PPOINTER);
9731 /* we have can just get the values */
9732 int size = AOP_SIZE (result);
9738 emitcode ("movx", "a,@%s", rname);
9739 aopPut (AOP (result), "a", offset);
9744 emitcode ("inc", "%s", rname);
9748 /* now some housekeeping stuff */
9751 /* we had to allocate for this iCode */
9752 if (pi) aopPut ( AOP (left), rname, 0);
9753 freeAsmop (NULL, aop, ic, TRUE);
9757 /* we did not allocate which means left
9758 already in a pointer register, then
9759 if size > 0 && this could be used again
9760 we have to point it back to where it
9762 if (AOP_SIZE (result) > 1 &&
9763 !OP_SYMBOL (left)->remat &&
9764 (OP_SYMBOL (left)->liveTo > ic->seq ||
9768 int size = AOP_SIZE (result) - 1;
9770 emitcode ("dec", "%s", rname);
9775 freeAsmop (result, NULL, ic, TRUE);
9776 if (pi) pi->generated = 1;
9779 /*-----------------------------------------------------------------*/
9780 /* genFarPointerGet - gget value from far space */
9781 /*-----------------------------------------------------------------*/
9783 genFarPointerGet (operand * left,
9784 operand * result, iCode * ic, iCode *pi)
9786 int size, offset, dopi=1;
9787 sym_link *retype = getSpec (operandType (result));
9788 sym_link *letype = getSpec (operandType (left));
9789 D (emitcode (";", "genFarPointerGet"););
9791 aopOp (left, ic, FALSE, FALSE);
9793 /* if the operand is already in dptr
9794 then we do nothing else we move the value to dptr */
9795 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9797 /* if this is remateriazable */
9798 if (AOP_TYPE (left) == AOP_IMMD)
9800 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9804 /* we need to get it byte by byte */
9805 _startLazyDPSEvaluation ();
9806 if (AOP_TYPE (left) != AOP_DPTR)
9808 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9809 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9810 if (options.model == MODEL_FLAT24)
9811 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9815 /* We need to generate a load to DPTR indirect through DPTR. */
9816 D (emitcode (";", "genFarPointerGet -- indirection special case."););
9817 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9818 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9819 if (options.model == MODEL_FLAT24)
9820 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9821 emitcode ("pop", "dph");
9822 emitcode ("pop", "dpl");
9825 _endLazyDPSEvaluation ();
9828 /* so dptr know contains the address */
9829 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9831 /* if bit then unpack */
9832 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9833 if (AOP_INDPTRn(left)) {
9834 genSetDPTR(AOP(left)->aopu.dptr);
9836 genUnpackBits (result, "dptr", FPOINTER);
9837 if (AOP_INDPTRn(left)) {
9842 size = AOP_SIZE (result);
9845 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9847 genSetDPTR(AOP(left)->aopu.dptr);
9848 emitcode ("movx", "a,@dptr");
9849 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9850 emitcode ("inc", "dptr");
9852 aopPut (AOP (result), "a", offset++);
9855 _startLazyDPSEvaluation ();
9857 if (AOP_INDPTRn(left)) {
9858 genSetDPTR(AOP(left)->aopu.dptr);
9864 emitcode ("movx", "a,@dptr");
9865 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9866 emitcode ("inc", "dptr");
9868 aopPut (AOP (result), "a", offset++);
9870 _endLazyDPSEvaluation ();
9873 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9874 if (!AOP_INDPTRn(left)) {
9875 _startLazyDPSEvaluation ();
9876 aopPut ( AOP (left), "dpl", 0);
9877 aopPut ( AOP (left), "dph", 1);
9878 if (options.model == MODEL_FLAT24)
9879 aopPut ( AOP (left), "dpx", 2);
9880 _endLazyDPSEvaluation ();
9883 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
9884 AOP_SIZE(result) > 1 &&
9886 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9888 size = AOP_SIZE (result) - 1;
9889 if (AOP_INDPTRn(left)) {
9890 genSetDPTR(AOP(left)->aopu.dptr);
9892 while (size--) emitcode ("lcall","__decdptr");
9893 if (AOP_INDPTRn(left)) {
9898 freeAsmop (left, NULL, ic, TRUE);
9899 freeAsmop (result, NULL, ic, TRUE);
9902 /*-----------------------------------------------------------------*/
9903 /* genCodePointerGet - get value from code space */
9904 /*-----------------------------------------------------------------*/
9906 genCodePointerGet (operand * left,
9907 operand * result, iCode * ic, iCode *pi)
9909 int size, offset, dopi=1;
9910 sym_link *retype = getSpec (operandType (result));
9912 aopOp (left, ic, FALSE, FALSE);
9914 /* if the operand is already in dptr
9915 then we do nothing else we move the value to dptr */
9916 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9918 /* if this is remateriazable */
9919 if (AOP_TYPE (left) == AOP_IMMD)
9921 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9924 { /* we need to get it byte by byte */
9925 _startLazyDPSEvaluation ();
9926 if (AOP_TYPE (left) != AOP_DPTR)
9928 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9929 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9930 if (options.model == MODEL_FLAT24)
9931 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9935 /* We need to generate a load to DPTR indirect through DPTR. */
9936 D (emitcode (";", "gencodePointerGet -- indirection special case."););
9937 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9938 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9939 if (options.model == MODEL_FLAT24)
9940 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9941 emitcode ("pop", "dph");
9942 emitcode ("pop", "dpl");
9945 _endLazyDPSEvaluation ();
9948 /* so dptr know contains the address */
9949 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9951 /* if bit then unpack */
9952 if (IS_BITFIELD (retype)) {
9953 if (AOP_INDPTRn(left)) {
9954 genSetDPTR(AOP(left)->aopu.dptr);
9956 genUnpackBits (result, "dptr", CPOINTER);
9957 if (AOP_INDPTRn(left)) {
9962 size = AOP_SIZE (result);
9964 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9966 genSetDPTR(AOP(left)->aopu.dptr);
9967 emitcode ("clr", "a");
9968 emitcode ("movc", "a,@a+dptr");
9969 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9970 emitcode ("inc", "dptr");
9972 aopPut (AOP (result), "a", offset++);
9975 _startLazyDPSEvaluation ();
9978 if (AOP_INDPTRn(left)) {
9979 genSetDPTR(AOP(left)->aopu.dptr);
9985 emitcode ("clr", "a");
9986 emitcode ("movc", "a,@a+dptr");
9987 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9988 emitcode ("inc", "dptr");
9989 aopPut (AOP (result), "a", offset++);
9991 _endLazyDPSEvaluation ();
9994 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9995 if (!AOP_INDPTRn(left)) {
9996 _startLazyDPSEvaluation ();
9998 aopPut ( AOP (left), "dpl", 0);
9999 aopPut ( AOP (left), "dph", 1);
10000 if (options.model == MODEL_FLAT24)
10001 aopPut ( AOP (left), "dpx", 2);
10003 _endLazyDPSEvaluation ();
10006 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
10007 AOP_SIZE(result) > 1 &&
10008 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10010 size = AOP_SIZE (result) - 1;
10011 if (AOP_INDPTRn(left)) {
10012 genSetDPTR(AOP(left)->aopu.dptr);
10014 while (size--) emitcode ("lcall","__decdptr");
10015 if (AOP_INDPTRn(left)) {
10020 freeAsmop (left, NULL, ic, TRUE);
10021 freeAsmop (result, NULL, ic, TRUE);
10024 /*-----------------------------------------------------------------*/
10025 /* genGenPointerGet - gget value from generic pointer space */
10026 /*-----------------------------------------------------------------*/
10028 genGenPointerGet (operand * left,
10029 operand * result, iCode * ic, iCode * pi)
10032 sym_link *retype = getSpec (operandType (result));
10033 sym_link *letype = getSpec (operandType (left));
10035 D (emitcode (";", "genGenPointerGet "); );
10037 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
10039 /* if the operand is already in dptr
10040 then we do nothing else we move the value to dptr */
10041 if (AOP_TYPE (left) != AOP_STR)
10043 /* if this is remateriazable */
10044 if (AOP_TYPE (left) == AOP_IMMD)
10046 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10047 if (AOP(left)->aopu.aop_immd.from_cast_remat)
10049 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
10053 emitcode ("mov", "b,#%d", pointerCode (retype));
10057 { /* we need to get it byte by byte */
10058 _startLazyDPSEvaluation ();
10059 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
10060 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
10061 if (options.model == MODEL_FLAT24) {
10062 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10063 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
10065 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10067 _endLazyDPSEvaluation ();
10071 /* so dptr-b now contains the address */
10073 aopOp (result, ic, FALSE, TRUE);
10076 /* if bit then unpack */
10077 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10079 genUnpackBits (result, "dptr", GPOINTER);
10083 size = AOP_SIZE (result);
10090 // Get two bytes at a time, results in _AP & A.
10091 // dptr will be incremented ONCE by __gptrgetWord.
10093 // Note: any change here must be coordinated
10094 // with the implementation of __gptrgetWord
10095 // in device/lib/_gptrget.c
10096 emitcode ("lcall", "__gptrgetWord");
10097 aopPut (AOP (result), DP2_RESULT_REG, offset++);
10098 aopPut (AOP (result), "a", offset++);
10103 // Only one byte to get.
10104 emitcode ("lcall", "__gptrget");
10105 aopPut (AOP (result), "a", offset++);
10108 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
10110 emitcode ("inc", "dptr");
10115 if (pi && AOP_TYPE (left) != AOP_IMMD) {
10116 _startLazyDPSEvaluation ();
10118 aopPut ( AOP (left), "dpl", 0);
10119 aopPut ( AOP (left), "dph", 1);
10120 if (options.model == MODEL_FLAT24) {
10121 aopPut ( AOP (left), "dpx", 2);
10122 aopPut ( AOP (left), "b", 3);
10123 } else aopPut ( AOP (left), "b", 2);
10125 _endLazyDPSEvaluation ();
10128 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
10129 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10131 size = AOP_SIZE (result) - 1;
10132 while (size--) emitcode ("lcall","__decdptr");
10135 freeAsmop (left, NULL, ic, TRUE);
10136 freeAsmop (result, NULL, ic, TRUE);
10139 /*-----------------------------------------------------------------*/
10140 /* genPointerGet - generate code for pointer get */
10141 /*-----------------------------------------------------------------*/
10143 genPointerGet (iCode * ic, iCode *pi)
10145 operand *left, *result;
10146 sym_link *type, *etype;
10149 D (emitcode (";", "genPointerGet ");
10152 left = IC_LEFT (ic);
10153 result = IC_RESULT (ic);
10155 /* depending on the type of pointer we need to
10156 move it to the correct pointer register */
10157 type = operandType (left);
10158 etype = getSpec (type);
10159 /* if left is of type of pointer then it is simple */
10160 if (IS_PTR (type) && !IS_FUNC (type->next))
10161 p_type = DCL_TYPE (type);
10164 /* we have to go by the storage class */
10165 p_type = PTR_TYPE (SPEC_OCLS (etype));
10167 /* special case when cast remat */
10168 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10169 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
10170 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10171 type = operandType (left);
10172 p_type = DCL_TYPE (type);
10174 /* now that we have the pointer type we assign
10175 the pointer values */
10181 genNearPointerGet (left, result, ic, pi);
10185 genPagedPointerGet (left, result, ic, pi);
10189 genFarPointerGet (left, result, ic, pi);
10193 genCodePointerGet (left, result, ic, pi);
10197 genGenPointerGet (left, result, ic, pi);
10203 /*-----------------------------------------------------------------*/
10204 /* genPackBits - generates code for packed bit storage */
10205 /*-----------------------------------------------------------------*/
10207 genPackBits (sym_link * etype,
10209 char *rname, int p_type)
10211 int offset = 0; /* source byte offset */
10212 int rlen = 0; /* remaining bitfield length */
10213 int blen; /* bitfield length */
10214 int bstr; /* bitfield starting bit within byte */
10215 int litval; /* source literal value (if AOP_LIT) */
10216 unsigned char mask; /* bitmask within current byte */
10218 D(emitcode ("; genPackBits",""));
10220 blen = SPEC_BLEN (etype);
10221 bstr = SPEC_BSTR (etype);
10223 /* If the bitfield length is less than a byte */
10226 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10227 (unsigned char) (0xFF >> (8 - bstr)));
10229 if (AOP_TYPE (right) == AOP_LIT)
10231 /* Case with a bitfield length <8 and literal source
10233 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10235 litval &= (~mask) & 0xff;
10236 emitPtrByteGet (rname, p_type, FALSE);
10237 if ((mask|litval)!=0xff)
10238 emitcode ("anl","a,#!constbyte", mask);
10240 emitcode ("orl","a,#!constbyte", litval);
10244 if ((blen==1) && (p_type!=GPOINTER))
10246 /* Case with a bitfield length == 1 and no generic pointer
10248 if (AOP_TYPE (right) == AOP_CRY)
10249 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10252 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10253 emitcode ("rrc","a");
10255 emitPtrByteGet (rname, p_type, FALSE);
10256 emitcode ("mov","acc.%d,c",bstr);
10260 /* Case with a bitfield length < 8 and arbitrary source
10262 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10263 /* shift and mask source value */
10265 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10267 /* transfer A to B and get next byte */
10268 emitPtrByteGet (rname, p_type, TRUE);
10270 emitcode ("anl", "a,#!constbyte", mask);
10271 emitcode ("orl", "a,b");
10272 if (p_type == GPOINTER)
10273 emitcode ("pop", "b");
10277 emitPtrByteSet (rname, p_type, "a");
10281 /* Bit length is greater than 7 bits. In this case, copy */
10282 /* all except the partial byte at the end */
10283 for (rlen=blen;rlen>=8;rlen-=8)
10285 emitPtrByteSet (rname, p_type,
10286 aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
10288 emitcode ("inc", "%s", rname);
10291 /* If there was a partial byte at the end */
10294 mask = (((unsigned char) -1 << rlen) & 0xff);
10296 if (AOP_TYPE (right) == AOP_LIT)
10298 /* Case with partial byte and literal source
10300 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10301 litval >>= (blen-rlen);
10302 litval &= (~mask) & 0xff;
10303 emitPtrByteGet (rname, p_type, FALSE);
10304 if ((mask|litval)!=0xff)
10305 emitcode ("anl","a,#!constbyte", mask);
10307 emitcode ("orl","a,#!constbyte", litval);
10311 /* Case with partial byte and arbitrary source
10313 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10314 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10316 /* transfer A to B and get next byte */
10317 emitPtrByteGet (rname, p_type, TRUE);
10319 emitcode ("anl", "a,#!constbyte", mask);
10320 emitcode ("orl", "a,b");
10321 if (p_type == GPOINTER)
10322 emitcode ("pop", "b");
10324 emitPtrByteSet (rname, p_type, "a");
10330 /*-----------------------------------------------------------------*/
10331 /* genDataPointerSet - remat pointer to data space */
10332 /*-----------------------------------------------------------------*/
10334 genDataPointerSet (operand * right,
10338 int size, offset = 0;
10339 char *l, buff[256];
10341 aopOp (right, ic, FALSE, FALSE);
10343 l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
10344 size = AOP_SIZE (right);
10349 SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
10353 SNPRINTF (buff, sizeof(buff), "%s", l + 1);
10356 emitcode ("mov", "%s,%s", buff,
10357 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10360 freeAsmop (right, NULL, ic, TRUE);
10361 freeAsmop (result, NULL, ic, TRUE);
10364 /*-----------------------------------------------------------------*/
10365 /* genNearPointerSet - emitcode for near pointer put */
10366 /*-----------------------------------------------------------------*/
10368 genNearPointerSet (operand * right,
10375 sym_link *retype, *letype;
10376 sym_link *ptype = operandType (result);
10378 retype = getSpec (operandType (right));
10379 letype = getSpec (ptype);
10381 aopOp (result, ic, FALSE, FALSE);
10383 /* if the result is rematerializable &
10384 in data space & not a bit variable */
10385 if (AOP_TYPE (result) == AOP_IMMD &&
10386 DCL_TYPE (ptype) == POINTER &&
10387 !IS_BITVAR (retype) &&
10388 !IS_BITVAR (letype))
10390 genDataPointerSet (right, result, ic);
10394 /* if the value is already in a pointer register
10395 then don't need anything more */
10396 if (!AOP_INPREG (AOP (result)))
10398 /* otherwise get a free pointer register */
10401 aop = newAsmop (0);
10402 preg = getFreePtr (ic, &aop, FALSE);
10403 emitcode ("mov", "%s,%s",
10405 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10406 rname = preg->name;
10409 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10411 aopOp (right, ic, FALSE, FALSE);
10413 /* if bitfield then unpack the bits */
10414 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10415 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10418 /* we have can just get the values */
10419 int size = AOP_SIZE (right);
10424 l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10428 emitcode ("mov", "@%s,a", rname);
10431 emitcode ("mov", "@%s,%s", rname, l);
10433 emitcode ("inc", "%s", rname);
10438 /* now some housekeeping stuff */
10441 /* we had to allocate for this iCode */
10442 if (pi) aopPut (AOP (result),rname,0);
10443 freeAsmop (NULL, aop, ic, TRUE);
10447 /* we did not allocate which means left
10448 already in a pointer register, then
10449 if size > 0 && this could be used again
10450 we have to point it back to where it
10452 if (AOP_SIZE (right) > 1 &&
10453 !OP_SYMBOL (result)->remat &&
10454 (OP_SYMBOL (result)->liveTo > ic->seq ||
10458 int size = AOP_SIZE (right) - 1;
10460 emitcode ("dec", "%s", rname);
10465 if (pi) pi->generated = 1;
10466 freeAsmop (result, NULL, ic, TRUE);
10467 freeAsmop (right, NULL, ic, TRUE);
10472 /*-----------------------------------------------------------------*/
10473 /* genPagedPointerSet - emitcode for Paged pointer put */
10474 /*-----------------------------------------------------------------*/
10476 genPagedPointerSet (operand * right,
10483 sym_link *retype, *letype;
10485 retype = getSpec (operandType (right));
10486 letype = getSpec (operandType (result));
10488 aopOp (result, ic, FALSE, FALSE);
10490 /* if the value is already in a pointer register
10491 then don't need anything more */
10492 if (!AOP_INPREG (AOP (result)))
10494 /* otherwise get a free pointer register */
10497 aop = newAsmop (0);
10498 preg = getFreePtr (ic, &aop, FALSE);
10499 emitcode ("mov", "%s,%s",
10501 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10502 rname = preg->name;
10505 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10507 aopOp (right, ic, FALSE, FALSE);
10509 /* if bitfield then unpack the bits */
10510 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10511 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10514 /* we have can just get the values */
10515 int size = AOP_SIZE (right);
10520 MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10522 emitcode ("movx", "@%s,a", rname);
10525 emitcode ("inc", "%s", rname);
10531 /* now some housekeeping stuff */
10534 if (pi) aopPut (AOP (result),rname,0);
10535 /* we had to allocate for this iCode */
10536 freeAsmop (NULL, aop, ic, TRUE);
10540 /* we did not allocate which means left
10541 already in a pointer register, then
10542 if size > 0 && this could be used again
10543 we have to point it back to where it
10545 if (AOP_SIZE (right) > 1 &&
10546 !OP_SYMBOL (result)->remat &&
10547 (OP_SYMBOL (result)->liveTo > ic->seq ||
10551 int size = AOP_SIZE (right) - 1;
10553 emitcode ("dec", "%s", rname);
10558 if (pi) pi->generated = 1;
10559 freeAsmop (result, NULL, ic, TRUE);
10560 freeAsmop (right, NULL, ic, TRUE);
10565 /*-----------------------------------------------------------------*/
10566 /* genFarPointerSet - set value from far space */
10567 /*-----------------------------------------------------------------*/
10569 genFarPointerSet (operand * right,
10570 operand * result, iCode * ic, iCode *pi)
10572 int size, offset, dopi=1;
10573 sym_link *retype = getSpec (operandType (right));
10574 sym_link *letype = getSpec (operandType (result));
10576 aopOp (result, ic, FALSE, FALSE);
10578 /* if the operand is already in dptr
10579 then we do nothing else we move the value to dptr */
10580 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10582 /* if this is remateriazable */
10583 if (AOP_TYPE (result) == AOP_IMMD)
10584 emitcode ("mov", "dptr,%s",
10585 aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10588 /* we need to get it byte by byte */
10589 _startLazyDPSEvaluation ();
10590 if (AOP_TYPE (result) != AOP_DPTR)
10592 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10593 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10594 if (options.model == MODEL_FLAT24)
10595 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10599 /* We need to generate a load to DPTR indirect through DPTR. */
10600 D (emitcode (";", "genFarPointerSet -- indirection special case."););
10602 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10603 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10604 if (options.model == MODEL_FLAT24)
10605 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10606 emitcode ("pop", "dph");
10607 emitcode ("pop", "dpl");
10610 _endLazyDPSEvaluation ();
10613 /* so dptr know contains the address */
10614 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10616 /* if bit then unpack */
10617 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10618 if (AOP_INDPTRn(result)) {
10619 genSetDPTR(AOP(result)->aopu.dptr);
10621 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10622 if (AOP_INDPTRn(result)) {
10626 size = AOP_SIZE (right);
10628 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10630 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10632 genSetDPTR(AOP(result)->aopu.dptr);
10633 emitcode ("movx", "@dptr,a");
10634 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10635 emitcode ("inc", "dptr");
10639 _startLazyDPSEvaluation ();
10641 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10643 if (AOP_INDPTRn(result)) {
10644 genSetDPTR(AOP(result)->aopu.dptr);
10650 emitcode ("movx", "@dptr,a");
10651 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10652 emitcode ("inc", "dptr");
10654 _endLazyDPSEvaluation ();
10658 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10659 if (!AOP_INDPTRn(result)) {
10660 _startLazyDPSEvaluation ();
10662 aopPut (AOP(result),"dpl",0);
10663 aopPut (AOP(result),"dph",1);
10664 if (options.model == MODEL_FLAT24)
10665 aopPut (AOP(result),"dpx",2);
10667 _endLazyDPSEvaluation ();
10670 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10671 AOP_SIZE(right) > 1 &&
10672 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10674 size = AOP_SIZE (right) - 1;
10675 if (AOP_INDPTRn(result)) {
10676 genSetDPTR(AOP(result)->aopu.dptr);
10678 while (size--) emitcode ("lcall","__decdptr");
10679 if (AOP_INDPTRn(result)) {
10683 freeAsmop (result, NULL, ic, TRUE);
10684 freeAsmop (right, NULL, ic, TRUE);
10687 /*-----------------------------------------------------------------*/
10688 /* genGenPointerSet - set value from generic pointer space */
10689 /*-----------------------------------------------------------------*/
10691 genGenPointerSet (operand * right,
10692 operand * result, iCode * ic, iCode *pi)
10695 sym_link *retype = getSpec (operandType (right));
10696 sym_link *letype = getSpec (operandType (result));
10698 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10700 /* if the operand is already in dptr
10701 then we do nothing else we move the value to dptr */
10702 if (AOP_TYPE (result) != AOP_STR)
10704 _startLazyDPSEvaluation ();
10705 /* if this is remateriazable */
10706 if (AOP_TYPE (result) == AOP_IMMD)
10708 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10709 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10711 MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10716 "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10720 { /* we need to get it byte by byte */
10721 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10722 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10723 if (options.model == MODEL_FLAT24) {
10724 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10725 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10727 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10730 _endLazyDPSEvaluation ();
10732 /* so dptr + b now contains the address */
10734 aopOp (right, ic, FALSE, TRUE);
10738 /* if bit then unpack */
10739 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10741 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10745 size = AOP_SIZE (right);
10748 _startLazyDPSEvaluation ();
10753 // Set two bytes at a time, passed in _AP & A.
10754 // dptr will be incremented ONCE by __gptrputWord.
10756 // Note: any change here must be coordinated
10757 // with the implementation of __gptrputWord
10758 // in device/lib/_gptrput.c
10759 emitcode("mov", "_ap, %s",
10760 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10761 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10765 emitcode ("lcall", "__gptrputWord");
10770 // Only one byte to put.
10771 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10775 emitcode ("lcall", "__gptrput");
10778 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10780 emitcode ("inc", "dptr");
10783 _endLazyDPSEvaluation ();
10786 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10787 _startLazyDPSEvaluation ();
10789 aopPut (AOP(result),"dpl",0);
10790 aopPut (AOP(result),"dph",1);
10791 if (options.model == MODEL_FLAT24) {
10792 aopPut (AOP(result),"dpx",2);
10793 aopPut (AOP(result),"b",3);
10795 aopPut (AOP(result),"b",2);
10797 _endLazyDPSEvaluation ();
10800 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10801 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10803 size = AOP_SIZE (right) - 1;
10804 while (size--) emitcode ("lcall","__decdptr");
10806 freeAsmop (result, NULL, ic, TRUE);
10807 freeAsmop (right, NULL, ic, TRUE);
10810 /*-----------------------------------------------------------------*/
10811 /* genPointerSet - stores the value into a pointer location */
10812 /*-----------------------------------------------------------------*/
10814 genPointerSet (iCode * ic, iCode *pi)
10816 operand *right, *result;
10817 sym_link *type, *etype;
10820 D (emitcode (";", "genPointerSet "););
10822 right = IC_RIGHT (ic);
10823 result = IC_RESULT (ic);
10825 /* depending on the type of pointer we need to
10826 move it to the correct pointer register */
10827 type = operandType (result);
10828 etype = getSpec (type);
10829 /* if left is of type of pointer then it is simple */
10830 if (IS_PTR (type) && !IS_FUNC (type->next))
10832 p_type = DCL_TYPE (type);
10836 /* we have to go by the storage class */
10837 p_type = PTR_TYPE (SPEC_OCLS (etype));
10839 /* special case when cast remat */
10840 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10841 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10842 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10843 type = operandType (result);
10844 p_type = DCL_TYPE (type);
10847 /* now that we have the pointer type we assign
10848 the pointer values */
10854 genNearPointerSet (right, result, ic, pi);
10858 genPagedPointerSet (right, result, ic, pi);
10862 genFarPointerSet (right, result, ic, pi);
10866 genGenPointerSet (right, result, ic, pi);
10870 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10871 "genPointerSet: illegal pointer type");
10876 /*-----------------------------------------------------------------*/
10877 /* genIfx - generate code for Ifx statement */
10878 /*-----------------------------------------------------------------*/
10880 genIfx (iCode * ic, iCode * popIc)
10882 operand *cond = IC_COND (ic);
10885 D (emitcode (";", "genIfx "););
10887 aopOp (cond, ic, FALSE, FALSE);
10889 /* get the value into acc */
10890 if (AOP_TYPE (cond) != AOP_CRY)
10899 /* the result is now in the accumulator */
10900 freeAsmop (cond, NULL, ic, TRUE);
10902 /* if there was something to be popped then do it */
10906 /* if the condition is a bit variable */
10907 if (isbit && IS_ITEMP (cond) &&
10910 genIfxJump (ic, SPIL_LOC (cond)->rname);
10912 else if (isbit && !IS_ITEMP (cond))
10914 genIfxJump (ic, OP_SYMBOL (cond)->rname);
10918 genIfxJump (ic, "a");
10924 /*-----------------------------------------------------------------*/
10925 /* genAddrOf - generates code for address of */
10926 /*-----------------------------------------------------------------*/
10928 genAddrOf (iCode * ic)
10930 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10933 D (emitcode (";", "genAddrOf ");
10936 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10938 /* if the operand is on the stack then we
10939 need to get the stack offset of this
10941 if (sym->onStack) {
10943 /* if 10 bit stack */
10944 if (options.stack10bit) {
10948 tsprintf(buff, sizeof(buff),
10949 "#!constbyte",(options.stack_loc >> 16) & 0xff);
10950 /* if it has an offset then we need to compute it */
10951 /* emitcode ("subb", "a,#!constbyte", */
10952 /* -((sym->stack < 0) ? */
10953 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10954 /* ((short) sym->stack)) & 0xff); */
10955 /* emitcode ("mov","b,a"); */
10956 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10957 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10958 /* ((short) sym->stack)) >> 8) & 0xff); */
10960 emitcode ("mov", "a,_bpx");
10961 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
10962 ((char) (sym->stack - _G.nRegsSaved)) :
10963 ((char) sym->stack )) & 0xff);
10964 emitcode ("mov", "b,a");
10965 emitcode ("mov", "a,_bpx+1");
10967 offset = (((sym->stack < 0) ?
10968 ((short) (sym->stack - _G.nRegsSaved)) :
10969 ((short) sym->stack )) >> 8) & 0xff;
10971 emitcode ("addc","a,#!constbyte", offset);
10973 aopPut (AOP (IC_RESULT (ic)), "b", 0);
10974 aopPut (AOP (IC_RESULT (ic)), "a", 1);
10975 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10977 /* we can just move _bp */
10978 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10979 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10980 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10983 /* if it has an offset then we need to compute it */
10985 emitcode ("mov", "a,_bp");
10986 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10987 aopPut (AOP (IC_RESULT (ic)), "a", 0);
10989 /* we can just move _bp */
10990 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10992 /* fill the result with zero */
10993 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10996 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10998 "*** warning: pointer to stack var truncated.\n");
11003 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
11009 /* object not on stack then we need the name */
11010 size = AOP_SIZE (IC_RESULT (ic));
11015 char s[SDCC_NAME_MAX];
11019 tsprintf(s, sizeof(s), "#!his",sym->rname);
11022 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
11025 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
11027 default: /* should not need this (just in case) */
11028 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
11035 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11038 aopPut (AOP (IC_RESULT (ic)), s, offset++);
11042 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11046 #if 0 // obsolete, and buggy for != xdata
11047 /*-----------------------------------------------------------------*/
11048 /* genArrayInit - generates code for address of */
11049 /*-----------------------------------------------------------------*/
11051 genArrayInit (iCode * ic)
11053 literalList *iLoop;
11055 int elementSize = 0, eIndex;
11056 unsigned val, lastVal;
11058 operand *left=IC_LEFT(ic);
11060 D (emitcode (";", "genArrayInit "););
11062 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
11064 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
11066 // Load immediate value into DPTR.
11067 emitcode("mov", "dptr, %s",
11068 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
11070 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
11073 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11074 "Unexpected operand to genArrayInit.\n");
11077 // a regression because of SDCCcse.c:1.52
11078 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
11079 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
11080 if (options.model == MODEL_FLAT24)
11081 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
11085 type = operandType(IC_LEFT(ic));
11087 if (type && type->next)
11089 elementSize = getSize(type->next);
11093 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11094 "can't determine element size in genArrayInit.\n");
11098 iLoop = IC_ARRAYILIST(ic);
11103 bool firstpass = TRUE;
11105 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
11106 iLoop->count, (int)iLoop->literalValue, elementSize);
11112 symbol *tlbl = NULL;
11114 count = ix > 256 ? 256 : ix;
11118 tlbl = newiTempLabel (NULL);
11119 if (firstpass || (count & 0xff))
11121 emitcode("mov", "b, #!constbyte", count & 0xff);
11124 emitcode ("", "!tlabeldef", tlbl->key + 100);
11129 for (eIndex = 0; eIndex < elementSize; eIndex++)
11131 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
11132 if (val != lastVal)
11134 emitcode("mov", "a, #!constbyte", val);
11138 emitcode("movx", "@dptr, a");
11139 emitcode("inc", "dptr");
11144 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
11150 iLoop = iLoop->next;
11153 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
11157 /*-----------------------------------------------------------------*/
11158 /* genFarFarAssign - assignment when both are in far space */
11159 /*-----------------------------------------------------------------*/
11161 genFarFarAssign (operand * result, operand * right, iCode * ic)
11163 int size = AOP_SIZE (right);
11165 symbol *rSym = NULL;
11169 /* quick & easy case. */
11170 D(emitcode(";","genFarFarAssign (1 byte case)"););
11171 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
11172 freeAsmop (right, NULL, ic, FALSE);
11173 /* now assign DPTR to result */
11175 aopOp(result, ic, FALSE, FALSE);
11177 aopPut(AOP(result), "a", 0);
11178 freeAsmop(result, NULL, ic, FALSE);
11182 /* See if we've got an underlying symbol to abuse. */
11183 if (IS_SYMOP(result) && OP_SYMBOL(result))
11185 if (IS_TRUE_SYMOP(result))
11187 rSym = OP_SYMBOL(result);
11189 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
11191 rSym = OP_SYMBOL(result)->usl.spillLoc;
11195 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
11197 /* We can use the '390 auto-toggle feature to good effect here. */
11199 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
11200 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11201 emitcode ("mov", "dptr,#%s", rSym->rname);
11202 /* DP2 = result, DP1 = right, DP1 is current. */
11205 emitcode("movx", "a,@dptr");
11206 emitcode("movx", "@dptr,a");
11209 emitcode("inc", "dptr");
11210 emitcode("inc", "dptr");
11213 emitcode("mov", "dps,#0");
11214 freeAsmop (right, NULL, ic, FALSE);
11216 some alternative code for processors without auto-toggle
11217 no time to test now, so later well put in...kpb
11218 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
11219 emitcode("mov", "dps,#1"); /* Select DPTR2. */
11220 emitcode ("mov", "dptr,#%s", rSym->rname);
11221 /* DP2 = result, DP1 = right, DP1 is current. */
11225 emitcode("movx", "a,@dptr");
11227 emitcode("inc", "dptr");
11228 emitcode("inc", "dps");
11229 emitcode("movx", "@dptr,a");
11231 emitcode("inc", "dptr");
11232 emitcode("inc", "dps");
11234 emitcode("mov", "dps,#0");
11235 freeAsmop (right, NULL, ic, FALSE);
11240 D (emitcode (";", "genFarFarAssign"););
11241 aopOp (result, ic, TRUE, TRUE);
11243 _startLazyDPSEvaluation ();
11247 aopPut (AOP (result),
11248 aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
11251 _endLazyDPSEvaluation ();
11252 freeAsmop (result, NULL, ic, FALSE);
11253 freeAsmop (right, NULL, ic, FALSE);
11257 /*-----------------------------------------------------------------*/
11258 /* genAssign - generate code for assignment */
11259 /*-----------------------------------------------------------------*/
11261 genAssign (iCode * ic)
11263 operand *result, *right;
11265 unsigned long lit = 0L;
11267 D (emitcode (";", "genAssign ");
11270 result = IC_RESULT (ic);
11271 right = IC_RIGHT (ic);
11273 /* if they are the same */
11274 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11277 aopOp (right, ic, FALSE, FALSE);
11279 emitcode (";", "genAssign: resultIsFar = %s",
11280 isOperandInFarSpace (result) ?
11283 /* special case both in far space */
11284 if ((AOP_TYPE (right) == AOP_DPTR ||
11285 AOP_TYPE (right) == AOP_DPTR2) &&
11286 /* IS_TRUE_SYMOP(result) && */
11287 isOperandInFarSpace (result))
11289 genFarFarAssign (result, right, ic);
11293 aopOp (result, ic, TRUE, FALSE);
11295 /* if they are the same registers */
11296 if (sameRegs (AOP (right), AOP (result)))
11299 /* if the result is a bit */
11300 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
11302 /* if the right size is a literal then
11303 we know what the value is */
11304 if (AOP_TYPE (right) == AOP_LIT)
11306 if (((int) operandLitValue (right)))
11307 aopPut (AOP (result), one, 0);
11309 aopPut (AOP (result), zero, 0);
11313 /* the right is also a bit variable */
11314 if (AOP_TYPE (right) == AOP_CRY)
11316 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11317 aopPut (AOP (result), "c", 0);
11321 /* we need to or */
11323 aopPut (AOP (result), "a", 0);
11327 /* bit variables done */
11329 size = AOP_SIZE (result);
11331 if (AOP_TYPE (right) == AOP_LIT)
11332 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11335 (AOP_TYPE (result) != AOP_REG) &&
11336 (AOP_TYPE (right) == AOP_LIT) &&
11337 !IS_FLOAT (operandType (right)))
11339 _startLazyDPSEvaluation ();
11340 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
11342 aopPut (AOP (result),
11343 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11348 /* And now fill the rest with zeros. */
11351 emitcode ("clr", "a");
11355 aopPut (AOP (result), "a", offset++);
11357 _endLazyDPSEvaluation ();
11361 _startLazyDPSEvaluation ();
11364 aopPut (AOP (result),
11365 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11369 _endLazyDPSEvaluation ();
11373 freeAsmop (right, NULL, ic, FALSE);
11374 freeAsmop (result, NULL, ic, TRUE);
11377 /*-----------------------------------------------------------------*/
11378 /* genJumpTab - generates code for jump table */
11379 /*-----------------------------------------------------------------*/
11381 genJumpTab (iCode * ic)
11386 D (emitcode (";", "genJumpTab ");
11389 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11390 /* get the condition into accumulator */
11391 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11393 /* multiply by four! */
11394 emitcode ("add", "a,acc");
11395 emitcode ("add", "a,acc");
11396 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11398 jtab = newiTempLabel (NULL);
11399 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11400 emitcode ("jmp", "@a+dptr");
11401 emitcode ("", "!tlabeldef", jtab->key + 100);
11402 /* now generate the jump labels */
11403 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11404 jtab = setNextItem (IC_JTLABELS (ic)))
11405 emitcode ("ljmp", "!tlabel", jtab->key + 100);
11409 /*-----------------------------------------------------------------*/
11410 /* genCast - gen code for casting */
11411 /*-----------------------------------------------------------------*/
11413 genCast (iCode * ic)
11415 operand *result = IC_RESULT (ic);
11416 sym_link *ctype = operandType (IC_LEFT (ic));
11417 sym_link *rtype = operandType (IC_RIGHT (ic));
11418 operand *right = IC_RIGHT (ic);
11421 D (emitcode (";", "genCast "););
11423 /* if they are equivalent then do nothing */
11424 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11427 aopOp (right, ic, FALSE, AOP_IS_STR (result));
11428 aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
11430 /* if the result is a bit */
11431 if (IS_BITVAR (OP_SYMBOL (result)->type)
11432 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11434 /* if the right size is a literal then
11435 we know what the value is */
11436 if (AOP_TYPE (right) == AOP_LIT)
11438 if (((int) operandLitValue (right)))
11439 aopPut (AOP (result), one, 0);
11441 aopPut (AOP (result), zero, 0);
11446 /* the right is also a bit variable */
11447 if (AOP_TYPE (right) == AOP_CRY)
11449 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11450 aopPut (AOP (result), "c", 0);
11454 /* we need to or */
11456 aopPut (AOP (result), "a", 0);
11460 /* if they are the same size : or less */
11461 if (AOP_SIZE (result) <= AOP_SIZE (right))
11464 /* if they are in the same place */
11465 if (sameRegs (AOP (right), AOP (result)))
11468 /* if they in different places then copy */
11469 size = AOP_SIZE (result);
11471 _startLazyDPSEvaluation ();
11474 aopPut (AOP (result),
11475 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11479 _endLazyDPSEvaluation ();
11484 /* if the result is of type pointer */
11485 if (IS_PTR (ctype))
11489 sym_link *type = operandType (right);
11491 /* pointer to generic pointer */
11492 if (IS_GENPTR (ctype))
11496 p_type = DCL_TYPE (type);
11500 #if OLD_CAST_BEHAVIOR
11501 /* KV: we are converting a non-pointer type to
11502 * a generic pointer. This (ifdef'd out) code
11503 * says that the resulting generic pointer
11504 * should have the same class as the storage
11505 * location of the non-pointer variable.
11507 * For example, converting an int (which happens
11508 * to be stored in DATA space) to a pointer results
11509 * in a DATA generic pointer; if the original int
11510 * in XDATA space, so will be the resulting pointer.
11512 * I don't like that behavior, and thus this change:
11513 * all such conversions will be forced to XDATA and
11514 * throw a warning. If you want some non-XDATA
11515 * type, or you want to suppress the warning, you
11516 * must go through an intermediate cast, like so:
11518 * char _generic *gp = (char _xdata *)(intVar);
11520 sym_link *etype = getSpec (type);
11522 /* we have to go by the storage class */
11523 if (SPEC_OCLS (etype) != generic)
11525 p_type = PTR_TYPE (SPEC_OCLS (etype));
11530 /* Converting unknown class (i.e. register variable)
11531 * to generic pointer. This is not good, but
11532 * we'll make a guess (and throw a warning).
11535 werror (W_INT_TO_GEN_PTR_CAST);
11539 /* the first two bytes are known */
11540 size = GPTRSIZE - 1;
11542 _startLazyDPSEvaluation ();
11545 aopPut (AOP (result),
11546 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11550 _endLazyDPSEvaluation ();
11552 /* the last byte depending on type */
11554 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11559 // pointerTypeToGPByte will have bitched.
11563 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11564 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11569 /* just copy the pointers */
11570 size = AOP_SIZE (result);
11572 _startLazyDPSEvaluation ();
11575 aopPut (AOP (result),
11576 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11580 _endLazyDPSEvaluation ();
11584 /* so we now know that the size of destination is greater
11585 than the size of the source */
11586 /* we move to result for the size of source */
11587 size = AOP_SIZE (right);
11589 _startLazyDPSEvaluation ();
11592 aopPut (AOP (result),
11593 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11597 _endLazyDPSEvaluation ();
11599 /* now depending on the sign of the source && destination */
11600 size = AOP_SIZE (result) - AOP_SIZE (right);
11601 /* if unsigned or not an integral type */
11602 /* also, if the source is a bit, we don't need to sign extend, because
11603 * it can't possibly have set the sign bit.
11605 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11609 aopPut (AOP (result), zero, offset++);
11614 /* we need to extend the sign :{ */
11615 MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11616 FALSE, FALSE, NULL));
11617 emitcode ("rlc", "a");
11618 emitcode ("subb", "a,acc");
11620 aopPut (AOP (result), "a", offset++);
11623 /* we are done hurray !!!! */
11626 freeAsmop (right, NULL, ic, TRUE);
11627 freeAsmop (result, NULL, ic, TRUE);
11631 /*-----------------------------------------------------------------*/
11632 /* genDjnz - generate decrement & jump if not zero instrucion */
11633 /*-----------------------------------------------------------------*/
11635 genDjnz (iCode * ic, iCode * ifx)
11637 symbol *lbl, *lbl1;
11641 /* if the if condition has a false label
11642 then we cannot save */
11643 if (IC_FALSE (ifx))
11646 /* if the minus is not of the form
11648 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11649 !IS_OP_LITERAL (IC_RIGHT (ic)))
11652 if (operandLitValue (IC_RIGHT (ic)) != 1)
11655 /* if the size of this greater than one then no
11657 if (getSize (operandType (IC_RESULT (ic))) > 1)
11660 /* otherwise we can save BIG */
11661 D(emitcode(";", "genDjnz"););
11663 lbl = newiTempLabel (NULL);
11664 lbl1 = newiTempLabel (NULL);
11666 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11668 if (AOP_NEEDSACC(IC_RESULT(ic)))
11670 /* If the result is accessed indirectly via
11671 * the accumulator, we must explicitly write
11672 * it back after the decrement.
11674 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11676 if (strcmp(rByte, "a"))
11678 /* Something is hopelessly wrong */
11679 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11680 __FILE__, __LINE__);
11681 /* We can just give up; the generated code will be inefficient,
11682 * but what the hey.
11684 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11687 emitcode ("dec", "%s", rByte);
11688 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11689 emitcode ("jnz", "!tlabel", lbl->key + 100);
11691 else if (IS_AOP_PREG (IC_RESULT (ic)))
11693 emitcode ("dec", "%s",
11694 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11695 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11696 emitcode ("jnz", "!tlabel", lbl->key + 100);
11700 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11703 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11704 emitcode ("", "!tlabeldef", lbl->key + 100);
11705 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11706 emitcode ("", "!tlabeldef", lbl1->key + 100);
11708 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11709 ifx->generated = 1;
11713 /*-----------------------------------------------------------------*/
11714 /* genReceive - generate code for a receive iCode */
11715 /*-----------------------------------------------------------------*/
11717 genReceive (iCode * ic)
11719 int size = getSize (operandType (IC_RESULT (ic)));
11723 D (emitcode (";", "genReceive "););
11725 if (ic->argreg == 1)
11727 /* first parameter */
11728 if (AOP_IS_STR(IC_RESULT(ic)))
11730 /* Nothing to do: it's already in the proper place. */
11737 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11738 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11739 IS_TRUE_SYMOP (IC_RESULT (ic)));
11742 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11745 /* Sanity checking... */
11746 if (AOP_USESDPTR(IC_RESULT(ic)))
11748 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11749 "genReceive got unexpected DPTR.");
11751 assignResultValue (IC_RESULT (ic));
11756 /* second receive onwards */
11757 /* this gets a little tricky since unused recevies will be
11758 eliminated, we have saved the reg in the type field . and
11759 we use that to figure out which register to use */
11760 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11761 rb1off = ic->argreg;
11764 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11767 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11770 /*-----------------------------------------------------------------*/
11771 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11772 /*-----------------------------------------------------------------*/
11773 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11775 operand *from , *to , *count;
11780 /* we know it has to be 3 parameters */
11781 assert (nparms == 3);
11783 rsave = newBitVect(16);
11784 /* save DPTR if it needs to be saved */
11785 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11786 if (bitVectBitValue(ic->rMask,i))
11787 rsave = bitVectSetBit(rsave,i);
11789 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11790 ds390_rUmaskForOp (IC_RESULT(ic))));
11797 aopOp (from, ic->next, FALSE, FALSE);
11799 /* get from into DPTR1 */
11800 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11801 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11802 if (options.model == MODEL_FLAT24) {
11803 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11806 freeAsmop (from, NULL, ic, FALSE);
11807 aopOp (to, ic, FALSE, FALSE);
11808 /* get "to" into DPTR */
11809 /* if the operand is already in dptr
11810 then we do nothing else we move the value to dptr */
11811 if (AOP_TYPE (to) != AOP_STR) {
11812 /* if already in DPTR then we need to push */
11813 if (AOP_TYPE(to) == AOP_DPTR) {
11814 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11815 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11816 if (options.model == MODEL_FLAT24)
11817 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11818 emitcode ("pop", "dph");
11819 emitcode ("pop", "dpl");
11821 _startLazyDPSEvaluation ();
11822 /* if this is remateriazable */
11823 if (AOP_TYPE (to) == AOP_IMMD) {
11824 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11825 } else { /* we need to get it byte by byte */
11826 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11827 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11828 if (options.model == MODEL_FLAT24) {
11829 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11832 _endLazyDPSEvaluation ();
11835 freeAsmop (to, NULL, ic, FALSE);
11836 _G.dptrInUse = _G.dptr1InUse = 1;
11837 aopOp (count, ic->next->next, FALSE,FALSE);
11838 lbl =newiTempLabel(NULL);
11840 /* now for the actual copy */
11841 if (AOP_TYPE(count) == AOP_LIT &&
11842 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11843 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11845 emitcode ("lcall","__bi_memcpyc2x_s");
11847 emitcode ("lcall","__bi_memcpyx2x_s");
11849 freeAsmop (count, NULL, ic, FALSE);
11851 symbol *lbl1 = newiTempLabel(NULL);
11853 emitcode (";"," Auto increment but no djnz");
11854 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11855 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11856 freeAsmop (count, NULL, ic, FALSE);
11857 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11858 emitcode ("","!tlabeldef",lbl->key+100);
11860 emitcode ("clr","a");
11861 emitcode ("movc", "a,@a+dptr");
11863 emitcode ("movx", "a,@dptr");
11864 emitcode ("movx", "@dptr,a");
11865 emitcode ("inc", "dptr");
11866 emitcode ("inc", "dptr");
11867 emitcode ("mov","a,b");
11868 emitcode ("orl","a,_ap");
11869 emitcode ("jz","!tlabel",lbl1->key+100);
11870 emitcode ("mov","a,_ap");
11871 emitcode ("add","a,#!constbyte",0xFF);
11872 emitcode ("mov","_ap,a");
11873 emitcode ("mov","a,b");
11874 emitcode ("addc","a,#!constbyte",0xFF);
11875 emitcode ("mov","b,a");
11876 emitcode ("sjmp","!tlabel",lbl->key+100);
11877 emitcode ("","!tlabeldef",lbl1->key+100);
11879 emitcode ("mov", "dps,#0");
11880 _G.dptrInUse = _G.dptr1InUse = 0;
11881 unsavermask(rsave);
11885 /*-----------------------------------------------------------------*/
11886 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
11887 /*-----------------------------------------------------------------*/
11888 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11890 operand *from , *to , *count;
11895 /* we know it has to be 3 parameters */
11896 assert (nparms == 3);
11898 rsave = newBitVect(16);
11899 /* save DPTR if it needs to be saved */
11900 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11901 if (bitVectBitValue(ic->rMask,i))
11902 rsave = bitVectSetBit(rsave,i);
11904 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11905 ds390_rUmaskForOp (IC_RESULT(ic))));
11912 aopOp (from, ic->next, FALSE, FALSE);
11914 /* get from into DPTR1 */
11915 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11916 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11917 if (options.model == MODEL_FLAT24) {
11918 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11921 freeAsmop (from, NULL, ic, FALSE);
11922 aopOp (to, ic, FALSE, FALSE);
11923 /* get "to" into DPTR */
11924 /* if the operand is already in dptr
11925 then we do nothing else we move the value to dptr */
11926 if (AOP_TYPE (to) != AOP_STR) {
11927 /* if already in DPTR then we need to push */
11928 if (AOP_TYPE(to) == AOP_DPTR) {
11929 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11930 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11931 if (options.model == MODEL_FLAT24)
11932 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11933 emitcode ("pop", "dph");
11934 emitcode ("pop", "dpl");
11936 _startLazyDPSEvaluation ();
11937 /* if this is remateriazable */
11938 if (AOP_TYPE (to) == AOP_IMMD) {
11939 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11940 } else { /* we need to get it byte by byte */
11941 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11942 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11943 if (options.model == MODEL_FLAT24) {
11944 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11947 _endLazyDPSEvaluation ();
11950 freeAsmop (to, NULL, ic, FALSE);
11951 _G.dptrInUse = _G.dptr1InUse = 1;
11952 aopOp (count, ic->next->next, FALSE,FALSE);
11953 lbl =newiTempLabel(NULL);
11954 lbl2 =newiTempLabel(NULL);
11956 /* now for the actual compare */
11957 if (AOP_TYPE(count) == AOP_LIT &&
11958 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11959 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11961 emitcode("lcall","__bi_memcmpc2x_s");
11963 emitcode("lcall","__bi_memcmpx2x_s");
11964 freeAsmop (count, NULL, ic, FALSE);
11965 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11966 aopPut(AOP(IC_RESULT(ic)),"a",0);
11967 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11969 symbol *lbl1 = newiTempLabel(NULL);
11971 emitcode("push","ar0");
11972 emitcode (";"," Auto increment but no djnz");
11973 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11974 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11975 freeAsmop (count, NULL, ic, FALSE);
11976 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11977 emitcode ("","!tlabeldef",lbl->key+100);
11979 emitcode ("clr","a");
11980 emitcode ("movc", "a,@a+dptr");
11982 emitcode ("movx", "a,@dptr");
11983 emitcode ("mov","r0,a");
11984 emitcode ("movx", "a,@dptr");
11985 emitcode ("clr","c");
11986 emitcode ("subb","a,r0");
11987 emitcode ("jnz","!tlabel",lbl2->key+100);
11988 emitcode ("inc", "dptr");
11989 emitcode ("inc", "dptr");
11990 emitcode ("mov","a,b");
11991 emitcode ("orl","a,_ap");
11992 emitcode ("jz","!tlabel",lbl1->key+100);
11993 emitcode ("mov","a,_ap");
11994 emitcode ("add","a,#!constbyte",0xFF);
11995 emitcode ("mov","_ap,a");
11996 emitcode ("mov","a,b");
11997 emitcode ("addc","a,#!constbyte",0xFF);
11998 emitcode ("mov","b,a");
11999 emitcode ("sjmp","!tlabel",lbl->key+100);
12000 emitcode ("","!tlabeldef",lbl1->key+100);
12001 emitcode ("clr","a");
12002 emitcode ("","!tlabeldef",lbl2->key+100);
12003 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12004 aopPut(AOP(IC_RESULT(ic)),"a",0);
12005 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12006 emitcode("pop","ar0");
12007 emitcode ("mov", "dps,#0");
12009 _G.dptrInUse = _G.dptr1InUse = 0;
12010 unsavermask(rsave);
12014 /*-----------------------------------------------------------------*/
12015 /* genInp - gen code for __builtin_inp read data from a mem mapped */
12016 /* port, first parameter output area second parameter pointer to */
12017 /* port third parameter count */
12018 /*-----------------------------------------------------------------*/
12019 static void genInp( iCode *ic, int nparms, operand **parms)
12021 operand *from , *to , *count;
12026 /* we know it has to be 3 parameters */
12027 assert (nparms == 3);
12029 rsave = newBitVect(16);
12030 /* save DPTR if it needs to be saved */
12031 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12032 if (bitVectBitValue(ic->rMask,i))
12033 rsave = bitVectSetBit(rsave,i);
12035 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12036 ds390_rUmaskForOp (IC_RESULT(ic))));
12043 aopOp (from, ic->next, FALSE, FALSE);
12045 /* get from into DPTR1 */
12046 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12047 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12048 if (options.model == MODEL_FLAT24) {
12049 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12052 freeAsmop (from, NULL, ic, FALSE);
12053 aopOp (to, ic, FALSE, FALSE);
12054 /* get "to" into DPTR */
12055 /* if the operand is already in dptr
12056 then we do nothing else we move the value to dptr */
12057 if (AOP_TYPE (to) != AOP_STR) {
12058 /* if already in DPTR then we need to push */
12059 if (AOP_TYPE(to) == AOP_DPTR) {
12060 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12061 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12062 if (options.model == MODEL_FLAT24)
12063 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12064 emitcode ("pop", "dph");
12065 emitcode ("pop", "dpl");
12067 _startLazyDPSEvaluation ();
12068 /* if this is remateriazable */
12069 if (AOP_TYPE (to) == AOP_IMMD) {
12070 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12071 } else { /* we need to get it byte by byte */
12072 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12073 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12074 if (options.model == MODEL_FLAT24) {
12075 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12078 _endLazyDPSEvaluation ();
12081 freeAsmop (to, NULL, ic, FALSE);
12083 _G.dptrInUse = _G.dptr1InUse = 1;
12084 aopOp (count, ic->next->next, FALSE,FALSE);
12085 lbl =newiTempLabel(NULL);
12087 /* now for the actual copy */
12088 if (AOP_TYPE(count) == AOP_LIT &&
12089 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12090 emitcode (";","OH JOY auto increment with djnz (very fast)");
12091 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12092 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12093 freeAsmop (count, NULL, ic, FALSE);
12094 emitcode ("","!tlabeldef",lbl->key+100);
12095 emitcode ("movx", "a,@dptr"); /* read data from port */
12096 emitcode ("dec","dps"); /* switch to DPTR */
12097 emitcode ("movx", "@dptr,a"); /* save into location */
12098 emitcode ("inc", "dptr"); /* point to next area */
12099 emitcode ("inc","dps"); /* switch to DPTR2 */
12100 emitcode ("djnz","b,!tlabel",lbl->key+100);
12102 symbol *lbl1 = newiTempLabel(NULL);
12104 emitcode (";"," Auto increment but no djnz");
12105 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12106 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12107 freeAsmop (count, NULL, ic, FALSE);
12108 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12109 emitcode ("","!tlabeldef",lbl->key+100);
12110 emitcode ("movx", "a,@dptr");
12111 emitcode ("dec","dps"); /* switch to DPTR */
12112 emitcode ("movx", "@dptr,a");
12113 emitcode ("inc", "dptr");
12114 emitcode ("inc","dps"); /* switch to DPTR2 */
12115 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
12116 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
12117 emitcode ("mov","a,b");
12118 emitcode ("orl","a,_ap");
12119 emitcode ("jz","!tlabel",lbl1->key+100);
12120 emitcode ("mov","a,_ap");
12121 emitcode ("add","a,#!constbyte",0xFF);
12122 emitcode ("mov","_ap,a");
12123 emitcode ("mov","a,b");
12124 emitcode ("addc","a,#!constbyte",0xFF);
12125 emitcode ("mov","b,a");
12126 emitcode ("sjmp","!tlabel",lbl->key+100);
12127 emitcode ("","!tlabeldef",lbl1->key+100);
12129 emitcode ("mov", "dps,#0");
12130 _G.dptrInUse = _G.dptr1InUse = 0;
12131 unsavermask(rsave);
12135 /*-----------------------------------------------------------------*/
12136 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
12137 /* port, first parameter output area second parameter pointer to */
12138 /* port third parameter count */
12139 /*-----------------------------------------------------------------*/
12140 static void genOutp( iCode *ic, int nparms, operand **parms)
12142 operand *from , *to , *count;
12147 /* we know it has to be 3 parameters */
12148 assert (nparms == 3);
12150 rsave = newBitVect(16);
12151 /* save DPTR if it needs to be saved */
12152 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12153 if (bitVectBitValue(ic->rMask,i))
12154 rsave = bitVectSetBit(rsave,i);
12156 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12157 ds390_rUmaskForOp (IC_RESULT(ic))));
12164 aopOp (from, ic->next, FALSE, FALSE);
12166 /* get from into DPTR1 */
12167 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12168 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12169 if (options.model == MODEL_FLAT24) {
12170 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12173 freeAsmop (from, NULL, ic, FALSE);
12174 aopOp (to, ic, FALSE, FALSE);
12175 /* get "to" into DPTR */
12176 /* if the operand is already in dptr
12177 then we do nothing else we move the value to dptr */
12178 if (AOP_TYPE (to) != AOP_STR) {
12179 /* if already in DPTR then we need to push */
12180 if (AOP_TYPE(to) == AOP_DPTR) {
12181 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12182 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12183 if (options.model == MODEL_FLAT24)
12184 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12185 emitcode ("pop", "dph");
12186 emitcode ("pop", "dpl");
12188 _startLazyDPSEvaluation ();
12189 /* if this is remateriazable */
12190 if (AOP_TYPE (to) == AOP_IMMD) {
12191 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12192 } else { /* we need to get it byte by byte */
12193 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12194 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12195 if (options.model == MODEL_FLAT24) {
12196 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12199 _endLazyDPSEvaluation ();
12202 freeAsmop (to, NULL, ic, FALSE);
12204 _G.dptrInUse = _G.dptr1InUse = 1;
12205 aopOp (count, ic->next->next, FALSE,FALSE);
12206 lbl =newiTempLabel(NULL);
12208 /* now for the actual copy */
12209 if (AOP_TYPE(count) == AOP_LIT &&
12210 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12211 emitcode (";","OH JOY auto increment with djnz (very fast)");
12212 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12213 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12214 emitcode ("","!tlabeldef",lbl->key+100);
12215 emitcode ("movx", "a,@dptr"); /* read data from port */
12216 emitcode ("inc","dps"); /* switch to DPTR2 */
12217 emitcode ("movx", "@dptr,a"); /* save into location */
12218 emitcode ("inc", "dptr"); /* point to next area */
12219 emitcode ("dec","dps"); /* switch to DPTR */
12220 emitcode ("djnz","b,!tlabel",lbl->key+100);
12221 freeAsmop (count, NULL, ic, FALSE);
12223 symbol *lbl1 = newiTempLabel(NULL);
12225 emitcode (";"," Auto increment but no djnz");
12226 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12227 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12228 freeAsmop (count, NULL, ic, FALSE);
12229 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12230 emitcode ("","!tlabeldef",lbl->key+100);
12231 emitcode ("movx", "a,@dptr");
12232 emitcode ("inc", "dptr");
12233 emitcode ("inc","dps"); /* switch to DPTR2 */
12234 emitcode ("movx", "@dptr,a");
12235 emitcode ("dec","dps"); /* switch to DPTR */
12236 emitcode ("mov","a,b");
12237 emitcode ("orl","a,_ap");
12238 emitcode ("jz","!tlabel",lbl1->key+100);
12239 emitcode ("mov","a,_ap");
12240 emitcode ("add","a,#!constbyte",0xFF);
12241 emitcode ("mov","_ap,a");
12242 emitcode ("mov","a,b");
12243 emitcode ("addc","a,#!constbyte",0xFF);
12244 emitcode ("mov","b,a");
12245 emitcode ("sjmp","!tlabel",lbl->key+100);
12246 emitcode ("","!tlabeldef",lbl1->key+100);
12248 emitcode ("mov", "dps,#0");
12249 _G.dptrInUse = _G.dptr1InUse = 0;
12250 unsavermask(rsave);
12254 /*-----------------------------------------------------------------*/
12255 /* genSwapW - swap lower & high order bytes */
12256 /*-----------------------------------------------------------------*/
12257 static void genSwapW(iCode *ic, int nparms, operand **parms)
12261 assert (nparms==1);
12264 dest=IC_RESULT(ic);
12266 assert(getSize(operandType(src))==2);
12268 aopOp (src, ic, FALSE, FALSE);
12269 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
12271 MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
12273 freeAsmop (src, NULL, ic, FALSE);
12275 aopOp (dest,ic, FALSE, FALSE);
12276 aopPut(AOP(dest),"b",0);
12277 aopPut(AOP(dest),"a",1);
12278 freeAsmop (dest, NULL, ic, FALSE);
12281 /*-----------------------------------------------------------------*/
12282 /* genMemsetX - gencode for memSetX data */
12283 /*-----------------------------------------------------------------*/
12284 static void genMemsetX(iCode *ic, int nparms, operand **parms)
12286 operand *to , *val , *count;
12292 /* we know it has to be 3 parameters */
12293 assert (nparms == 3);
12299 /* save DPTR if it needs to be saved */
12300 rsave = newBitVect(16);
12301 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12302 if (bitVectBitValue(ic->rMask,i))
12303 rsave = bitVectSetBit(rsave,i);
12305 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12306 ds390_rUmaskForOp (IC_RESULT(ic))));
12309 aopOp (to, ic, FALSE, FALSE);
12310 /* get "to" into DPTR */
12311 /* if the operand is already in dptr
12312 then we do nothing else we move the value to dptr */
12313 if (AOP_TYPE (to) != AOP_STR) {
12314 /* if already in DPTR then we need to push */
12315 if (AOP_TYPE(to) == AOP_DPTR) {
12316 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12317 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12318 if (options.model == MODEL_FLAT24)
12319 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12320 emitcode ("pop", "dph");
12321 emitcode ("pop", "dpl");
12323 _startLazyDPSEvaluation ();
12324 /* if this is remateriazable */
12325 if (AOP_TYPE (to) == AOP_IMMD) {
12326 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12327 } else { /* we need to get it byte by byte */
12328 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12329 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12330 if (options.model == MODEL_FLAT24) {
12331 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12334 _endLazyDPSEvaluation ();
12337 freeAsmop (to, NULL, ic, FALSE);
12339 aopOp (val, ic->next->next, FALSE,FALSE);
12340 aopOp (count, ic->next->next, FALSE,FALSE);
12341 lbl =newiTempLabel(NULL);
12342 /* now for the actual copy */
12343 if (AOP_TYPE(count) == AOP_LIT &&
12344 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12345 l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
12346 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12348 emitcode ("","!tlabeldef",lbl->key+100);
12349 emitcode ("movx", "@dptr,a");
12350 emitcode ("inc", "dptr");
12351 emitcode ("djnz","b,!tlabel",lbl->key+100);
12353 symbol *lbl1 = newiTempLabel(NULL);
12355 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12356 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12357 emitcode ("","!tlabeldef",lbl->key+100);
12358 MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
12359 emitcode ("movx", "@dptr,a");
12360 emitcode ("inc", "dptr");
12361 emitcode ("mov","a,b");
12362 emitcode ("orl","a,_ap");
12363 emitcode ("jz","!tlabel",lbl1->key+100);
12364 emitcode ("mov","a,_ap");
12365 emitcode ("add","a,#!constbyte",0xFF);
12366 emitcode ("mov","_ap,a");
12367 emitcode ("mov","a,b");
12368 emitcode ("addc","a,#!constbyte",0xFF);
12369 emitcode ("mov","b,a");
12370 emitcode ("sjmp","!tlabel",lbl->key+100);
12371 emitcode ("","!tlabeldef",lbl1->key+100);
12373 freeAsmop (count, NULL, ic, FALSE);
12374 unsavermask(rsave);
12377 /*-----------------------------------------------------------------*/
12378 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12379 /*-----------------------------------------------------------------*/
12380 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12383 operand *pnum, *result;
12386 assert (nparms==1);
12387 /* save registers that need to be saved */
12388 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12389 ds390_rUmaskForOp (IC_RESULT(ic))));
12392 aopOp (pnum, ic, FALSE, FALSE);
12393 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12394 freeAsmop (pnum, NULL, ic, FALSE);
12395 emitcode ("lcall","NatLib_LoadPrimitive");
12396 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12397 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
12398 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12399 for (i = (size-1) ; i >= 0 ; i-- ) {
12400 emitcode ("push","a%s",javaRet[i]);
12402 for (i=0; i < size ; i++ ) {
12403 emitcode ("pop","a%s",
12404 aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12407 for (i = 0 ; i < size ; i++ ) {
12408 aopPut(AOP(result),javaRet[i],i);
12411 freeAsmop (result, NULL, ic, FALSE);
12412 unsavermask(rsave);
12415 /*-----------------------------------------------------------------*/
12416 /* genNatLibLoadPointer - calls TINI api function to load pointer */
12417 /*-----------------------------------------------------------------*/
12418 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12421 operand *pnum, *result;
12425 assert (nparms==1);
12426 /* save registers that need to be saved */
12427 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12428 ds390_rUmaskForOp (IC_RESULT(ic))));
12431 aopOp (pnum, ic, FALSE, FALSE);
12432 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12433 freeAsmop (pnum, NULL, ic, FALSE);
12434 emitcode ("lcall","NatLib_LoadPointer");
12435 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12436 if (AOP_TYPE(result)!=AOP_STR) {
12437 for (i = 0 ; i < size ; i++ ) {
12438 aopPut(AOP(result),fReturn[i],i);
12441 freeAsmop (result, NULL, ic, FALSE);
12442 unsavermask(rsave);
12445 /*-----------------------------------------------------------------*/
12446 /* genNatLibInstallStateBlock - */
12447 /*-----------------------------------------------------------------*/
12448 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
12449 operand **parms, const char *name)
12452 operand *psb, *handle;
12453 assert (nparms==2);
12455 /* save registers that need to be saved */
12456 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12457 ds390_rUmaskForOp (IC_RESULT(ic))));
12461 /* put pointer to state block into DPTR1 */
12462 aopOp (psb, ic, FALSE, FALSE);
12463 if (AOP_TYPE (psb) == AOP_IMMD) {
12464 emitcode ("mov","dps,#1");
12465 emitcode ("mov", "dptr,%s",
12466 aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12467 emitcode ("mov","dps,#0");
12469 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12470 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12471 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12473 freeAsmop (psb, NULL, ic, FALSE);
12475 /* put libraryID into DPTR */
12476 emitcode ("mov","dptr,#LibraryID");
12478 /* put handle into r3:r2 */
12479 aopOp (handle, ic, FALSE, FALSE);
12480 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12481 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12482 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12483 emitcode ("pop","ar3");
12484 emitcode ("pop","ar2");
12486 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12487 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12489 freeAsmop (psb, NULL, ic, FALSE);
12491 /* make the call */
12492 emitcode ("lcall","NatLib_Install%sStateBlock",name);
12494 /* put return value into place*/
12496 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12498 aopPut(AOP(IC_RESULT(ic)),"a",0);
12499 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12500 unsavermask(rsave);
12503 /*-----------------------------------------------------------------*/
12504 /* genNatLibRemoveStateBlock - */
12505 /*-----------------------------------------------------------------*/
12506 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12512 /* save registers that need to be saved */
12513 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12514 ds390_rUmaskForOp (IC_RESULT(ic))));
12516 /* put libraryID into DPTR */
12517 emitcode ("mov","dptr,#LibraryID");
12518 /* make the call */
12519 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12520 unsavermask(rsave);
12523 /*-----------------------------------------------------------------*/
12524 /* genNatLibGetStateBlock - */
12525 /*-----------------------------------------------------------------*/
12526 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12527 operand **parms,const char *name)
12530 symbol *lbl = newiTempLabel(NULL);
12533 /* save registers that need to be saved */
12534 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12535 ds390_rUmaskForOp (IC_RESULT(ic))));
12537 /* put libraryID into DPTR */
12538 emitcode ("mov","dptr,#LibraryID");
12539 /* make the call */
12540 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12541 emitcode ("jnz","!tlabel",lbl->key+100);
12543 /* put return value into place */
12544 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12545 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12546 emitcode ("push","ar3");
12547 emitcode ("push","ar2");
12548 emitcode ("pop","%s",
12549 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12550 emitcode ("pop","%s",
12551 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12553 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12554 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12556 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12557 emitcode ("","!tlabeldef",lbl->key+100);
12558 unsavermask(rsave);
12561 /*-----------------------------------------------------------------*/
12562 /* genMMMalloc - */
12563 /*-----------------------------------------------------------------*/
12564 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12565 int size, const char *name)
12570 symbol *lbl = newiTempLabel(NULL);
12572 assert (nparms == 1);
12573 /* save registers that need to be saved */
12574 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12575 ds390_rUmaskForOp (IC_RESULT(ic))));
12578 aopOp (bsize,ic,FALSE,FALSE);
12580 /* put the size in R4-R2 */
12581 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12582 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12583 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12585 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12586 emitcode("pop","ar4");
12588 emitcode("pop","ar3");
12589 emitcode("pop","ar2");
12591 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12592 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12594 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12597 freeAsmop (bsize, NULL, ic, FALSE);
12599 /* make the call */
12600 emitcode ("lcall","MM_%s",name);
12601 emitcode ("jz","!tlabel",lbl->key+100);
12602 emitcode ("mov","r2,#!constbyte",0xff);
12603 emitcode ("mov","r3,#!constbyte",0xff);
12604 emitcode ("","!tlabeldef",lbl->key+100);
12605 /* we don't care about the pointer : we just save the handle */
12606 rsym = OP_SYMBOL(IC_RESULT(ic));
12607 if (rsym->liveFrom != rsym->liveTo) {
12608 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12609 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12610 emitcode ("push","ar3");
12611 emitcode ("push","ar2");
12612 emitcode ("pop","%s",
12613 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12614 emitcode ("pop","%s",
12615 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12617 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12618 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12620 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12622 unsavermask(rsave);
12625 /*-----------------------------------------------------------------*/
12627 /*-----------------------------------------------------------------*/
12628 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12633 assert (nparms == 1);
12634 /* save registers that need to be saved */
12635 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12636 ds390_rUmaskForOp (IC_RESULT(ic))));
12639 aopOp (handle,ic,FALSE,FALSE);
12641 /* put the size in R4-R2 */
12642 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12643 emitcode("push","%s",
12644 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12645 emitcode("push","%s",
12646 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12647 emitcode("pop","ar3");
12648 emitcode("pop","ar2");
12650 emitcode ("mov","r2,%s",
12651 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12652 emitcode ("mov","r3,%s",
12653 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12655 freeAsmop (handle, NULL, ic, FALSE);
12657 /* make the call */
12658 emitcode ("lcall","MM_Deref");
12661 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12662 if (rsym->liveFrom != rsym->liveTo) {
12663 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12664 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12665 _startLazyDPSEvaluation ();
12667 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12668 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12669 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12671 _endLazyDPSEvaluation ();
12676 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12677 unsavermask(rsave);
12680 /*-----------------------------------------------------------------*/
12681 /* genMMUnrestrictedPersist - */
12682 /*-----------------------------------------------------------------*/
12683 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12688 assert (nparms == 1);
12689 /* save registers that need to be saved */
12690 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12691 ds390_rUmaskForOp (IC_RESULT(ic))));
12694 aopOp (handle,ic,FALSE,FALSE);
12696 /* put the size in R3-R2 */
12697 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12698 emitcode("push","%s",
12699 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12700 emitcode("push","%s",
12701 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12702 emitcode("pop","ar3");
12703 emitcode("pop","ar2");
12705 emitcode ("mov","r2,%s",
12706 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12707 emitcode ("mov","r3,%s",
12708 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12710 freeAsmop (handle, NULL, ic, FALSE);
12712 /* make the call */
12713 emitcode ("lcall","MM_UnrestrictedPersist");
12716 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12717 if (rsym->liveFrom != rsym->liveTo) {
12718 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12719 aopPut(AOP(IC_RESULT(ic)),"a",0);
12720 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12723 unsavermask(rsave);
12726 /*-----------------------------------------------------------------*/
12727 /* genSystemExecJavaProcess - */
12728 /*-----------------------------------------------------------------*/
12729 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12732 operand *handle, *pp;
12734 assert (nparms==2);
12735 /* save registers that need to be saved */
12736 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12737 ds390_rUmaskForOp (IC_RESULT(ic))));
12742 /* put the handle in R3-R2 */
12743 aopOp (handle,ic,FALSE,FALSE);
12744 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12745 emitcode("push","%s",
12746 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12747 emitcode("push","%s",
12748 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12749 emitcode("pop","ar3");
12750 emitcode("pop","ar2");
12752 emitcode ("mov","r2,%s",
12753 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12754 emitcode ("mov","r3,%s",
12755 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12757 freeAsmop (handle, NULL, ic, FALSE);
12759 /* put pointer in DPTR */
12760 aopOp (pp,ic,FALSE,FALSE);
12761 if (AOP_TYPE(pp) == AOP_IMMD) {
12762 emitcode ("mov", "dptr,%s",
12763 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12764 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12765 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12766 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12767 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12769 freeAsmop (handle, NULL, ic, FALSE);
12771 /* make the call */
12772 emitcode ("lcall","System_ExecJavaProcess");
12774 /* put result in place */
12776 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12777 if (rsym->liveFrom != rsym->liveTo) {
12778 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12779 aopPut(AOP(IC_RESULT(ic)),"a",0);
12780 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12784 unsavermask(rsave);
12787 /*-----------------------------------------------------------------*/
12788 /* genSystemRTCRegisters - */
12789 /*-----------------------------------------------------------------*/
12790 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12796 assert (nparms==1);
12797 /* save registers that need to be saved */
12798 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12799 ds390_rUmaskForOp (IC_RESULT(ic))));
12802 /* put pointer in DPTR */
12803 aopOp (pp,ic,FALSE,FALSE);
12804 if (AOP_TYPE (pp) == AOP_IMMD) {
12805 emitcode ("mov","dps,#1");
12806 emitcode ("mov", "dptr,%s",
12807 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12808 emitcode ("mov","dps,#0");
12810 emitcode ("mov","dpl1,%s",
12811 aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12812 emitcode ("mov","dph1,%s",
12813 aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12814 emitcode ("mov","dpx1,%s",
12815 aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12817 freeAsmop (pp, NULL, ic, FALSE);
12819 /* make the call */
12820 emitcode ("lcall","System_%sRTCRegisters",name);
12822 unsavermask(rsave);
12825 /*-----------------------------------------------------------------*/
12826 /* genSystemThreadSleep - */
12827 /*-----------------------------------------------------------------*/
12828 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12833 assert (nparms==1);
12834 /* save registers that need to be saved */
12835 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12836 ds390_rUmaskForOp (IC_RESULT(ic))));
12839 aopOp(to,ic,FALSE,FALSE);
12840 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12841 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12842 emitcode ("push","%s",
12843 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12844 emitcode ("push","%s",
12845 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12846 emitcode ("push","%s",
12847 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12848 emitcode ("push","%s",
12849 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12850 emitcode ("pop","ar3");
12851 emitcode ("pop","ar2");
12852 emitcode ("pop","ar1");
12853 emitcode ("pop","ar0");
12855 emitcode ("mov","r0,%s",
12856 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12857 emitcode ("mov","r1,%s",
12858 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12859 emitcode ("mov","r2,%s",
12860 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12861 emitcode ("mov","r3,%s",
12862 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12864 freeAsmop (to, NULL, ic, FALSE);
12866 /* suspend in acc */
12868 aopOp(s,ic,FALSE,FALSE);
12869 emitcode ("mov","a,%s",
12870 aopGet(AOP(s),0,FALSE,TRUE,NULL));
12871 freeAsmop (s, NULL, ic, FALSE);
12873 /* make the call */
12874 emitcode ("lcall","System_%s",name);
12876 unsavermask(rsave);
12879 /*-----------------------------------------------------------------*/
12880 /* genSystemThreadResume - */
12881 /*-----------------------------------------------------------------*/
12882 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12887 assert (nparms==2);
12888 /* save registers that need to be saved */
12889 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12890 ds390_rUmaskForOp (IC_RESULT(ic))));
12896 aopOp(pid,ic,FALSE,FALSE);
12897 emitcode ("mov","r0,%s",
12898 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12899 freeAsmop (pid, NULL, ic, FALSE);
12902 aopOp(tid,ic,FALSE,FALSE);
12903 emitcode ("mov","a,%s",
12904 aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12905 freeAsmop (tid, NULL, ic, FALSE);
12907 emitcode ("lcall","System_ThreadResume");
12909 /* put result into place */
12911 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12912 if (rsym->liveFrom != rsym->liveTo) {
12913 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12914 aopPut(AOP(IC_RESULT(ic)),"a",0);
12915 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12918 unsavermask(rsave);
12921 /*-----------------------------------------------------------------*/
12922 /* genSystemProcessResume - */
12923 /*-----------------------------------------------------------------*/
12924 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12929 assert (nparms==1);
12930 /* save registers that need to be saved */
12931 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12932 ds390_rUmaskForOp (IC_RESULT(ic))));
12937 aopOp(pid,ic,FALSE,FALSE);
12938 emitcode ("mov","a,%s",
12939 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12940 freeAsmop (pid, NULL, ic, FALSE);
12942 emitcode ("lcall","System_ProcessResume");
12944 unsavermask(rsave);
12947 /*-----------------------------------------------------------------*/
12949 /*-----------------------------------------------------------------*/
12950 static void genSystem (iCode *ic,int nparms,char *name)
12952 assert(nparms == 0);
12954 emitcode ("lcall","System_%s",name);
12957 /*-----------------------------------------------------------------*/
12958 /* genSystemPoll - */
12959 /*-----------------------------------------------------------------*/
12960 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12965 assert (nparms==1);
12966 /* save registers that need to be saved */
12967 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12968 ds390_rUmaskForOp (IC_RESULT(ic))));
12971 aopOp (fp,ic,FALSE,FALSE);
12972 if (AOP_TYPE (fp) == AOP_IMMD) {
12973 emitcode ("mov", "dptr,%s",
12974 aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12975 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12976 emitcode ("mov","dpl,%s",
12977 aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12978 emitcode ("mov","dph,%s",
12979 aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12980 emitcode ("mov","dpx,%s",
12981 aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12983 freeAsmop (fp, NULL, ic, FALSE);
12985 emitcode ("lcall","System_%sPoll",name);
12987 /* put result into place */
12989 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12990 if (rsym->liveFrom != rsym->liveTo) {
12991 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12992 aopPut(AOP(IC_RESULT(ic)),"a",0);
12993 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12996 unsavermask(rsave);
12999 /*-----------------------------------------------------------------*/
13000 /* genSystemGetCurrentID - */
13001 /*-----------------------------------------------------------------*/
13002 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
13004 assert (nparms==0);
13006 emitcode ("lcall","System_GetCurrent%sId",name);
13007 /* put result into place */
13009 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13010 if (rsym->liveFrom != rsym->liveTo) {
13011 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13012 aopPut(AOP(IC_RESULT(ic)),"a",0);
13013 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13018 /*-----------------------------------------------------------------*/
13019 /* genDummyRead - generate code for dummy read of volatiles */
13020 /*-----------------------------------------------------------------*/
13022 genDummyRead (iCode * ic)
13027 D(emitcode("; genDummyRead",""));
13029 op = IC_RIGHT (ic);
13030 if (op && IS_SYMOP (op))
13032 aopOp (op, ic, FALSE, FALSE);
13034 /* if the result is a bit */
13035 if (AOP_TYPE (op) == AOP_CRY)
13036 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13039 /* bit variables done */
13041 size = AOP_SIZE (op);
13045 MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13050 freeAsmop (op, NULL, ic, TRUE);
13054 if (op && IS_SYMOP (op))
13056 aopOp (op, ic, FALSE, FALSE);
13058 /* if the result is a bit */
13059 if (AOP_TYPE (op) == AOP_CRY)
13060 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13063 /* bit variables done */
13065 size = AOP_SIZE (op);
13069 MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13074 freeAsmop (op, NULL, ic, TRUE);
13079 /*-----------------------------------------------------------------*/
13080 /* genCritical - generate code for start of a critical sequence */
13081 /*-----------------------------------------------------------------*/
13083 genCritical (iCode *ic)
13085 symbol *tlbl = newiTempLabel (NULL);
13087 D(emitcode("; genCritical",""));
13089 if (IC_RESULT (ic))
13090 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
13092 emitcode ("setb", "c");
13093 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
13094 emitcode ("clr", "c");
13095 emitcode ("", "%05d$:", (tlbl->key + 100));
13097 if (IC_RESULT (ic))
13098 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
13100 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
13102 if (IC_RESULT (ic))
13103 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13106 /*-----------------------------------------------------------------*/
13107 /* genEndCritical - generate code for end of a critical sequence */
13108 /*-----------------------------------------------------------------*/
13110 genEndCritical (iCode *ic)
13112 D(emitcode("; genEndCritical",""));
13116 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
13117 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
13119 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
13120 emitcode ("mov", "ea,c");
13124 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE));
13125 emitcode ("rrc", "a");
13126 emitcode ("mov", "ea,c");
13128 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
13132 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
13133 emitcode ("mov", "ea,c");
13139 /*-----------------------------------------------------------------*/
13140 /* genBuiltIn - calls the appropriate function to generating code */
13141 /* for a built in function */
13142 /*-----------------------------------------------------------------*/
13143 static void genBuiltIn (iCode *ic)
13145 operand *bi_parms[MAX_BUILTIN_ARGS];
13150 /* get all the arguments for a built in function */
13151 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
13153 /* which function is it */
13154 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
13155 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
13156 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
13157 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
13158 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
13159 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
13160 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
13161 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
13162 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
13163 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
13164 genMemsetX(bi_iCode,nbi_parms,bi_parms);
13165 } else if (strcmp(bif->name,"__builtin_inp")==0) {
13166 genInp(bi_iCode,nbi_parms,bi_parms);
13167 } else if (strcmp(bif->name,"__builtin_outp")==0) {
13168 genOutp(bi_iCode,nbi_parms,bi_parms);
13169 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
13170 genSwapW(bi_iCode,nbi_parms,bi_parms);
13171 /* JavaNative builtIns */
13172 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
13173 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
13174 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
13175 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
13176 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
13177 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
13178 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
13179 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
13180 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
13181 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13182 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
13183 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13184 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
13185 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
13186 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
13187 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
13188 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
13189 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13190 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
13191 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13192 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
13193 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
13194 } else if (strcmp(bif->name,"MM_Malloc")==0) {
13195 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
13196 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
13197 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
13198 } else if (strcmp(bif->name,"MM_Free")==0) {
13199 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
13200 } else if (strcmp(bif->name,"MM_Deref")==0) {
13201 genMMDeref(bi_iCode,nbi_parms,bi_parms);
13202 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
13203 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
13204 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
13205 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
13206 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
13207 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
13208 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
13209 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
13210 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
13211 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
13212 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
13213 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
13214 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
13215 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
13216 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
13217 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
13218 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13219 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13220 } else if (strcmp(bif->name,"System_SaveThread")==0) {
13221 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13222 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13223 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13224 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
13225 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
13226 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
13227 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
13228 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
13229 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
13230 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
13231 genSystem(bi_iCode,nbi_parms,"ProcessYield");
13232 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
13233 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
13234 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
13235 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
13236 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
13237 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
13238 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
13239 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
13240 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
13241 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
13243 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
13249 /*-----------------------------------------------------------------*/
13250 /* gen390Code - generate code for Dallas 390 based controllers */
13251 /*-----------------------------------------------------------------*/
13253 gen390Code (iCode * lic)
13258 lineHead = lineCurr = NULL;
13259 dptrn[1][0] = "dpl1";
13260 dptrn[1][1] = "dph1";
13261 dptrn[1][2] = "dpx1";
13263 if (options.model == MODEL_FLAT24) {
13264 fReturnSizeDS390 = 5;
13265 fReturn = fReturn24;
13267 fReturnSizeDS390 = 4;
13268 fReturn = fReturn16;
13269 options.stack10bit=0;
13272 /* print the allocation information */
13273 if (allocInfo && currFunc)
13274 printAllocInfo (currFunc, codeOutFile);
13276 /* if debug information required */
13277 if (options.debug && currFunc)
13279 debugFile->writeFunction(currFunc);
13281 if (IS_STATIC (currFunc->etype))
13282 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
13284 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
13287 /* stack pointer name */
13288 if (options.useXstack)
13294 for (ic = lic; ic; ic = ic->next)
13297 if (ic->lineno && cln != ic->lineno)
13302 emitcode ("", "C$%s$%d$%d$%d ==.",
13303 FileBaseName (ic->filename), ic->lineno,
13304 ic->level, ic->block);
13307 if (!options.noCcodeInAsm) {
13308 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
13309 printCLine(ic->filename, ic->lineno));
13313 if (options.iCodeInAsm) {
13314 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
13316 /* if the result is marked as
13317 spilt and rematerializable or code for
13318 this has already been generated then
13320 if (resultRemat (ic) || ic->generated)
13323 /* depending on the operation */
13343 /* IPOP happens only when trying to restore a
13344 spilt live range, if there is an ifx statement
13345 following this pop then the if statement might
13346 be using some of the registers being popped which
13347 would destory the contents of the register so
13348 we need to check for this condition and handle it */
13350 ic->next->op == IFX &&
13351 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
13352 genIfx (ic->next, ic);
13370 genEndFunction (ic);
13390 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
13407 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
13411 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
13418 /* note these two are xlated by algebraic equivalence
13419 during parsing SDCC.y */
13420 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13421 "got '>=' or '<=' shouldn't have come here");
13425 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
13437 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
13441 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
13445 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
13469 genRightShift (ic);
13472 case GET_VALUE_AT_ADDRESS:
13473 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13477 if (POINTER_SET (ic))
13478 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13504 if (ic->builtinSEND) genBuiltIn(ic);
13505 else addSet (&_G.sendSet, ic);
13508 case DUMMY_READ_VOLATILE:
13517 genEndCritical (ic);
13524 #if 0 // obsolete, and buggy for != xdata
13536 /* now we are ready to call the
13537 peep hole optimizer */
13538 if (!options.nopeep)
13539 peepHole (&lineHead);
13541 /* now do the actual printing */
13542 printLine (lineHead, codeOutFile);